Commit Graph

15 Commits

Author SHA1 Message Date
glenneth 4b6d14d47c Add system notifications for track changes
- Implement Web Notifications API in ParenScript
- Add notification toggle button (🔔/🔕) to player frame
- Show 'Artist - Track' notification when track changes
- Store notification preference in localStorage
- Auto-close notifications after 5 seconds
- Click notification to focus browser window
2026-01-18 16:50:54 +03:00
glenneth 8b6209e4e0 Add mini spectrum analyzer to player frame with theme/style sync
- Remove cross-frame audio access that was breaking audio on navigation
- Add mini spectrum visualizer to persistent player frame
- Mini analyzer syncs theme and style with main analyzer via localStorage
- Add MusicBrainz search link to player frame (updates with track changes)
- Reduce quality selector width from 140px to 55px
- Add search_url to now-playing-json API response

The main analyzer is disabled in frameset mode due to browser restrictions
on cross-frame MediaElementSource, but the mini analyzer in the player
frame provides visualization that persists across content navigation.
2026-01-11 13:25:55 -05:00
glenneth 8e60563e9d Fix stream stall reconnection failure
- Reset *is-reconnecting* flag before play attempt so error handler can
  catch failures and trigger retry with exponential backoff
- Always reconnect on stall event - ready-state check was unreliable
- Add retry logic with backoff when reconnect fails (up to 5 attempts)
- Store stalled timeout reference for proper cancellation

Fixes issue where stream would show 'Stream stalled - reconnecting...'
but never actually reconnect, requiring manual intervention.
2026-01-05 08:35:50 -05:00
Glenn Thompson 4b49f63991 fix: Normalize USERS table timestamps before dm:save to prevent PostgreSQL type errors
- Add format-timestamp-for-postgres and normalize-user-timestamps functions in database.lisp
- data-model-save now normalizes timestamp fields for USERS table before saving
- Fix authenticate-user to use data-model-save instead of dm:save directly
- Add global auth state in auth-ui.lisp for other scripts to check login status
- Add auth checks in front-page.lisp and stream-player.lisp to skip API calls when not logged in
- Fix ParenScript parentheses structure in stream-player.lisp DOMContentLoaded handler

Fixes password reset, role update, and last-login update failures caused by
integer timestamps being sent to PostgreSQL TIMESTAMP columns.
2025-12-29 09:39:51 -05:00
glenneth ccce10db50 feat: Sync favorites between front page and frame player via postMessage 2025-12-28 09:58:33 -05:00
glenneth 116d9ceebf fix: Favorites star UI and track-id lookup
- Fix find-track-by-title to parse 'Artist - Title' format from Icecast
  and search both artist and title columns in tracks table
- Fix favorites API alist key mismatch (TRACK-TITLE not TRACK_TITLE)
- Fix favorites cache to update UI after loading
- Fix race condition where star reverted after clicking
- Add aget-profile helper for Postmodern uppercase key lookup
2025-12-27 20:06:37 +03:00
glenneth 02e585bd5b feat: Custom user playlists with submission and admin review
- Add user playlist creation, editing, and track management
- Add library browser for adding tracks to playlists
- Add playlist submission workflow for station airing
- Add admin review interface with preview, approve, reject
- Generate M3U files on approval in playlists/user-submissions/
- Include user-submissions in playlist scheduler dropdown
- Use playlist description as PHASE tag in M3U
- Add database migration for user_playlists table
- Update TODO-next-features.org to mark feature complete
2025-12-21 18:45:35 +03:00
glenneth 7600ea6bed feat: Add listening history tracking and fix favorites
Listening History:
- Auto-record tracks when they change (logged-in users only)
- Track stored by title (no tracks table dependency)
- Profile page shows real recent tracks, top artists, listening stats
- APIs: /api/asteroid/user/history, /user/listening-stats, /user/recent-tracks, /user/top-artists

Favorites Fixes:
- Remove favorite now uses title instead of track-id
- Fixed response parsing to show green success message
- Profile page remove button works correctly

