Commit Graph

90 Commits

Author SHA1 Message Date
b1f81eff0f Revert "perf: split into fast poll + slow-cached library fetches"
All checks were successful
Build and Push Docker Image / build (push) Successful in 24s
This reverts commit 78a8737f29.
2026-05-16 00:21:46 +01:00
78a8737f29 perf: split into fast poll + slow-cached library fetches
All checks were successful
Build and Push Docker Image / build (push) Successful in 24s
Fast poll (every cycle): SABnzbd, Sonarr/Radarr queue + history,
qBittorrent — all lightweight with no include* params.

Slow cache (5 min TTL): Sonarr series, Radarr movies, tags —
fetched only when cache expires. These rarely change.

This eliminates the 2s+ includeSeries/includeMovie joins from
every poll cycle. First poll is still slow (cold cache), but
subsequent polls should complete in <500ms.
2026-05-16 00:20:11 +01:00
d5542abd27 perf: drop includeSeries/includeMovie from history fetches
All checks were successful
Build and Push Docker Image / build (push) Successful in 23s
Sonarr/Radarr history with include* params forces expensive DB
joins (~2s each). History records still have seriesId/movieId
for matching; the series/movie objects come from the queue-built
maps instead.

Trade-off: completed downloads only show if the series/movie
is also currently in the queue. Active downloads unaffected.
2026-05-16 00:16:31 +01:00
980e20247c perf: reduce history page sizes and drop includeEpisode
All checks were successful
Build and Push Docker Image / build (push) Successful in 22s
- Sonarr/Radarr history: pageSize 20 -> 10
- SABnzbd history: limit 20 -> 10
- Drop includeEpisode from Sonarr queue and history (never rendered)
- These reduce DB join overhead and response payload size
2026-05-16 00:14:12 +01:00
ba43a3d6bd fix: crash from stale references to removed sonarrSeries/radarrMovies
All checks were successful
Build and Push Docker Image / build (push) Successful in 33s
Debug logging at line 389/393 still referenced radarrMovies.data and
sonarrSeries.data which were removed in the previous commit. Updated
to use moviesMap/seriesMap built from embedded queue/history objects.
2026-05-16 00:11:24 +01:00
b44d370b51 perf: eliminate full Sonarr Series + Radarr Movies library fetches
All checks were successful
Build and Push Docker Image / build (push) Successful in 40s
The poller was fetching the entire series and movie libraries on every
poll cycle (~9s each). Queue and history records already embed the full
series/movie object via includeSeries/includeMovie params.

Changes:
- Remove 'Sonarr Series' and 'Radarr Movies' timed fetches from poller
- Tag queue/history records with _instanceUrl in the poller instead
- Build seriesMap/moviesMap from embedded objects in dashboard
- Remove poll:sonarr-series and poll:radarr-movies cache keys
- Fix missing axios and config imports in dashboard
- Net result: ~18s saved per poll cycle, ~2 fewer API calls
2026-05-16 00:05:14 +01:00
6e81180175 feat: status page shows effective refresh mode across all active clients
All checks were successful
Build and Push Docker Image / build (push) Successful in 41s
- Server tracks each client's refresh rate via query param on /user-downloads
- Active clients expire after 30s of no requests
- Status panel 'Data Refresh' card shows:
  - Background poll interval (or Disabled)
  - Effective mode: Background if all clients >= poll rate,
    Foreground (with rate) if any client is faster, Idle if no clients
  - Active client list with per-user refresh rate and last-seen age
- Foreground mode shown with orange badge for visibility
- Client refresh rate sent on every dashboard request
2026-05-16 00:00:08 +01:00
5ae6af114e feat: live-updating status panel with per-task poll timings
All checks were successful
Build and Push Docker Image / build (push) Successful in 28s
- Each service fetch is individually timed (SABnzbd, Sonarr, Radarr, qBit)
- Status panel shows timing bar chart with ms per task and total
- Shows 'Last Poll' age that updates live
- Shows client refresh rate (1s/5s/10s/Off)
- Status panel auto-refreshes in sync with dashboard refresh cycle
- Changing refresh rate restarts the status panel refresh too
- TTL counters update live on each refresh
2026-05-15 23:58:10 +01:00
c97f232290 feat: add admin-only status page with cache stats
All checks were successful
Build and Push Docker Image / build (push) Successful in 29s
- New /api/dashboard/status endpoint (admin-only, 403 for non-admins)
- Returns server info (uptime, Node version, memory usage)
- Returns polling mode and interval
- Returns cache stats: entry count, total size, per-key breakdown
  with item count, size in KB, and TTL remaining
