From 8a7946b26cddf42ec68a0f069a3bc59b164a7b5b Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Mon, 15 Jun 2026 00:17:25 -0500 Subject: [PATCH] pond --- .../the_pond/assets/components/router.js | 2 +- .../components/tools/device_settings.js | 62 ++++++++++++++----- .../system/the_pond/templates/index.html | 2 +- starpilot/system/the_pond/the_pond.py | 1 + 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/starpilot/system/the_pond/assets/components/router.js b/starpilot/system/the_pond/assets/components/router.js index 1cd94e8b3..8e4677904 100644 --- a/starpilot/system/the_pond/assets/components/router.js +++ b/starpilot/system/the_pond/assets/components/router.js @@ -1,7 +1,7 @@ import { html, reactive } from "/assets/vendor/arrow-core.js" import { createBrowserHistory, createRouter } from "/assets/vendor/remix-router-1.3.1.js" import { hideSidebar } from "/assets/js/utils.js" -import { DeviceSettings } from "/assets/components/tools/device_settings.js?v=favorite-slots-2" +import { DeviceSettings } from "/assets/components/tools/device_settings.js?v=favorite-slots-3" import { ErrorLogs } from "/assets/components/tools/error_logs.js" import { VehicleFeatures } from "/assets/components/tools/vehicle_features.js" import { GalaxyPairing } from "/assets/components/tools/galaxy.js" diff --git a/starpilot/system/the_pond/assets/components/tools/device_settings.js b/starpilot/system/the_pond/assets/components/tools/device_settings.js index af06b2c9a..73a318dab 100644 --- a/starpilot/system/the_pond/assets/components/tools/device_settings.js +++ b/starpilot/system/the_pond/assets/components/tools/device_settings.js @@ -7,6 +7,7 @@ const COLOR_UI_DEFAULTS = { PathEdgesColor: "#00ff00", PathColor: "#30ff9c", } +const FAVORITE_OPTION_COLLATOR = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" }) // Plain variables — scheduling/routing flags that must NOT be reactive let syncScheduled = false @@ -233,7 +234,7 @@ function syncInputs() { if (!slot) continue if (el.tagName === "SELECT" && field === "key") { - el.value = slot.key || "" + populateFavoriteSelect(slotIndex, el) el.disabled = !!state.favoriteSaving } else if (el.tagName === "INPUT" && field === "search") { el.value = state.favoriteFilters[slotIndex] || "" @@ -285,7 +286,7 @@ async function fetchLayoutAndParams() { state.loadingValues = true try { - const layoutRes = await fetch("/assets/components/tools/device_settings_layout.json?v=favorite-slots-2", { cache: "no-store" }) + const layoutRes = await fetch("/assets/components/tools/device_settings_layout.json?v=favorite-slots-3", { cache: "no-store" }) const rawLayoutData = await layoutRes.json() const layoutData = rawLayoutData @@ -459,13 +460,51 @@ function normalizeFavoriteSlots(slots) { return normalized } +function compareFavoriteOptions(a, b) { + const labelCompare = FAVORITE_OPTION_COLLATOR.compare(String(a?.label || a?.key || ""), String(b?.label || b?.key || "")) + if (labelCompare !== 0) return labelCompare + return FAVORITE_OPTION_COLLATOR.compare(String(a?.key || ""), String(b?.key || "")) +} + +function normalizeFavoriteOptions(options) { + if (!Array.isArray(options)) return [] + return [...options].sort(compareFavoriteOptions) +} + +function favoriteOptionMatchesFilter(option, filter) { + if (!filter) return true + const q = filter.toLowerCase() + return [option.label, option.key, option.section, option.description] + .some(value => String(value || "").toLowerCase().includes(q)) +} + +function filteredFavoriteOptions(index) { + const filter = state.favoriteFilters[index] || "" + return normalizeFavoriteOptions(state.favoriteOptions).filter(opt => favoriteOptionMatchesFilter(opt, filter)) +} + +function populateFavoriteSelect(index, selectEl = null) { + const select = selectEl || document.querySelector(`select[data-favorite-slot="${index}"][data-favorite-field="key"]`) + if (!select) return + + const slots = normalizeFavoriteSlots(state.favoriteSlots) + const selectedKey = slots[index]?.key || "" + const options = filteredFavoriteOptions(index) + select.replaceChildren() + select.appendChild(new Option("Select a toggle...", "", false, selectedKey === "")) + for (const opt of options) { + select.appendChild(new Option(opt.label, opt.key, false, selectedKey === opt.key)) + } + select.value = options.some(opt => opt.key === selectedKey) ? selectedKey : "" +} + async function fetchFavoriteSlots() { state.favoriteLoading = true try { const res = await fetch("/api/favorites/slots") const data = await res.json() if (res.ok) { - state.favoriteOptions = Array.isArray(data.options) ? data.options : [] + state.favoriteOptions = normalizeFavoriteOptions(data.options) state.favoriteSlots = normalizeFavoriteSlots(data.slots) state.favoriteValues = data.values || {} state.values = { ...state.values, ...state.favoriteValues, StarPilotFavoriteSlots: state.favoriteSlots } @@ -492,7 +531,7 @@ async function saveFavoriteSlots(slots) { const data = await res.json() if (res.ok) { - state.favoriteOptions = Array.isArray(data.options) ? data.options : state.favoriteOptions + state.favoriteOptions = Array.isArray(data.options) ? normalizeFavoriteOptions(data.options) : normalizeFavoriteOptions(state.favoriteOptions) state.favoriteSlots = normalizeFavoriteSlots(data.slots) state.favoriteValues = data.values || {} state.values = { ...state.values, ...state.favoriteValues, StarPilotFavoriteSlots: state.favoriteSlots } @@ -530,16 +569,10 @@ function updateFavoriteFilter(index, event) { const filters = Array.isArray(state.favoriteFilters) ? [...state.favoriteFilters] : ["", "", ""] filters[index] = getEventValue(event) state.favoriteFilters = filters.slice(0, 3) + populateFavoriteSelect(index) scheduleSyncInputs() } -function favoriteOptionMatchesFilter(option, filter) { - if (!filter) return true - const q = filter.toLowerCase() - return [option.label, option.key, option.section, option.description] - .some(value => String(value || "").toLowerCase().includes(q)) -} - async function updateFavoriteValue(key, checked) { const current = state.values[key] state.values = { ...state.values, [key]: checked } @@ -953,7 +986,7 @@ function renderFavoriteSlotsPanel() { } const slots = normalizeFavoriteSlots(state.favoriteSlots) - const options = state.favoriteOptions || [] + const options = normalizeFavoriteOptions(state.favoriteOptions) return html`
@@ -962,10 +995,7 @@ function renderFavoriteSlotsPanel() { const selectedKey = slot.key || "" const selectedValue = selectedKey ? !!state.values[selectedKey] : false const favoriteFilter = state.favoriteFilters[index] || "" - let filteredOptions = options.filter(opt => favoriteOptionMatchesFilter(opt, favoriteFilter)) - if (selectedOption && !filteredOptions.some(opt => opt.key === selectedOption.key)) { - filteredOptions = [selectedOption, ...filteredOptions] - } + const filteredOptions = options.filter(opt => favoriteOptionMatchesFilter(opt, favoriteFilter)) return html`
diff --git a/starpilot/system/the_pond/templates/index.html b/starpilot/system/the_pond/templates/index.html index 072e0442d..31e8d1f3a 100644 --- a/starpilot/system/the_pond/templates/index.html +++ b/starpilot/system/the_pond/templates/index.html @@ -44,7 +44,7 @@