Migration Script Updated:
- track_title column added to both tables
- track-id now optional (nullable)
- Unique index on (user-id, track_title)
- No foreign key to tracks table (title-based storage)

For production: run migrations/005-user-favorites-history.sql
2025-12-21 08:35:35 +03:00
glenneth 5225a07b8b feat: Add track favorites feature with star button
- Add user_favorites and listening_history database tables
- Add migration 005-user-favorites-history.sql
- Create user-profile.lisp with favorites/history API endpoints
- Add star button (☆/★) to Now Playing on main page
- Add star button to frame player bar
- Add Favorites section to profile page
- Show login prompt when unauthenticated user clicks star
- Use gold color (#ffcc00) for favorited state (space theme)
- Fix require-authentication to properly detect API routes
- Support title-based favorites (no track DB required)
2025-12-21 08:15:52 +03:00
glenneth bc7da82d84 Fix playlist display polling and add footer links
- Add /api/asteroid/channel-name endpoint for live channel name updates
- Update front-page.js and stream-player.js to poll server for channel name
  instead of relying on localStorage (fixes issue where listeners don't see
  playlist changes until page refresh)
- Add footer with Internet Radio directory link and craftering webring links
- Fix last-login display bug: use proper ISO 8601 timestamp format and
  parse as Date string instead of Unix epoch
2025-12-19 18:00:30 -05:00
Glenn Thompson cb76c02e63 Remove debug logging from channel name update code 2025-12-14 19:08:41 -05:00
Glenn Thompson 987d01beaa Dynamic channel name updates and playlist crossfade transition
- Fix channel name not updating in frame player when playlist changes
- Use localStorage polling (2s interval) for cross-frame communication
- Fix API response access: use bracket notation for 'channel-name' property
- Add skip command after playlist load to trigger crossfade to new playlist
- Add #PHASE metadata to Asteroid-Low-Orbit.m3u playlist
2025-12-14 19:08:41 -05:00
Glenn Thompson 93140f8f24 Add channel/quality selector separation with dynamic playlist phase names
- Separate Channel selector (Curated/Shuffle) from Quality selector (bitrate)
- Add channel selector to frame player, front page, and popout player
- Dynamic curated channel name from playlist #PHASE: metadata
- Channel selection syncs across all player contexts via localStorage
- Quality selector disabled when Shuffle channel selected (fixed bitrate)
- Fix reconnectStream to use channel-aware config
- Consistent CSS styling for selector heights
2025-12-14 19:08:41 -05:00
Glenn Thompson 4f1a60328b Add shuffle stream mount with separate recently-played tracking
- Add shuffle source to Liquidsoap config (96kbps MP3)
- Add shuffle option to all UI quality selectors (frame, popout, front page)
- Make now-playing APIs mount-aware for correct metadata display
- Implement separate recently-played lists for curated vs shuffle streams
- Speed up now-playing and recently-played refresh on stream change
- Fix clean shutdown of stats polling thread (positional timeout arg)
- Widen quality selector dropdown for shuffle label
2025-12-14 14:02:01 -05:00
Glenn Thompson 1467df7d14 Fix geo stats peak tracking and migrate inline JS to ParenScript
- Fix listener_count accumulation bug: use GREATEST() instead of + to track
  peak concurrent listeners per day rather than cumulative count
- Migrate all inline JavaScript from templates to ParenScript:
  - admin.ctml: listener stats, geo stats, password reset -> admin.lisp
  - audio-player-frame.ctml: stream player logic -> stream-player.lisp (new)
  - popout-player.ctml: popout player logic -> stream-player.lisp (shared)
  - frameset-wrapper.ctml: frame-busting -> frameset-utils.lisp (new)
  - profile.ctml: removed redundant inline init (already in profile.lisp)
- Fix API route detection: handle URIs with or without leading slash
- Add routes to serve new ParenScript-generated JS files
- Update ASDF system definition with new ParenScript components

Tested locally for 8+ hours with no issues.
2025-12-14 10:20:32 -05:00