fix: switch overlay dismissal and port dropdown selection persistence
All checks were successful
CI / fmt (push) Successful in 34s
CI / check (push) Successful in 1m14s
CI / clippy (push) Successful in 1m19s
Publish / frontend (push) Successful in 52s
Publish / backend (push) Successful in 2m36s

- Overlay now reliably dismissed: use window.setTimeout and inline
  overlay hide instead of separate function that could lose DOM ref
- Minimum 1s duration to prevent flash for short hotkey sequences
- Port dropdown preserves user's selection across page refreshes
  by tracking selectedPort locally instead of always using device's
  active_port
- Prevent duplicate change listener on port select across remounts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 13:20:30 +03:00
parent 2e6f80f9ac
commit edb6853e3a

View File

@@ -56,6 +56,8 @@ export function unmountConsole() {
ws?.close()
ws = null
buttonMask = 0
inputSuspended = false
portSelectWired = false
if (containerEl) containerEl.innerHTML = ''
containerEl = null
}
@@ -157,6 +159,8 @@ function handleMessage(ev: MessageEvent) {
let portHotkeys: Record<number, string> = {}
let keyPauseDuration = 2000
let inputSuspended = false
let selectedPort = -1
let portSelectWired = false
async function loadPortList() {
try {
@@ -168,32 +172,39 @@ async function loadPortList() {
if (!select) return
select.innerHTML = ''
portHotkeys = {}
// Use locally tracked selection if we've switched, otherwise use device's active port
const activePort = selectedPort >= 0 ? selectedPort : data.active_port
for (const p of data.ports) {
const opt = document.createElement('option')
opt.value = String(p.index)
opt.textContent = p.name || `Port ${p.index + 1}`
opt.selected = p.index === data.active_port
opt.selected = p.index === activePort
select.appendChild(opt)
if (p.hotkey) portHotkeys[p.index] = p.hotkey
}
select.addEventListener('change', () => {
const port = parseInt(select.value)
switchToPort(port)
})
if (!portSelectWired) {
select.addEventListener('change', () => {
const port = parseInt(select.value)
switchToPort(port)
})
portSelectWired = true
}
} catch { /* port list optional */ }
}
function switchToPort(port: number) {
selectedPort = port
const hotkey = portHotkeys[port]
if (!hotkey || ws?.readyState !== WebSocket.OPEN) return
// Count pause tokens to calculate total switch duration
const pauseCount = (hotkey.match(/\*/g) || []).length
const totalDelay = pauseCount * keyPauseDuration + 500 // +500ms buffer
const totalDelay = (pauseCount * keyPauseDuration) + 500 // +500ms buffer
// Suspend input and show overlay
inputSuspended = true
showSwitchOverlay(totalDelay)
const duration = Math.max(totalDelay, 1000)
showSwitchOverlay(duration)
// Send the hotkey sequence
const messages = parseHotkey(hotkey)
@@ -209,11 +220,12 @@ function switchToPort(port: number) {
}).catch(() => {})
// Resume input after the switch completes
setTimeout(() => {
window.setTimeout(() => {
inputSuspended = false
hideSwitchOverlay()
const overlay = document.getElementById('switch-overlay')
if (overlay) overlay.hidden = true
document.getElementById('canvas')?.focus()
}, totalDelay)
}, duration)
}
function showSwitchOverlay(duration: number) {
@@ -245,11 +257,6 @@ function showSwitchOverlay(duration: number) {
tick()
}
function hideSwitchOverlay() {
const overlay = document.getElementById('switch-overlay')
if (overlay) overlay.hidden = true
}
// ---------------------------------------------------------------------------
// Input handlers
// ---------------------------------------------------------------------------