Commit Graph
6 Commits
Author SHA1 Message Date
peter e257e2aca0 style(frontend): Prettier config + one-time repo-wide format pass
Prettier 3 (pinned), printWidth 100, double quotes — chosen to match the existing
hand-formatting and minimise reflow. This commit is ONLY the mechanical format pass
(`prettier --write`) plus the config/ignore/scripts, isolated so it never pollutes a
feature diff. Verified behaviour-neutral: typecheck, eslint (0 errors), and vitest
all green before and after. See .git-blame-ignore-revs — `git blame` skips this sha.
2026-07-21 02:26:40 +02:00
peter 5ac30abe1f fix(deferred): close frontend UI/UX tails from the hygiene sweep
- player YB2: keepalive pagehide beacon (api.saveProgressBeacon) so the resume
  position isn't lost on F5/close within 5s of the last checkpoint (mirrors Plex).
- player YB4: bound consecutive unplayable items in auto-advance so an
  auto-advancing/loop=all queue can't spin over a run of dead videos.
- downloads B6 (client): localise structured quota/edit errors centrally in
  api.req() via localizeDetail() + Intl.NumberFormat (fixes HU/DE + decimal sep);
  + 3-locale download error strings.
- channels FB1: focusChannelToken bump so re-clicking the same channel re-seeds
  the search box; FB2: syncSubs invalidates feed/feed-count (set can change now).
- config CB2: reseed the ConfigPanel draft on a key-set dataVersion + explicit
  post-save token, so a mid-edit refetch can't clobber an in-progress edit.
- config AB3 (UI): a blank allow_empty field stores "" instead of resetting.
- admin SB2/SC2: confirm + success toast on demo-whitelist remove and deny-invite
  (+ trilingual strings); SC1: disable only the acted-on row (pendingId), not all;
  SB3: pause the 1s scheduler countdown ticker while the tab is hidden.
- messages CT4: only invalidate conversations/unread when the incoming-message
  count actually changed, not on every 20s poll; MB3 (client): react to the live
  unread ping (onUnread → invalidate); MC3: extract e2ee installKey (setup/unlock);
  CC2: hoist POLL_MS to messaging.ts; MB4: document the reload-scoped socket.
2026-07-12 05:59:25 +02:00
peter 0b2740de0f chore: Phase 1 hygiene — drop unused imports/exports/types (behavior-neutral)
Machine-baseline harvest (ruff + knip), all tsc/parse-green, no runtime change:
- backend: remove 3 unused imports (channels/playlists/youtube) via ruff; drop the
  unused `job` binding in unshare_download (keep the _own_job ownership guard call).
- frontend: remove `export` from 23 internally-used-only symbols (knip "unused
  exports") to shrink the public surface; delete 2 genuinely-dead declarations
  (PlexBrowseResult — leftover from the removed /browse route; WIDGET_TITLES —
  hardcoded English titles superseded by i18n).

Held back for a decision (unused here = possibly-unwired, NOT dead — flagged, not
removed): e2ee.lock()/clearDevice() (security primitives never wired to logout / a
"forget device" feature) and loadDefaultViewFilters (App reimplements it inline — a
DRY issue). See siftlode-ops/CODE-HYGIENE.md.
2026-07-11 04:47:08 +02:00
peter e77a7e5a08 feat(auth): per-tab account — different account per browser tab
Two tabs in one browser can now run two different signed-in accounts at once.

- The signed session cookie stays the browser's account WALLET (account_ids). Which account a
  given tab acts as is a per-tab choice held in sessionStorage and sent per-request via the
  X-Siftlode-Account header; current_user honours it only for an account already in the wallet,
  without mutating the cookie's default account. Switching accounts sets the header + reloads
  THIS tab only, instead of the old cookie-wide switch that changed every tab.
- WebSocket can't send headers, so the per-tab account rides in the ?account= query param
  (validated against the wallet).
- Logout is per-tab aware: it signs the requesting tab's active account out of the wallet
  (promoting a new default only if the removed one was the default), and the tab drops its
  override. A stale per-tab header account 401s just that tab instead of clearing the session.
- Serve index.html with Cache-Control: no-cache so a deploy's new hashed bundle is picked up
  immediately instead of the browser running a heuristically-cached stale index.html.
2026-07-01 23:43:35 +02:00
peter 44e9e33354 feat(messages): auto-open/flash dock on incoming + persist dock across reload
The live-message push now carries both parties, so an incoming message opens
that conversation's dock window if it's closed, or flashes it once if it's
already open (expanded or minimised, without disturbing the minimised state) —
only for messages from someone else, never your own echo.

Dock state (open windows + minimised state) is persisted per user, so a reload
restores exactly what was open, minimised, or closed.
2026-06-25 22:46:54 +02:00
peter 5807faf790 feat(messages): E2EE real-time messaging UI + system welcome
A Messages tab in the notification center (hidden for demo): set up secure
messaging with a passphrase (key generated + wrapped in-browser via WebCrypto,
stored non-extractable per device), unlock on other devices, then chat with
end-to-end encrypted, live-delivered messages. The server-authored Siftlode
welcome is readable before any key setup.

- lib/e2ee.ts: ECDH P-256 + HKDF + AES-GCM, PBKDF2-wrapped key, IndexedDB.
- lib/messagesSocket.ts: WebSocket client with backoff reconnect.
- Messages.tsx: key gate, conversation list with decrypted previews, directory,
  thread with client-side decrypt + encrypt-on-send. Unread feeds the nav badge.
  EN/HU/DE strings.
2026-06-25 22:05:35 +02:00