Skip to content

Testing#3

Merged
DorkSoul merged 11 commits into
mainfrom
testing
May 31, 2026
Merged

Testing#3
DorkSoul merged 11 commits into
mainfrom
testing

Conversation

@DorkSoul

Copy link
Copy Markdown
Owner

No description provided.

Luke Hallinan and others added 11 commits May 31, 2026 16:58
Auth:
- Login/logout with bcryptjs password hashing and express-session
- First user created becomes admin; admin creates all other accounts
- Setup flow shown on first visit when no users exist yet
- Global fetch interceptor shows login overlay on 401

Access control:
- Admin assigns top-level media folders per user via allowedPaths
- /api/browse, /api/stream, /api/artwork, /api/metadata all require auth
- Root browse filters to user's allowed dirs; sub-path access denied if not under an allowed path

Cross-device state sync:
- Device UUID stored in localStorage; state pushed to server every 5s while playing
- On load: if another device was active within 30 min, offer to resume
- On first play: if another device is active within 5 min, offer to take over
- PUT /api/state stores queue, index, position, sort prefs, active device

Custom playlists:
- Create/rename/delete playlists; add tracks via long-press context menu
- Play full playlist or jump to individual tracks
- Stored per-user in data/playlists.json

Admin panel:
- Full-screen user management: create, edit (password/role/folders), delete
- Folder picker uses /api/browse root listing for checkbox selection

Data stored in data/ (gitignored); sessions persist via session-file-store

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cross-device sync:
- Remove resume banner — state now syncs silently on login
- Both devices auto-load same queue/track on connect (no prompt)
- Takeover banner still shown when another device is active within 30 min
- Takeover button added to fullscreen fs-extra row (shown when not active device)
- Transport buttons (prev/play/next) on non-active device send remote commands
  to the server via POST /api/command; active device polls every 3s and executes
- Active device pushes updated state after executing a command (clears it server-side)
- When another device claims active status, local audio is paused automatically
- Add POST /api/command server endpoint; PUT /api/state now always clears pendingCommand

Admin panel:
- Move '+ Add user' button above the user list so it's visible without scrolling

Username display:
- Truncate with ellipsis at 110px so long usernames don't overflow topbar on mobile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n attribute

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… eye toggle

Folder access:
- Replace flat top-level checklist with a recursive lazy-loading folder tree
- Each node has an expand (▶/▼) button that fetches subdirs on first click
- Checking any folder grants access to it and all its subdirectories
- Works for both create and edit forms

Edit user section:
- Separate 'Edit User' section with a proper h3 header
- User dropdown selector — choose any user from the list to edit
- Edit form appears below after selecting; dismiss with Cancel
- Delete button remains in the 'All Users' list

Password fields:
- All password creation/change forms now have a confirm field
- Passwords must match before the form can submit
- Eye toggle button on every password field (click to show/hide)
- Login page: eye toggle on password; confirm field shown only during setup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er button position

- Add svg[hidden] override inside .pw-eye so only one eye icon shows at a time
- Override flex-direction on .ftree-label inside admin forms so checkbox stays inline
- Defer media src loading in restore() to prevent browser "Continue playing" prompt; seek to saved position on first play
- Move fs-btn-takeover out of icon row into its own .fs-takeover row at the bottom of the fullscreen player

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ck selection

- Active device pushes position on every poll tick while playing so non-active
  devices see live progress without user interaction
- Add syncPositionDisplay() to Player so non-active devices update seek bar and
  time display from server state on each poll
- Add duration to server state (PUT /api/state) so non-active devices can
  convert seek-bar percentage to seconds without loading audio
- Intercept skip ±30s buttons in capture phase to send skip commands when another
  device is active
- Intercept seek bar change events to send seek commands to the active device
- Add loadqueue command type (server + executeCommand) so non-active devices can
  queue tracks on the active device
- Wrap Player.startQueue to redirect to active device via loadqueue command when
  another device is playing; show takeover banner so user can switch if desired
- Fix takeoverHere() to update serverState.activeDeviceId before calling loadState
  so startQueue is not erroneously redirected back during takeover

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tive devices

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add getDuration(), getPosition(), seekTo() to Player so SyncManager always
  uses the active media element (video or audio) rather than hardcoding audio
- Fix getPlayerState() to use Player.getDuration/getPosition so video position
  and duration are correctly pushed to the server
- Fix executeCommand('seek') to use Player.seekTo() so seeks land on the video
  element when a video is playing
- Fix seek bar interception to use serverState.duration (already correct for
  video) instead of document.getElementById('audio').duration
- Rewrite syncQueue to be display-only: updates title/art/metadata without
  loading any media stream, and exits video mode so the non-active device shows
  a static artwork image instead of attempting to play the video

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e devices

- Fix video unpausing then immediately re-pausing: active device was not pushing
  after executing a play command (only pushed when result was paused), so the
  next poll still saw the same pendingCommand and executed it again. Now always
  push 200ms after any command execution to clear it from the server.
- Separate the position-push path (no pending command + playing) from the
  command-execution path so they can't interfere with each other.
- Add playing boolean to server state and getPlayerState() so non-active devices
  know whether the active device is playing or paused.
- Call Player.syncPlayState(state.playing) on each poll so the play/pause button
  icon stays in sync on non-active devices.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dden attribute

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@DorkSoul
DorkSoul merged commit 3f21cfe into main May 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant