Commit Graph

148 Commits

Author SHA1 Message Date
alexei.dolgolyov cad6e8a1fe feat: redesign media browser UI
Lint & Test / test (push) Successful in 9s
- Root folder cards with hero-style layout and SVG icons
- Full-width thumbnails with aspect-ratio grid items
- List view column headers (Name, Bitrate, Duration, Size)
- Modernized breadcrumb with pill segments and overflow handling
- Proper skeleton shimmer replacing emoji hourglass on thumbnails
- Pagination shows "Showing X-Y of Z" item count
- Refined hover effects, animations, and visual hierarchy
- Download button revealed on row hover in list view
- Type badges hidden by default, shown on hover
- Localized new keys in en.json and ru.json
2026-03-29 14:59:43 +03:00
alexei.dolgolyov c9ee41ad35 feat: add media folder management from WebUI
Lint & Test / test (push) Successful in 10s
- Add media_folders_management config flag (enabled by default)
- Guard folder CRUD endpoints with 403 when management disabled
- Wire up frontend folder add/edit/delete in Settings tab
- Add per-folder availability check (for network shares)
- Show unavailable badge on offline folders in browser view
- Expose management flag via /api/health endpoint
- Add EN/RU locale keys for folder management UI
2026-03-29 14:44:03 +03:00
alexei.dolgolyov 0256be816e chore: update release notes for v0.1.1
Release / create-release (push) Successful in 3s
Lint & Test / test (push) Successful in 9s
Release / build-linux (push) Successful in 32s
Release / build-windows (push) Successful in 1m10s
v0.1.1
2026-03-28 18:53:13 +03:00
alexei.dolgolyov 5219263388 fix: port-in-use check and remove packaging dependency 2026-03-28 18:52:46 +03:00
alexei.dolgolyov 98163ea5a9 chore: update release notes and version for v0.1.1
Release / create-release (push) Successful in 5s
Lint & Test / test (push) Successful in 11s
Release / build-linux (push) Successful in 33s
Release / build-windows (push) Successful in 1m11s
2026-03-28 18:37:56 +03:00
alexei.dolgolyov 5e5e5036c0 fix: use custom icon for Windows shortcuts instead of python.exe
Lint & Test / test (push) Successful in 10s
2026-03-28 18:36:53 +03:00
alexei.dolgolyov 4f9e99e10b ci: add manual build workflow for testing artifacts
Lint & Test / test (push) Failing after 11m21s
workflow_dispatch-triggered build.yml that produces Windows
installer/portable and Linux tarball as CI artifacts without
creating a release. Trigger from Gitea UI → Actions → Run.
2026-03-27 23:44:21 +03:00
alexei.dolgolyov 81d5b0a402 ci: sparse-checkout RELEASE_NOTES.md in create-release job
Release / create-release (push) Successful in 3s
Lint & Test / test (push) Successful in 10s
Release / build-linux (push) Successful in 30s
Release / build-windows (push) Successful in 1m8s
v0.1.0
2026-03-25 23:20:00 +03:00
alexei.dolgolyov d67e61ae39 ci: embed RELEASE_NOTES.md in Gitea release body
Lint & Test / test (push) Successful in 11s
Release / create-release (push) Successful in 2s
Release / build-linux (push) Successful in 36s
Release / build-windows (push) Successful in 1m21s
2026-03-25 23:17:01 +03:00
alexei.dolgolyov e795d224a8 chore: update release notes and version for v0.1.0
Lint & Test / test (push) Successful in 19s
Release / create-release (push) Successful in 8s
Release / build-linux (push) Successful in 36s
Release / build-windows (push) Has been cancelled
2026-03-25 23:10:42 +03:00
alexei.dolgolyov d0830cbbe5 ci: use warning annotation for existing release fallback
Lint & Test / test (push) Successful in 10s
2026-03-25 23:02:46 +03:00
alexei.dolgolyov 4ef11c8f00 chore: CI/build improvements and version detection
Lint & Test / test (push) Successful in 10s
- Rename GITEA_TOKEN to DEPLOY_TOKEN in release workflow
- Extract shared version detection into build-common.sh
- Use importlib.metadata for runtime version instead of hardcoded string
- Use PEP 440 parsing (packaging lib) for update version comparison
- Add packaging>=23.0 to dependencies
- Fix update banner close button alignment (CSS)
- Update CLAUDE.md with versioning docs and frontend rebuild notes
2026-03-25 15:43:27 +03:00
alexei.dolgolyov fb56e6cdc0 feat: persist audio capture device selection to config.yaml
Release / create-release (push) Successful in 1s
Lint & Test / test (push) Successful in 9s
Release / build-linux (push) Successful in 26s
Release / build-windows (push) Successful in 1m3s
Device choice now survives server restarts. Falls back to default
if the saved device is no longer available.
2026-03-25 11:50:01 +03:00
alexei.dolgolyov ff6712620e chore: bump version to 1.0.1
Release / create-release (push) Successful in 2s
Lint & Test / test (push) Successful in 38s
Release / build-linux (push) Successful in 2m10s
Release / build-windows (push) Successful in 2m48s
2026-03-25 11:37:50 +03:00
alexei.dolgolyov 795a15cb8b feat: add update-available notification system
Lint & Test / test (push) Successful in 10s
- Abstract ReleaseProvider protocol for platform-agnostic version checking
- GiteaReleaseProvider implementation using stdlib urllib
- UpdateChecker service with periodic background checks and WS broadcast
- Persistent dismissible banner in Web UI when a new version is detected
- Health endpoint now returns cached update info
- Configurable via update_check_enabled and update_check_interval settings
- i18n support (EN/RU)
2026-03-25 11:37:09 +03:00
alexei.dolgolyov 1410a8d2cb feat: typed script parameters with validation and icon-grid selector
Release / create-release (push) Successful in 1s
Lint & Test / test (push) Successful in 10s
Release / build-linux (push) Successful in 36s
Release / build-windows (push) Successful in 1m15s
- Add ScriptParameterConfig model (string, integer, float, boolean, select types)
- Server-side validation at both define-time and execute-time
- Parameters passed as SCRIPT_PARAM_* environment variables
- Web UI parameter editor in script create/edit dialog (add/remove/reorder)
- Icon-grid selector component (ported from wled-screen-controller)
- Replace audio device dropdown with icon-grid selector
- Replace callback event dropdown with icon-grid selector
- Localization for parameter UI (en, ru)
2026-03-25 11:25:03 +03:00
alexei.dolgolyov 1c0a011342 feat: tint slider tracks with 15% accent color
Lint & Test / test (push) Successful in 9s
2026-03-24 15:59:55 +03:00
alexei.dolgolyov 2b1e09ded9 feat: add Swagger API docs button to header toolbar
Lint & Test / test (push) Successful in 9s
2026-03-24 15:58:01 +03:00
alexei.dolgolyov 415231f2f2 fix: tray restart uses python -m for reliable process respawn
Release / create-release (push) Successful in 1s
Lint & Test / test (push) Successful in 15s
Release / build-linux (push) Successful in 32s
Release / build-windows (push) Successful in 1m8s
The previous os.execv approach and console_script detection both
failed on Windows. Now restart always spawns `python -m media_server.main`
via subprocess.Popen with start_new_session, which works regardless
of how the server was originally started.
2026-03-24 15:26:14 +03:00
alexei.dolgolyov 32e2ff532d fix: add --only-binary to pip download fallback (CI compatibility)
Lint & Test / test (push) Successful in 9s
Release / create-release (push) Successful in 1s
Release / build-linux (push) Successful in 37s
Release / build-windows (push) Successful in 1m15s
2026-03-24 15:07:33 +03:00
alexei.dolgolyov 309f547a5e feat: add default MDI icons to example config scripts
Lint & Test / test (push) Successful in 9s
2026-03-24 15:07:09 +03:00
alexei.dolgolyov 402183765c fix: tray main-thread message loop, numpy <2.0 pin, installer config copy
Lint & Test / test (push) Successful in 9s
Release / create-release (push) Successful in 1s
Release / build-windows (push) Failing after 30s
Release / build-linux (push) Successful in 35s
- Rewrite tray to run on main thread (pystray owns message loop, uvicorn
  in background thread) — fixes unresponsive confirmation dialogs
