release: merge dev into main - #438
Merged
Merged
Conversation
added 30 commits
July 1, 2026 19:02
Restores full Props API (segments, totalLabel, showLegend, variant, per-segment colorClass) and the 7-color palette (bg-error was missing). Updates MediaServerStatsSection call sites to use the segments prop name. Addresses spec review findings on Batch E.
…ttern The needs-attention badges and root-folder scan-status badges used low-opacity backgrounds without borders and the wrong text color variant (text-warning-content on bg-warning/20 is unreadable in dark theme - content colors are designed for solid backgrounds). Aligns with the working pattern used in monitoring/logs, RootFolderList, LibraryList, and storage-utils getStatusBadgeClass: border-X/30 bg-X/10 text-X Adds font-medium to attention badges for better small-text readability.
Moves heightToResolution/extractResolution/extractVideoCodec/extractHdrFormat/ extractAudioCodec/extractContainer from status/media/+page.server.ts into a shared module. Adds logicalKey() helper for storage_items dedup. Phase 2 prep.
…FreeSpace Two-line extension: also calls getTotalSpace() and includes the value in the DB update. The column was added in v105 but nothing was writing to it.
Adds EventEmitter to MediaServerStatsSyncService. ReconciliationService (Phase 2) subscribes to syncComplete to re-populate storage_items after every media-server sync.
StorageItemJoined, LogicalKey, ReconcileResult. Consumed by ReconciliationService (next task) and InsightsService (Phase 3).
Shared factories for storage-domain test setup. Used by ReconciliationService integration tests next.
BackgroundService that populates storage_items and storage_item_server_links from movie_files + episode_files + media_server_synced_items, joined by tmdbId. Idempotent in-memory diff with stale cleanup. Lock-protected against concurrent runs. Subscribes to scanComplete and syncComplete events. Initial backfill runs 5s after startup. Includes integration tests using createTestDb + fixtures. Also extends clearTestDb to wipe storage/media-server tables (children-first ordering) so reconciliation tests start from a clean slate.
Service starts on app startup, subscribes to scanComplete and syncComplete events, and runs an initial backfill 5s after ready.
- Wrap reconcile writes in a transaction (single commit, atomic). Uses a synchronous better-sqlite3 transaction since async transaction callbacks throw 'Transaction function cannot return a promise' in this driver. - Per-item try/catch so one bad row doesn't abort the whole run; tracks errorCount in ReconcileResult. - Expand episode files to per-episode granularity via the episodes table join (was collapsing whole seasons to one storage_items row). - Fix linksUpserted counter (now counts both inserts and updates). - Add .catch() to lazy event subscriptions to avoid unhandled rejections. Adds errorCount to ReconcileResult. Adds per-episode and multi-server tests.
Notes the event-loop blocking behavior and the chunked-transactions mitigation path for libraries >10k items.
InsightsService (Phase 3) subscribes to this event so it runs after writes land, avoiding a race with the upstream scanComplete/syncComplete events.
StorageInsightRule interface, InsightFinding, InsightType enum (8 values), InsightSeverity, InsightScope, RuleContext.
Idempotent sync of InsightFinding[] into storage_insights. Updates existing rows preserving dismissed state, inserts new, deletes resolved non-dismissed. Transaction-wrapped for atomicity.
BackgroundService that subscribes to reconcileComplete, runs all registered rules, and upserts findings. Lock-protected. Starts with zero rules; tasks 5-12 register them via the rules barrel.
Counts items with sourceSystem='local'. Suppressed when no media servers configured. First of 8 insight rules.
Counts items with sourceSystem='server'. The inverse of MissingFromMediaServerRule.
Flags items with playCount=0 across all servers AND firstSeenAt >30 days ago. Suppressed when no media servers configured.
Detects movies with multiple movie_files rows. Queries movie_files directly since storage_items collapses to one row per logical item.
Counts unmatched_files rows. Deep-links to /library/unmatched for review.
Aggregates 4 health signals: inaccessible folders (critical), read-only (info), needs-scan (warning), libraries without root folder (warning). Uses node:fs existsSync for accessibility check.
Detects movies whose quality.resolution < profile.minResolution using RESOLUTION_ORDER ordinal comparison. Fills the gap left by the softened CutoffUnmetSpecification. For display only — does NOT trigger upgrades.
Verifies file paths via node:fs existsSync. Builds full paths by joining storage_items -> movie_files/episode_files -> movies/series -> root_folders.
HealthIssuesRule flags libraries with no root folder. Migrations seed system libraries (defaultRootFolderId IS NULL) into a fresh test DB, so the zero-findings baseline test needs to clear them for a genuinely empty DB.
Pre-existing formatting drift in a Batch B file; collapsed a chained insert to the compact form the current prettier config expects.
Admin-only manual reconcile trigger (fire-and-forget, 202 response). Registers InsightsService in ServiceManager so it starts on app startup and subscribes to reconcileComplete.
Queries storage_insights WHERE dismissedAt IS NULL, severity-sorted. Enables SSR for the InsightsPanel (no client-side fetch flash).
severityBadgeClass (matching Phase 1 fixed pattern), dismissInsight API helper, insightTypeLabel, formatBytes re-export.
- track local scanStarting/syncStarting state so buttons respond instantly on click without waiting for SSE
- change followSymlinks from true to false in LibraryWatcher chokidar config - On Synology NAS (and similar), home directory mounts typically contain symlinks to shared volumes; with followSymlinks:true, chokidar's initial directory traversal follows these into enormous or circular directory trees, pinning CPU at 100% and blocking the Node.js event loop
…ponsive under load - add setImmediate yields between scan batches in DiskScanService so HTTP requests and logging are served during large library scans - add setImmediate yield between match_unmatched pages in LibraryJobWorker - add setImmediate yield between files in processUnmatchedByRootFolder so the event loop is released between each synchronous DB + TMDB operation - add setImmediate yield between series in updateAllSeriesStats - add setImmediate yield in processLoop after each completed job before picking up the next one
…} is missing in rename preview - add missingCollectionData flag to RenamePreviewResult - RenamePreviewModal shows an alert banner with an inline Refresh Metadata button when the flag is set; clicking it calls `POST /api/library/movies/[id]/refresh` then reloads the preview
- add searchCollections() to TMDB service hitting /search/collection - extend movieUpdateSchema with tmdbCollectionId and collectionName; handle both fields in the PATCH /api/library/movies/[id] handler - add collectionName to page server load select
Adds Unraid XML template files for Community Apps listing: - ca_profile.xml: Repository metadata (author, icon, support link) - cinephage.xml: Docker container template (ports, volumes, env vars) - icon.png: 512x512 application icon Closes #423
…/vite 4.3.0->4.3.1) Closes #405
Flake lock file updates:
• Updated input 'flake-parts':
'github:hercules-ci/flake-parts/f7c1a2d' (2026-05-13)
→ 'github:hercules-ci/flake-parts/17c9d6c' (2026-07-01)
• Updated input 'flake-parts/nixpkgs-lib':
'github:nix-community/nixpkgs.lib/f590132' (2026-04-26)
→ 'github:nix-community/nixpkgs.lib/db3f255' (2026-06-28)
• Updated input 'nixpkgs':
'github:NixOS/nixpkgs/64c08a7' (2026-05-23)
→ 'github:NixOS/nixpkgs/241313f' (2026-07-19)
• Updated input 'treefmt-nix':
'github:numtide/treefmt-nix/790751f' (2026-04-08)
→ 'github:numtide/treefmt-nix/df3c064' (2026-07-18)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- show all TMDB collection parts (not just library siblings), with missing entries dimmed and grayed out - add Add Collection CTA that bulk-adds missing parts, inheriting rootFolderId and scoringProfileId from the current movie - add per-movie hover overlay with + (add) (add individually) and i (info) (Discover page) buttons - add POST /api/library/collections/[tmdbId]/track endpoint that fetches collection from TMDB, skips existing library entries, and bulk-inserts missing movies using the standard add pipeline - add contextual header buttons: search (missing-file tracked movies) and subtitle auto-download, each hidden when there is nothing to act on
…rch state - show a primary "Search in Discover" button when no movies/tv match a library search, which links to ` /discover?type=movie` or `/discover?type=tv` depending on where the search is intiated - Both links carry the current search query via ?q= so Discover loads results without the user having to retype search query
- replace filteredOutResults.length === 0 guard in debug $effect with a debugResultsLoaded flag - set debugResultsLoaded = true in the finally block after each load
- add clearAllFiles() to logHistoryService - add DELETE handler to /api/settings/logs/history
…ng manual import - resolveTvEpisodeMapping now returns episodeNumbers[] instead of a single episodeNumber - buildEpisodeNamingInfo receives the full episode array so NamingService generates the correct multi-episode filename (e.g. S01E02-E03 instead of S01E02) - add parsedEpisodes?: number[] to ManualImportDetectionData and DetectionGroup - populate from resolveTvEpisodeIdentifier when episodeNumbers.length > 1 - replace editable episode input with a read-only E1-E2 (auto) display for multi-episode files
…lder scan - add a global ffprobe concurrency semaphore (default 1, configurable via FFPROBE_CONCURRENCY env var) to prevent D-state ffprobe processes accumulating on NAS mounts where SIGKILL has no effect - change processUnmatchedByRootFolder per-file yield from setImmediate to 250ms delay, matching processAllUnmatched, to prevent back-to-back NAS I/O saturation during the match phase
- change Phase 1 complete-series filter from ?? to || so the seasons-length fallback actually runs; ?? never falls through because isCompleteSeries is always a boolean (never undefined) - remove season: startSeason from Phase 2 search criteria; passing a season caused filterBySeasonEpisode to strip multi-season packs before Phase 2's own range filter could see them - add parser tests confirming S01-S07, S01-07, and bracketed [S01-S07] in localized titles are correctly detected as complete-series packs
- fix series folder naming on add: generateSeriesFolderName wrapper in series POST handler was omitting tmdbId, imdbId, and originalTitle - fix RenamePreviewService: movie and series folder name calls missing originalTitle, collectionName (movie), and imdbId (series) - fix SmartListService: movie add/auto-add called generateMovieFolderName before fetchMovieExternalIds; reordered and added all missing fields to both movie and series add/auto-add paths - fix manual-import-service: movie and series new-folder paths missing originalTitle, imdbId, collectionName - fix LibraryDestinationPlanner: widen MoviePlanInput and EpisodePlanInput to accept originalTitle, collectionName, imdbId; pass all fields through to MediaNamingInfo in planMovie and planEpisode - fix ReadyProviderFileMapper: widen MovieContext and SeriesContext to accept originalTitle, collectionName (movie), tmdbId, imdbId (series) - fix DebridPollService: mediaContext now passes originalTitle, collectionName (movie) and originalTitle, tmdbId, imdbId (series) into the context objects consumed by ReadyProviderFileMapper - fix StrmService: widen SeriesData interface and buildMovieStrmPath / buildEpisodeStrmPath inputs to include originalTitle, collectionName, imdbId; propagate fields through all DB-to-SeriesData assignments and createStrmFileDirect's inline show object
…layout - Add metadata_language and prefer_original_title columns to movies and series (migration v126) - Add metadata refresh service that re-fetches TMDB when language override changes - Tighten edit modal layout: section headers, multi-column grids, uniform labels - Replace FormCheckbox with raw DaisyUI toggles, inline DesiredQualities as btn-xs chips - Add displayTitle() helper used across all media cards, table rows, and detail headers - Wire PATCH/GET handlers for both movies and series to accept and return new fields - Series metadata refresh cascades to episode titles/overviews - Include new fields in page server loads for movie and series detail pages
- add desktop sort button group (Score/Seeders/Size/Age + asc/desc) to SearchFilters - redesign SearchResultRow mobile layout into 3 rows: title+grab / badges / metadata - show full release title in expanded panel on mobile (truncated in header row) - release flex scroll lock on small landscape screens (height ≤600px) so the full modal scrolls as one unit rather than trapping results in a tiny sometimes not accessible view - reduce SearchHeader and SearchFilters bottom margins on mobile for a tighter header
# Conflicts: # src/lib/components/libraries/DiskUsageBar.svelte # src/lib/components/libraries/LibraryBreakdownMobileList.svelte # src/lib/components/libraries/LibraryBreakdownTable.svelte # src/lib/components/libraries/RootFolderDesktopRow.svelte # src/lib/components/libraries/StorageMaintenanceSection.svelte # src/lib/components/status/MediaServerStatsSection.svelte # src/routes/settings/general/status/+page.svelte
- Remove duplicate GITHUB_URL/DISCORD_URL declarations from +layout.svelte (merge conflict leftover) - Remove duplicate library_movieHeader_backToLibrary key from en.json (merge conflict leftover) - Fix invalid baseBranchPatterns -> baseBranches in renovate.json - Add automergeType: pr to enable Renovate automerge
Contributor
|
🎉 This PR is included in version 0.14.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
Mainup to date withDev.