mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-18 05:23:57 +08:00
backpack
This commit is contained in:
Binary file not shown.
@@ -318,6 +318,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"DeveloperSidebarMetric7", {PERSISTENT, INT, "7", "0", 3}},
|
||||
{"DeveloperUI", {PERSISTENT, BOOL, "0", "0", 3}},
|
||||
{"GalaxyDeveloperMode", {PERSISTENT | DONT_LOG, BOOL, "0", "0", 0, SETTINGS_SIMPLE}},
|
||||
{"GalaxyDeviceName", {PERSISTENT | DONT_LOG, STRING, "", "", 0}},
|
||||
{"GalaxyMobileDefault", {PERSISTENT | DONT_LOG, BOOL, "1", "1", 0, SETTINGS_SIMPLE}},
|
||||
{"DeveloperWidgets", {PERSISTENT, BOOL, "1", "0", 3}},
|
||||
{"DeviceManagement", {PERSISTENT, BOOL, "1", "0", 1, SETTINGS_SIMPLE}},
|
||||
|
||||
Binary file not shown.
@@ -1285,6 +1285,12 @@ button.gx-chip:hover {
|
||||
|
||||
.gx-drawer.open { transform: translateX(0); }
|
||||
|
||||
.gx-drawer.open ~ .liquid-glass-nav {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateX(-50%) translateY(12px) translateZ(0);
|
||||
}
|
||||
|
||||
.gx-drawer__header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
@@ -1845,6 +1851,18 @@ button.gx-chip:hover {
|
||||
color: var(--on-surface);
|
||||
}
|
||||
|
||||
.gx-device-picker__editor button:disabled {
|
||||
cursor: wait;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.gx-device-picker__error {
|
||||
color: var(--error);
|
||||
font-size: var(--fs-xs);
|
||||
line-height: 1.4;
|
||||
margin-top: var(--sp-2);
|
||||
}
|
||||
|
||||
.gx-scrim {
|
||||
align-items: center;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
@@ -2373,6 +2391,7 @@ button.gx-chip:hover {
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.liquid-glass-nav { display: flex; }
|
||||
.gx-drawer { padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px)); }
|
||||
.gx-back-btn { display: inline-flex; }
|
||||
.gx-appbar__search { flex: 1; min-width: 0; }
|
||||
.gx-status-pill { display: none; }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const SLUG_RE = /^[A-Za-z0-9]{16}$/
|
||||
const DEVICE_NAMES_KEY = "galaxy-device-names"
|
||||
const MAX_NAME_LENGTH = 40
|
||||
|
||||
export const DevicePicker = {
|
||||
@@ -8,9 +7,10 @@ export const DevicePicker = {
|
||||
return {
|
||||
devices: [],
|
||||
activeSlug: "",
|
||||
customNames: {},
|
||||
draftName: "",
|
||||
editingSlug: "",
|
||||
renameError: "",
|
||||
saving: false,
|
||||
loading: true,
|
||||
}
|
||||
},
|
||||
@@ -18,30 +18,10 @@ export const DevicePicker = {
|
||||
hasMultipleDevices() { return this.devices.length > 1 },
|
||||
},
|
||||
methods: {
|
||||
loadCustomNames() {
|
||||
try {
|
||||
const saved = JSON.parse(localStorage.getItem(DEVICE_NAMES_KEY) || "{}")
|
||||
if (saved && typeof saved === "object" && !Array.isArray(saved)) {
|
||||
this.customNames = Object.fromEntries(Object.entries(saved).filter(([slug, name]) => (
|
||||
SLUG_RE.test(slug) && typeof name === "string" && name.trim()
|
||||
)))
|
||||
}
|
||||
} catch (error) {
|
||||
this.customNames = {}
|
||||
}
|
||||
},
|
||||
saveCustomNames() {
|
||||
try {
|
||||
localStorage.setItem(DEVICE_NAMES_KEY, JSON.stringify(this.customNames))
|
||||
} catch (error) {
|
||||
// Private browsing can disable localStorage; the current name still works.
|
||||
}
|
||||
},
|
||||
displayName(device, index) {
|
||||
return this.customNames[device.slug] || device.name || `Comma ${index + 1}`
|
||||
return device.name || `Comma ${index + 1}`
|
||||
},
|
||||
async loadDevices() {
|
||||
this.loadCustomNames()
|
||||
try {
|
||||
const response = await fetch("/_gateway/devices", { cache: "no-store" })
|
||||
if (!response.ok) return
|
||||
@@ -59,6 +39,7 @@ export const DevicePicker = {
|
||||
startRename(device, index) {
|
||||
this.editingSlug = device.slug
|
||||
this.draftName = this.displayName(device, index)
|
||||
this.renameError = ""
|
||||
this.$nextTick(() => {
|
||||
const input = this.$refs.deviceNameInput
|
||||
;(Array.isArray(input) ? input[0] : input)?.focus()
|
||||
@@ -67,18 +48,28 @@ export const DevicePicker = {
|
||||
cancelRename() {
|
||||
this.editingSlug = ""
|
||||
this.draftName = ""
|
||||
this.renameError = ""
|
||||
},
|
||||
saveRename(device) {
|
||||
async saveRename(device) {
|
||||
if (!device) return
|
||||
const name = this.draftName.trim().slice(0, MAX_NAME_LENGTH)
|
||||
if (name) this.customNames = { ...this.customNames, [device.slug]: name }
|
||||
else {
|
||||
const nextNames = { ...this.customNames }
|
||||
delete nextNames[device.slug]
|
||||
this.customNames = nextNames
|
||||
this.saving = true
|
||||
this.renameError = ""
|
||||
try {
|
||||
const response = await fetch(`/_gateway/devices/${encodeURIComponent(device.slug)}/name`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name }),
|
||||
})
|
||||
const data = await response.json().catch(() => ({}))
|
||||
if (!response.ok) throw new Error(data?.error || "Could not save the comma name.")
|
||||
this.devices = this.devices.map((item) => item.slug === device.slug ? { ...item, name: data.name } : item)
|
||||
this.cancelRename()
|
||||
} catch (error) {
|
||||
this.renameError = error?.message || "Could not save the comma name."
|
||||
} finally {
|
||||
this.saving = false
|
||||
}
|
||||
this.saveCustomNames()
|
||||
this.cancelRename()
|
||||
},
|
||||
selectDevice(device) {
|
||||
if (!device?.path || device.slug === this.activeSlug) return
|
||||
@@ -114,9 +105,10 @@ export const DevicePicker = {
|
||||
<label class="gx-device-picker__editor-label" for="gx-device-name">Rename comma</label>
|
||||
<div class="gx-device-picker__editor-row">
|
||||
<input id="gx-device-name" ref="deviceNameInput" v-model="draftName" maxlength="40" autocomplete="off" autofocus />
|
||||
<button type="submit" class="gx-device-picker__save">Save</button>
|
||||
<button type="button" class="gx-device-picker__cancel" @click="cancelRename">Cancel</button>
|
||||
<button type="submit" class="gx-device-picker__save" :disabled="saving">{{ saving ? 'Saving…' : 'Save' }}</button>
|
||||
<button type="button" class="gx-device-picker__cancel" :disabled="saving" @click="cancelRename">Cancel</button>
|
||||
</div>
|
||||
<div v-if="renameError" class="gx-device-picker__error">{{ renameError }}</div>
|
||||
</form>
|
||||
</div>
|
||||
`,
|
||||
|
||||
@@ -66,13 +66,19 @@ def test_ui_index_wires_vue_and_mount_point():
|
||||
def test_ui_device_picker_uses_gateway_directory_and_preserves_local_galaxy():
|
||||
picker = _read("js/components/DevicePicker.js")
|
||||
shell = _read("js/components/AppShell.js")
|
||||
css = _read("css/material.css")
|
||||
param_keys = (REPO_ROOT / "common/params_keys.h").read_text(encoding="utf-8")
|
||||
|
||||
assert 'fetch("/_gateway/devices"' in picker
|
||||
assert "localStorage" in picker
|
||||
assert 'method: "PUT"' in picker
|
||||
assert "/name`" in picker
|
||||
assert "Rename comma" in picker
|
||||
assert "hasMultipleDevices" in picker
|
||||
assert "window.location.assign(device.path)" in picker
|
||||
assert shell.index('<DevicePicker />') > shell.index('v-for="(links, section) in NAV"')
|
||||
assert '"GalaxyDeviceName", {PERSISTENT | DONT_LOG, STRING' in param_keys
|
||||
assert "localStorage" not in picker
|
||||
assert ".gx-drawer.open ~ .liquid-glass-nav" in css
|
||||
assert "Local Galaxy instances do not have the gateway directory endpoint." in picker
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user