This commit is contained in:
firestar5683
2026-09-14 13:37:53 -05:00
parent 1d6d0cb5ba
commit 16ec6bc5c9
6 changed files with 52 additions and 34 deletions
Binary file not shown.
+1
View File
@@ -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