- Use native Windows MessageBoxW instead of tkinter (embedded Python
  has no tkinter)
- Pin numpy <2.0 to fix soundcard's numpy.fromstring (removed in 2.0)
- Strip transitive numpy 2.x wheels in build script
- Installer copies config.example.yaml as config.yaml on fresh install
- Suppress noisy screen_brightness_control warnings
2026-03-24 15:05:36 +03:00
alexei.dolgolyov d7e10b1005 fix: interpolate tag in release body template (f-string)
Lint & Test / test (push) Successful in 10s
Release / create-release (push) Successful in 1s
Release / build-linux (push) Successful in 33s
Release / build-windows (push) Successful in 1m8s
2026-03-24 14:26:14 +03:00
alexei.dolgolyov 3f14512e5d feat: add Restart and Shutdown tray actions with confirmation dialogs
Lint & Test / test (push) Successful in 24s
Release / create-release (push) Successful in 1s
Release / build-linux (push) Successful in 31s
Release / build-windows (push) Successful in 1m13s
2026-03-24 14:19:15 +03:00
alexei.dolgolyov 26b5f74c24 feat: improve installer with custom icon, launch-after-install, and running-instance detection
Lint & Test / test (push) Successful in 9s
- Use custom icon.ico for installer/uninstaller UI
- LaunchApp opens server then browser after install
- .onInit detects running instance and offers to stop it
- Use WMIC-based process kill targeting embedded Python path
- start-hidden.vbs prefers embedded Python over system Python
- Add pystray dependency to build script
- CLAUDE.md: note to consult CI/CD guide for build changes
2026-03-24 12:48:31 +03:00
alexei.dolgolyov 1f6e4f6d55 feat: add Launch option to installer finish page
Lint & Test / test (push) Successful in 9s
2026-03-23 14:05:57 +03:00
alexei.dolgolyov 6500d6f615 feat: add system tray icon with Show UI and Exit actions
Lint & Test / test (push) Successful in 9s
Adds pystray-based tray icon (green play button) that runs alongside
uvicorn. Double-click opens the web UI in the browser, Exit triggers
graceful shutdown. Disabled with --no-tray flag for headless/service mode.
2026-03-23 14:05:13 +03:00
alexei.dolgolyov 4d1bb78c83 feat: make authentication optional — no tokens = no auth
Lint & Test / test (push) Successful in 10s
When no api_tokens are configured (the new default), all endpoints
are accessible without authentication. The frontend detects this
via /api/health's auth_required field and skips the login form.