- Status button in admin controls header
- Collapsible status panel with grid layout
- Responsive: single column on mobile
2026-05-15 23:52:32 +01:00
6d35ce06e0 docs: add POLL_INTERVAL to README, .env.sample, and .env.example
All checks were successful
Build and Push Docker Image / build (push) Successful in 31s
- Document background polling and on-demand mode in README
- Add POLL_INTERVAL to all config examples (Docker, Compose, .env)
- New 'Background Polling' section in Features
- Sanitize leaked credentials in .env.example
2026-05-15 23:48:46 +01:00
6d6969190a feat: make background polling disablable with on-demand fallback
All checks were successful
Build and Push Docker Image / build (push) Successful in 27s
- Set POLL_INTERVAL=0, off, false, or disabled to disable background polling
- When disabled, data is fetched on-demand when a user opens the dashboard
- On-demand results cached for 30s so other users benefit from fresh data
- A user with a faster refresh rate keeps the cache warm for everyone
- When polling is enabled, behaviour is unchanged (default 5s)
2026-05-15 23:46:51 +01:00
fe73589633 perf: background poller for near-instant dashboard responses
All checks were successful
Build and Push Docker Image / build (push) Successful in 28s
- New poller.js polls all services on a configurable interval
- POLL_INTERVAL env var (default 5000ms / 5 seconds)
- All data stored in cache with TTL of 3x poll interval
- Dashboard endpoint now reads from cache only (no network calls)
- API responses are near-instant regardless of service count
- First poll runs immediately on server start
2026-05-15 23:42:38 +01:00
6baf643645 perf: reduce history page size from 100 to 20
All checks were successful
Build and Push Docker Image / build (push) Successful in 23s
- SABnzbd, Sonarr, and Radarr history now fetch 20 items instead of 100
- Only recent completions are needed for the dashboard
- Reduces response payload and serialization time
2026-05-15 23:36:43 +01:00
570eca0b82 perf: persist qBittorrent clients between requests
All checks were successful
Build and Push Docker Image / build (push) Successful in 27s
- Reuse client instances so auth cookies survive across requests
- Eliminates redundant login round-trips on every dashboard refresh
- Clients still re-authenticate automatically if session expires (403)
2026-05-15 23:35:16 +01:00
b04b52e3f1 perf: cache slow-changing data (series, movies, tags) with 60s TTL
All checks were successful
Build and Push Docker Image / build (push) Successful in 27s
- Add MemoryCache utility with get/set/invalidate/clear
- Cache Sonarr series, Sonarr tags, Radarr movies, Radarr tags
- 60-second TTL - first request fetches, subsequent requests served from cache
- Queue, history, and torrent data remain uncached (changes frequently)
- On cache hit, these 4 heavy API calls resolve instantly
2026-05-15 23:32:45 +01:00
eda9770f49 feat: show import-pending red lozenge when Sonarr/Radarr has issues
All checks were successful
Build and Push Docker Image / build (push) Successful in 23s
- Detect trackedDownloadState=importPending or status=warning/error
- Extract statusMessages and errorMessage from queue records
- Display red 'Import Pending' badge on download card header
- Hover reveals tooltip with the specific issue messages
- Visible to all users (not admin-only)
2026-05-15 23:23:25 +01:00
efa66b9fd6 feat: revise login screen with logo and smooth transition to splash
All checks were successful
Build and Push Docker Image / build (push) Successful in 25s
- Replace 'Login to Emby' heading with sofarr logo and subtitle
- Subtitle reads 'Login with your Emby credentials'
- Login form fades out smoothly before splash screen appears
- Form labels remain left-aligned within centered login box
2026-05-15 23:16:10 +01:00
fd8335b683 feat: add splash screen with logo on app load and after login
All checks were successful
Build and Push Docker Image / build (push) Successful in 29s
- Show sofarr logo splash screen while app initialises
- On page load: splash stays visible while checking auth and fetching data
- After login: splash reappears while fetching initial downloads
- Minimum 1.2s display with smooth fade-out transition
- Subtle pulse animation on the logo
2026-05-15 23:14:16 +01:00
4c1b11c3cc fix: handle Ombi-mangled tags for email-style usernames
All checks were successful
Build and Push Docker Image / build (push) Successful in 27s
- Replicate Ombi's SanitizeTagLabel logic (lowercase, replace non-alnum with hyphen, collapse, trim)
- Try exact tag match first (handles users with normal usernames)
- Fall back to sanitized comparison (handles email usernames like robcunn@live.co.uk → robcunn-live-co-uk)
- Applied to all tag matching locations
2026-05-15 21:46:43 +01:00
c6d1a7ffed feat: link series/movie titles to Sonarr/Radarr for admin users
All checks were successful
Build and Push Docker Image / build (push) Successful in 25s
- Series title links to Sonarr series page (/series/{titleSlug})
- Movie title links to Radarr movie page (/movie/{titleSlug})
- Links open in new tab, only shown for admin users
- Instance URL preserved through data aggregation for multi-instance support
2026-05-15 21:34:01 +01:00
9b0e778392 fix: show full download path (content_path) for qBittorrent
All checks were successful
Build and Push Docker Image / build (push) Successful in 20s
- Prefer content_path over save_path for qBittorrent torrents
- content_path is the full path to the single file or top-level
  folder for multi-file torrents
