From e6df2aadb81cfcc879f097578273c1a18b0e171e Mon Sep 17 00:00:00 2001 From: Danny Date: Tue, 8 Sep 2026 22:23:05 -0700 Subject: [PATCH] Bugs Be Ghosty --- .../components/recordings/dashcam_routes.js | 38 +-- .../the_galaxy/assets/mobile/css/material.css | 237 +++++++++++++++++- .../assets/mobile/js/views/Recordings.js | 102 +++++--- .../tests/test_dashcam_routes_helpers.py | 4 +- starpilot/system/the_galaxy/utilities.py | 13 +- 5 files changed, 323 insertions(+), 71 deletions(-) diff --git a/starpilot/system/the_galaxy/assets/components/recordings/dashcam_routes.js b/starpilot/system/the_galaxy/assets/components/recordings/dashcam_routes.js index 749697c7ea..8113b4ade7 100644 --- a/starpilot/system/the_galaxy/assets/components/recordings/dashcam_routes.js +++ b/starpilot/system/the_galaxy/assets/components/recordings/dashcam_routes.js @@ -361,30 +361,6 @@ async function openOverlay(route) { let upgradeTimer = null let isUpgrading = false - const clearDeferredNativeControls = video => { - if (typeof video._dashcamControlsCleanup === "function") video._dashcamControlsCleanup() - } - const setNativeControls = (video, enabled) => { - clearDeferredNativeControls(video) - video.controls = enabled - } - const deferNativeControlsUntilInteraction = video => { - clearDeferredNativeControls(video) - video.controls = false - - const restore = () => { - if (video !== activeVideo || !overlay) return - setNativeControls(video, true) - } - const events = ["pointermove", "pointerdown", "focus"] - const cleanup = () => { - events.forEach(eventName => video.removeEventListener(eventName, restore)) - delete video._dashcamControlsCleanup - } - video._dashcamControlsCleanup = cleanup - events.forEach(eventName => video.addEventListener(eventName, restore)) - } - const setPlayerMessage = (message, isError = false) => { playerState.textContent = message playerState.hidden = !message @@ -412,7 +388,7 @@ async function openOverlay(route) { upgradeController = null stagingVideo.pause() stagingVideo.removeAttribute("src") - setNativeControls(stagingVideo, false) + stagingVideo.controls = false stagingVideo.load() } @@ -479,12 +455,13 @@ async function openOverlay(route) { activeVideo.classList.remove("active") activeVideo.classList.add("staging") - setNativeControls(activeVideo, false) + activeVideo.controls = false stagingVideo.classList.remove("staging") stagingVideo.classList.add("active") - if (isPlaying) deferNativeControlsUntilInteraction(stagingVideo) - else setNativeControls(stagingVideo, true) + // Keep native controls enabled across the quality swap so touch browsers + // can reveal them again after their normal auto-hide. + stagingVideo.controls = true const oldActive = activeVideo activeVideo = stagingVideo @@ -590,11 +567,11 @@ async function openOverlay(route) { stagingVideo.removeAttribute("src") stagingVideo.classList.remove("active") stagingVideo.classList.add("staging") - setNativeControls(stagingVideo, false) + stagingVideo.controls = false activeVideo.classList.remove("staging") activeVideo.classList.add("active") - setNativeControls(activeVideo, true) + activeVideo.controls = true activeVideo.src = cameraVideoUrl(segmentUrl, camera, showingPreview ? "low" : undefined) activeVideo.load() if (autoplay) activeVideo.play().catch(() => {}) @@ -768,7 +745,6 @@ function closeOverlay() { document.removeEventListener("keydown", overlay._closeOnEscape) const videos = overlay.querySelectorAll("video") videos.forEach(v => { - v._dashcamControlsCleanup?.() v.pause() v.removeAttribute("src") v.load() diff --git a/starpilot/system/the_galaxy/assets/mobile/css/material.css b/starpilot/system/the_galaxy/assets/mobile/css/material.css index d3c3715183..b20f92e731 100644 --- a/starpilot/system/the_galaxy/assets/mobile/css/material.css +++ b/starpilot/system/the_galaxy/assets/mobile/css/material.css @@ -733,6 +733,8 @@ ul { list-style: none; margin: 0; padding: 0; } white-space: nowrap; } +.gx-row__actions { align-self: flex-end; display: flex; flex-wrap: wrap; gap: 6px; } + .gx-row.disabled .gx-row__label, .gx-row.disabled .gx-row__desc { opacity: 0.45; } .gx-row--favorites { align-items: stretch; flex-direction: column; } .gx-row--favorites .gx-row__info { flex: none; } @@ -974,6 +976,8 @@ input[type="color"].gx-color { .gx-btn--danger:hover { background: #ff6b8b; } [data-theme="light"] .gx-btn--danger:hover { background: #e04b6f; } +.gx-btn--icon { min-height: 36px; min-width: 36px; padding: 0; } + .gx-tabs { display: flex; flex-wrap: wrap; @@ -1083,6 +1087,20 @@ input[type="color"].gx-color { padding: 3px 10px; } +button.gx-chip { + -webkit-appearance: none; + appearance: none; + background: var(--surface-container-high); + border: 1px solid var(--glass-border); + color: var(--on-surface-variant); + cursor: pointer; + font-family: var(--font-body); +} + +button.gx-chip:hover { + background: var(--glass-bg-hover); +} + .gx-chip--advanced { background: rgba(255, 184, 101, 0.18); border: 1px solid var(--warning); @@ -1300,7 +1318,7 @@ input[type="color"].gx-color { sibling of gx-sheet so confirm dialogs keep their centered look. */ .gx-scrim--bottomsheet { align-items: flex-end; - padding: var(--sp-4) 0 calc(var(--bottomnav-height) + var(--sp-3)); + padding: var(--sp-4) 0 0; } .gx-scrim--bottomsheet .gx-sheet { @@ -1372,7 +1390,224 @@ input[type="color"].gx-color { display: block; margin: 0 auto; max-height: 48dvh; + /* Give native controls their own stacking layer above the sheet background. */ + position: relative; width: 100%; + z-index: 1; +} + +.gx-video-segment-controls { + align-items: center; + display: flex; + gap: var(--sp-2); + justify-content: center; +} + +.gx-video-segment-select { + flex: 0 1 240px; +} + +/* Custom dropdown standing in for a native