- Backend: auth.py skips verification when api_tokens is empty
- Frontend: shared getAuthHeaders()/hasCredentials() helpers replace
  scattered token logic across all JS modules
- Health endpoint exposes auth_required for frontend discovery
- config.example.yaml ships with tokens commented out
- CLI --show-token and startup log reflect disabled state

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 13:59:55 +03:00
alexei.dolgolyov f80f6e9299 fix: correct ._pth path in Windows build script
Lint & Test / test (push) Successful in 10s
Release / create-release (push) Successful in 2s
Release / build-linux (push) Successful in 35s
Release / build-windows (push) Successful in 1m28s
..\..\app was resolving two levels up from python/ dir instead of one.
Changed to ..\app so embedded Python finds the media_server package.
2026-03-23 13:35:17 +03:00
alexei.dolgolyov 02168519b7 docs: comprehensive README update with all API endpoints and features
Lint & Test / test (push) Successful in 9s
- Add display control API endpoints and monitor response schema
- Add header links section with CRUD API and configuration
- Add visualizer API endpoints (status, devices, device selection)
- Add album artwork endpoint documentation
- Add audio devices endpoint
- Add script/callback CRUD endpoints (create, update, delete)
- Add browser folder management CRUD endpoints
- Add play-folder and download endpoints
- Add WebSocket protocol documentation (all message types)
- Add full config.yaml example with all sections
- Document Dynamic WebGL background feature
- Fix all markdown lint warnings (duplicate headings, table alignment,
  missing code fence languages, blank lines around fences)
2026-03-23 02:33:03 +03:00
alexei.dolgolyov c76ffb9997 fix: handle existing release in create-release job
Lint & Test / test (push) Successful in 9s
Release / create-release (push) Successful in 1s
Release / build-linux (push) Successful in 25s
Release / build-windows (push) Successful in 58s
If the Gitea release already exists for a tag (e.g. from a retried
workflow), fall back to fetching the existing release ID instead of
failing with KeyError.
2026-03-23 02:24:50 +03:00
alexei.dolgolyov ddd8788701 Add Linux build to release workflow, fix pytest exit code 5
Lint & Test / test (push) Successful in 10s
Release / create-release (push) Failing after 1s
Release / build-windows (push) Has been skipped
Release / build-linux (push) Has been skipped
- Add build-dist-linux.sh: venv-based tarball with systemd installer
- Add build-linux job to release.yml (parallel with build-windows)
- Include Linux download in release body
- Allow pytest to pass when no tests are collected (exit code 5)
2026-03-23 02:04:06 +03:00
alexei.dolgolyov 5439af1955 Add CI/CD pipelines, NSIS installer, ES module bundling, and ruff linting
Lint & Test / test (push) Failing after 9s
Release / create-release (push) Successful in 1s
Release / build-windows (push) Successful in 59s
- Add Gitea Actions workflows: test.yml (lint + test on push/PR) and
  release.yml (build + NSIS installer + upload on v* tags)