- save_path is just the base download directory
2026-05-15 21:29:16 +01:00
d31f108821 ci: remove arm builds, amd64 only for now
All checks were successful
Build and Push Docker Image / build (push) Successful in 28s
2026-05-15 21:14:40 +01:00
b590513f94 ci: build develop tag on every push to develop branch
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Triggers on develop branch in addition to release/* branches
- Develop pushes get tagged as :develop only
- Release pushes continue to get :version, :release, and :latest tags
2026-05-15 21:10:03 +01:00
ebb73492c4 feat: show download/target paths for admin users
- Admin users see download path (SABnzbd storage / qBittorrent save_path)
- Admin users see target path (Sonarr series folder / Radarr movie folder)
- Paths displayed in monospace font at bottom of card details
- Non-admin users unaffected (paths not sent in API response)
2026-05-15 21:07:19 +01:00
8b526aa13b Merge pull request 'ci: build multi-arch images (amd64, arm64, arm/v7)' (#2) from develop into main
Reviewed-on: #2
2026-05-15 20:55:54 +01:00
67b816cd61 ci: build multi-arch images (amd64, arm64, arm/v7)
- Add QEMU for cross-platform emulation
- Add Docker Buildx for multi-platform builds
- Build for linux/amd64, linux/arm64, linux/arm/v7
2026-05-15 20:53:37 +01:00
faaca310e9 chore: bump version to 0.1.2
All checks were successful
Build and Push Docker Image / build (push) Successful in 4m20s
Create Release / release (push) Successful in 1m47s
v0.1.2
2026-05-15 20:48:40 +01:00
0957f83411 feat: admin users can view all downloads with user badges
- Admin users (Emby IsAdministrator) see a 'Show all users' toggle
- When toggled, all tagged downloads are shown regardless of user
- Each download card shows the tagged user's name as a badge
- Non-admin users see only their own downloads (unchanged behavior)
- Backend accepts ?showAll=true query param (admin-only)
2026-05-15 20:46:56 +01:00
6463c6b3d1 docs: add docker-compose.yaml with sample configuration 2026-05-15 20:41:46 +01:00
bd9868b4e1 chore: bump version to 0.1.1
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m8s
Create Release / release (push) Successful in 1m29s
v0.1.1
2026-05-15 17:30:46 +01:00
07e5b185d7 Merge pull request 'develop' (#1) from develop into main
Reviewed-on: #1
2026-05-15 17:30:00 +01:00
6140808efb feat: compact UI with theme switcher (light/dark/mono)
- Redesign download cards to be significantly more compact
- Add CSS custom properties for theming
- Add theme switcher (Light, Dark, Mono) with localStorage persistence
- Update README with environment variable Docker deployment docs
- Update Docker Compose example to use environment: instead of volume mount
2026-05-15 17:28:48 +01:00
db89a920e4 ci: add automated release creation on tag push
All checks were successful
Create Release / release (push) Successful in 1m38s
Build and Push Docker Image / build (push) Successful in 2m14s
- Triggers on v* tags
- Generates release notes from commit log since previous tag
- Includes Docker pull command and source archive links
- Creates formal Gitea Release via akkuman/gitea-release-action
v0.1.0
2026-05-15 16:55:07 +01:00
a3dbe8b6c0 docs: add Docker deployment instructions and OCI labels
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m26s
- Add LABEL tags to Dockerfile (OCI standard + custom.hardware.requirement)
- Add dynamic version/created labels in CI workflow
- Add Docker deployment section to README with docker run, compose, and update instructions
- Registry pull source: docker.i3omb.com/sofarr
2026-05-15 16:50:50 +01:00
44055f0327 ci: remove registry login step (Distribution registry has no auth by default)
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m18s
2026-05-15 15:38:39 +01:00
70c9953a2d ci: use distribution registry at reg.i3omb.com
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
2026-05-15 15:19:15 +01:00
87f8c2d42b ci: add Dockerfile and Gitea Actions workflow for automated image builds
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Dockerfile based on node:18-alpine
- Gitea Actions workflow triggers on push to release/* branches
- Builds and pushes to Gitea container registry with version tags
2026-05-15 15:15:09 +01:00
d90908c1da chore: set version to 0.1.0 2026-05-15 15:10:00 +01:00
f500f4db3b feat: fix download-to-user matching, add cover art to downloads
- Fix seriesMap key (use Sonarr internal id, not tvdbId)
- Fix Sonarr tag resolution (use tag map like Radarr)
- Use sourceTitle for history record matching
- Fall back to embedded movie/series objects when API timeouts
- Add includeMovie/includeSeries params to queue/history API calls
- Add coverArt field to all download responses (TMDB poster URLs)
- Add cover art display to frontend download cards
- Fix user-summary route to use instance config and tag maps
2026-05-15 14:54:21 +01:00
5d04d2796b Initial commit: Media Download Dashboard with SABnzbd, Sonarr, Radarr, and Emby integration 2026-05-15 10:36:29 +01:00