harden: relay timeouts, DNS resolver reuse, cache hygiene + frontend polish
Server (relay/SSRF): - Bound connect+TLS+request under CONNECT_TIMEOUT and body download under BODY_TIMEOUT so a stalling upstream can't pin a relay permit indefinitely - Add inbound header_read_timeout to defeat slow-loris connections - Allowlist relayed Content-Type (fall back to octet-stream) to block content-confusion from attacker-controlled stream origins - Reuse one DNS resolver process-wide instead of rebuilding it per request (restores hickory's DNS cache; drops per-segment resolver setup) - Probe cache: random per-process hash seed (DefaultHasher was deterministic) + bounded growth with expired-entry eviction - Real Ctrl-C handler for a clean shutdown (honours the banner) - Collapse the wrap_raw no-op alias into wrap Frontend: - Guide: visible focus ring tracking arrow-key navigation - Player: buffering/tuning indicator while <video> is stalled - prefers-contrast: more pass (lifts --ink-dim to meet WCAG AA) - Service worker: date-stamped cache names so shell updates propagate Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+9
-3
@@ -112,7 +112,7 @@ export class Guide {
|
||||
|
||||
_renderRow(ch, idx) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'guide-row';
|
||||
row.className = 'guide-row' + (idx === this.focusRow ? ' focused' : '');
|
||||
row.style.position = 'absolute';
|
||||
row.style.top = (idx * ROW_H) + 'px';
|
||||
row.style.left = '0'; row.style.right = '0';
|
||||
@@ -189,12 +189,18 @@ export class Guide {
|
||||
_onKey(e) {
|
||||
const list = this.agg.channels;
|
||||
switch (e.key) {
|
||||
case 'ArrowDown': e.preventDefault(); this.focusRow = Math.min(list.length-1, this.focusRow+1); this._scrollToFocus(); break;
|
||||
case 'ArrowUp': e.preventDefault(); this.focusRow = Math.max(0, this.focusRow-1); this._scrollToFocus(); break;
|
||||
case 'ArrowDown': e.preventDefault(); this.focusRow = Math.min(list.length-1, this.focusRow+1); this._moveFocus(); break;
|
||||
case 'ArrowUp': e.preventDefault(); this.focusRow = Math.max(0, this.focusRow-1); this._moveFocus(); break;
|
||||
case 'Enter': e.preventDefault(); { const ch = list[this.focusRow]; if (ch){ this.onTune(ch); this.hide(); } } break;
|
||||
case 'Escape': e.preventDefault(); this.hide(); break;
|
||||
}
|
||||
}
|
||||
// Scroll the focused row into view, then repaint so the .focused highlight
|
||||
// tracks the cursor even when no scroll was needed (scroll event wouldn't fire).
|
||||
_moveFocus() {
|
||||
this._scrollToFocus();
|
||||
this._renderViewport();
|
||||
}
|
||||
_scrollToFocus() {
|
||||
const y = this.focusRow * ROW_H;
|
||||
if (y < this.scroll.scrollTop) this.scroll.scrollTop = y;
|
||||
|
||||
Reference in New Issue
Block a user