- Add NSIS installer with optional desktop shortcut and auto-start
- Add esbuild bundler: ES module migration with IIFE bundle output
- Add build-dist-windows.sh for cross-building Windows distribution
- Fix all ruff lint errors (import sorting, unused imports, line length)
- Remove redundant scripts (start-server.bat, stop-server.bat,
  start-server-background.vbs)
- Update CLAUDE.md with CI/CD and release documentation
2026-03-23 02:01:28 +03:00
alexei.dolgolyov be48318212 Add dynamic WebGL background with audio reactivity
- WebGL shader background with flowing waves, radial pulse, and frequency ring arcs
- Reacts to captured audio data (frequency bands + bass) when visualizer is active
- Uses page accent color; adapts to dark/light theme via bg-primary blending
- Toggle button in header toolbar, state persisted in localStorage
- Cached uniform locations and color values to avoid per-frame getComputedStyle calls
- i18n support for EN/RU locales

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 01:07:46 +03:00
alexei.dolgolyov 0eca8292cb Fix loopback device status showing 'Unavailable' after change
The POST /visualizer/device response has 'success' but no 'available'
field, causing updateAudioDeviceStatus to always fall to 'Unavailable'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 15:17:13 +03:00
alexei.dolgolyov 3cfc437599 Add UI animations: dialogs, tabs, settings, browser stagger, banner pulse
- Dialog modals: scale+fade entrance/exit with animated backdrop
- Tab panels: fade-in with subtle slide on switch
- Settings sections: content slide-down on expand
- Browser grid/list items: staggered cascade entrance animation
- Connection banner: slide-in + attention pulse on disconnect
- Accessibility: prefers-reduced-motion disables all animations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:45:02 +03:00
alexei.dolgolyov a20812ec29 Add PWA support: installable standalone app with safe area handling
- Service worker, manifest, and SVG icon for PWA installability
- Root /sw.js route for full-scope service worker registration
- Meta tags: theme-color, apple-mobile-web-app, viewport-fit=cover
- Safe area insets for notched phones (container, mini-player, footer, banner)
- Dynamic theme-color sync on light/dark toggle
- Overscroll prevention and touch-action optimization
- Hide mini-player prev/next buttons on small screens
- Updated README with PWA and new feature documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:17:56 +03:00
alexei.dolgolyov 652f10fc4c Reduce visualizer latency, tighten UI paddings, fix mobile browser toolbar
- Visualizer: FPS 25→30, chunk_size 2048→1024, smoothing 0.65→0.15
- Beat effect: scale 0.03→0.04, glow range 0.5-0.8→0.4-0.8
- UI: reduce container/section paddings from 2rem to 1rem
- Source name: add ellipsis overflow for long names
- Mobile browser toolbar: use flex-wrap instead of column stack,
  hide "Items per page" label text on small screens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:35:23 +03:00
alexei.dolgolyov 3846610042 On-demand audio visualizer capture + UI fixes
- Audio capture starts only when first client subscribes,
  stops when last client unsubscribes (saves CPU/battery)
- Add lifecycle lock to AudioAnalyzer for thread-safe start/stop
- Status badge uses local visualizer state instead of server flag
- Fix script name vertical text break on narrow screens
- Fix script grid minimum column width on small viewports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:34:17 +03:00
alexei.dolgolyov 92d6709d58 Refactor monolithic app.js into 8 modular files
Split 3803-line app.js into focused modules:
- core.js: shared state, utilities, i18n, API commands, MDI icons
- player.js: tabs, theme, accent, vinyl, visualizer, UI updates
- websocket.js: connection, auth, reconnection
- scripts.js: scripts CRUD, quick access, execution dialog
- callbacks.js: callbacks CRUD
- browser.js: media file browser, thumbnails, pagination, search
- links.js: links CRUD, header links, display controls
- main.js: DOMContentLoaded init orchestrator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:34:01 +03:00
alexei.dolgolyov 9404b37f05 Codebase audit fixes: stability, performance, accessibility
- Fix CORS: set allow_credentials=False (token auth, not cookies)
- Add threading.Lock for position cache thread safety
- Add shutdown_executor() for clean ThreadPoolExecutor cleanup
- Dedicated ThreadPoolExecutors for script/callback execution
- Fix Mutagen file handle leaks with try/finally close
- Reduce idle WebSocket polling (0.5s → 2.0s when no clients)
- Add :focus-visible styles for playback control buttons
- Add aria-label to icon-only header buttons
- Dynamic album art alt text for screen readers
- Persist MDI icon cache to localStorage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 12:10:24 +03:00
alexei.dolgolyov 73a6f387e1 Add friendly media source names with brand icons
- Registry of 17 popular media apps (browsers, players, streaming)
- Substring matching resolves raw process names to friendly names
- Brand-colored SVG icons displayed inline next to source name
- Russian locale support for Yandex Music (Яндекс Музыка)
- Unknown sources fall back to .exe-stripped name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 11:03:46 +03:00
alexei.dolgolyov b11edc25b9 Redesign header as pill-shaped toolbar group
- Unified header-toolbar container with border and rounded corners
- Consistent header-btn styling for all action buttons
- Compact locale select, separator before logout icon
- Header links integrate as part of the toolbar with divider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:01:55 +03:00
alexei.dolgolyov 3d01d98da0 Style audio device select, hide mini player volume on tablet
- Native select with explicit font stack and focus glow
- Hide mini player volume section below 900px

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:10:28 +03:00
alexei.dolgolyov 4112367175 Add 3D album art rotation and vinyl desaturation effect
- Subtle oscillating Y/X rotation with perspective for depth
- Enhanced vinyl mode filter: more desaturation + sepia warmth

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:52:27 +03:00
alexei.dolgolyov 00d313daa1 Fix vinyl angle persistence on toggle, group player toggle buttons
- Save vinyl rotation angle before flipping vinylMode flag off
- Wrap vinyl + visualizer buttons in .player-toggles container
- Move margin-left:auto from individual buttons to group

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:44:48 +03:00
alexei.dolgolyov 0691e3d338 Add audio visualizer with spectrogram, beat-reactive art, and device selection
- New audio_analyzer service: loopback capture via soundcard + numpy FFT
- Real-time spectrogram bars below album art with accent color gradient
- Album art and vinyl pulse to bass energy beats
- WebSocket subscriber pattern for opt-in audio data streaming
- Audio device selection in Settings tab with auto-detect fallback
- Optimized FFT pipeline: vectorized cumsum bin grouping, pre-serialized JSON broadcast
- Visualizer config: enabled/fps/bins/device in config.yaml
- Optional deps: soundcard + numpy (graceful degradation if missing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:42:19 +03:00
alexei.dolgolyov 8a8f00ff31 Persist vinyl rotation angle across page reloads
- Save current rotation angle to localStorage every 2s and on page unload
- Restore angle on page load via CSS custom property --vinyl-offset
- Extract angle from computed transform matrix

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 21:06:20 +03:00
alexei.dolgolyov 397d38ac12 Add primary display indicator, custom accent color picker, restart script
- Detect primary monitor via Windows EnumDisplayMonitors API and show badge
- Expand accent color picker with 9 presets and custom color input
- Auto-generate hover color for custom accent colors
- Re-render accent swatches on locale change for proper i18n
- Replace restart-server.bat with PowerShell restart-server.ps1

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 16:18:18 +03:00
alexei.dolgolyov adf2d936da Consolidate tabs, Quick Access links, mini player nav, link descriptions
- Merge Scripts/Callbacks/Links tabs into single Settings tab with collapsible sections
- Rename Actions tab to Quick Access showing both scripts and configured links
- Add prev/next buttons to mini (secondary) player
- Add optional description field to links (backend + frontend)
- Add CSS chevron indicators on collapsible settings sections
- Persist section collapse/expand state in localStorage
- Fix race condition in Quick Access rendering with generation counter
- Order settings sections: Scripts, Links, Callbacks

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 15:08:09 +03:00