[ { "guid": "38bdb090-b763-4294-934b-b54ade4d9d6d", "name": "MediaDash", "description": "Whole-library housekeeping for Jellyfin covering movies, TV, music, audiobooks, books and comics. Finds duplicates, broken files, oversized encodes, unwanted or missing language tracks, misplaced files, ungrouped media, corrupt artwork, suspicious executables, orphaned metadata, stale content and space-heavy trickplay — then fixes them safely. Dry-run mode and a recycle bin protect your media by default.", "overview": "The one plugin a Jellyfin library owner needs.", "owner": "crackruckles", "category": "General", "imageUrl": "https://raw.githubusercontent.com/crackruckles/MediaDash/main/logo.png", "versions": [ { "version": "1.0.5.0", "changelog": "Full-scanner community stats, on-by-default opt-in, and first-run wizard layout polish. Dashboard\u0027s fix-completion popup and redownload banner now survive a plugin reload.\n\nFeatures\n- Community stats now cover every scanner MediaDash ships. 8 new scanners added to the payload, backend schema, and public views (Ungrouped, LargeTrickplay, SubtitleFonts, OrphanedDebris, CorruptNfo, HeavyTranscode, FailedTranscode, EmbeddedCoverArt) alongside the existing 10.\n- Community stats default flipped from off to on for new installs. Existing installs are unchanged; their persisted AnalyticsEnabled value wins. The first-run wizard shows the checkbox pre-ticked; untick in Settings -\u003e Safety at any time to opt out.\n- Dashboard\u0027s LastFixRun (fix-completion popup) and RedownloadWarnings (Overview banner) are now persisted to the plugin DB via a write-through wrapper. Previously both dropped on every plugin reload, so a mid-day restart made the popup or banner vanish. Rehydrated on plugin start.\n- README\u0027s community-impact table, docs/index.html impact section, and the monthly-stats GitHub Actions workflow now render rows for all 18 scanner types. docs/PRIVACY.md field table extended to match; opt-out language rewritten throughout.\n- Docs screenshots (overview, issues, history, settings) regenerated against the current UI with Blender open-movie sample data - no personal filenames or hostnames.\n\nBug fixes\n- First-run wizard \"Skip walkthrough\" now mints the anonymous install UUID when analytics is enabled. Previously, skipping the wizard left the ID empty and the reporter silently no-op\u0027d, so an on-by-default install that never completed the walkthrough never actually contributed a single row.\n- Wizard step 5 (Oversized files): \"Skip HDR files\" now sits to the right of \"Preferred GPU\" in a two-column flex row instead of stacked below the description. Both controls align to the same height.\n- Wizard step 8 (Language cleanup): the mdChipInput language pickers no longer sit taller than the emby-select controls next to them. Same 46px height rule that already applied on the Settings tab now applies inside the wizard too.\n- Wizard step 2 (Libraries): the \"Check library access\" button now uses the plugin\u0027s mdActionBtn class (rounded pill, primary accent, 44px tall) instead of Jellyfin\u0027s raw raised-button styling. Matches the rest of the plugin.\n- Wizard step 16 (Community stats): intro copy no longer starts with \"Off by default -\" and now lists every scanner in the \"What\u0027s sent\" panel.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.5/mediadash_1.0.5.zip", "checksum": "6f1bb3f2a0cc9c02eea07dc5f7676c75", "timestamp": "2026-08-20T12:37:13Z" }, { "version": "1.0.5.0", "changelog": "Full-scanner community stats, on-by-default opt-in, and first-run wizard layout polish. Dashboard\u0027s fix-completion popup and redownload banner now survive a plugin reload.\n\nFeatures\n- Community stats now cover every scanner MediaDash ships. 8 new scanners added to the payload, backend schema, and public views (Ungrouped, LargeTrickplay, SubtitleFonts, OrphanedDebris, CorruptNfo, HeavyTranscode, FailedTranscode, EmbeddedCoverArt) alongside the existing 10.\n- Community stats default flipped from off to on for new installs. Existing installs are unchanged; their persisted AnalyticsEnabled value wins. The first-run wizard shows the checkbox pre-ticked; untick in Settings -\u003e Safety at any time to opt out.\n- Dashboard\u0027s LastFixRun (fix-completion popup) and RedownloadWarnings (Overview banner) are now persisted to the plugin DB via a write-through wrapper. Previously both dropped on every plugin reload, so a mid-day restart made the popup or banner vanish. Rehydrated on plugin start.\n- README\u0027s community-impact table, docs/index.html impact section, and the monthly-stats GitHub Actions workflow now render rows for all 18 scanner types. docs/PRIVACY.md field table extended to match; opt-out language rewritten throughout.\n- Docs screenshots (overview, issues, history, settings) regenerated against the current UI with Blender open-movie sample data - no personal filenames or hostnames.\n\nBug fixes\n- First-run wizard \"Skip walkthrough\" now mints the anonymous install UUID when analytics is enabled. Previously, skipping the wizard left the ID empty and the reporter silently no-op\u0027d, so an on-by-default install that never completed the walkthrough never actually contributed a single row.\n- Wizard step 5 (Oversized files): \"Skip HDR files\" now sits to the right of \"Preferred GPU\" in a two-column flex row instead of stacked below the description. Both controls align to the same height.\n- Wizard step 8 (Language cleanup): the mdChipInput language pickers no longer sit taller than the emby-select controls next to them. Same 46px height rule that already applied on the Settings tab now applies inside the wizard too.\n- Wizard step 2 (Libraries): the \"Check library access\" button now uses the plugin\u0027s mdActionBtn class (rounded pill, primary accent, 44px tall) instead of Jellyfin\u0027s raw raised-button styling. Matches the rest of the plugin.\n- Wizard step 16 (Community stats): intro copy no longer starts with \"Off by default -\" and now lists every scanner in the \"What\u0027s sent\" panel.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.5/mediadash_1.0.5.zip", "checksum": "6f1bb3f2a0cc9c02eea07dc5f7676c75", "timestamp": "2026-08-20T12:37:13Z" }, { "version": "1.0.4.0", "changelog": "Reclaim totals now match across the plugin, heavy-transcode fixer works on well-encoded sources, SMART shows correctly on unprivileged Linux, and the History tab lets you slice failures by reason.\n\nFeatures\n- History tab\u0027s Failed filter now surfaces a \"search by reason\" dropdown listing the distinct failure reasons in your history with a count each (Permission denied, I/O error, Cross-device link, File no longer exists, etc.). Selecting one narrows the list; switching the top-level chip clears it.\n- SMART pill on the Overview drives now shows a specific hint when smartctl fails due to permissions on Linux: setcap \u0027cap_sys_rawio+ep\u0027 $(which smartctl) for native installs, --cap-add=SYS_RAWIO --device=... for Docker.\n\nBug fixes\n- Overview \"Reclaimed since install\" and History tab\u0027s summary + per-library chart now show the same number. History was summing the paginated 500-row window client-side while Overview summed the entire history server-side, causing the mismatch (e.g. 599 GB vs 8.1 GB). New /History/Stats endpoint aggregates over all history server-side; both panels source the total from it.\n- Heavy-transcode / failed-transcode fixes no longer refuse to swap when the re-encoded file is slightly larger than the original. Those fix types exist for direct-play compatibility, not disk savings — the size gate is now Quality-only, with a 30% hard cap on the transcode types to guard against misconfigured encode settings.\n- SMART pills now appear on library drives on Linux. Library-drive detection was using Path.GetPathRoot which always returns \"/\" on Linux — no library drive was ever flagged, so the SMART probe never ran there. Now uses the deepest-matching mount point via FindDriveForPath.\n- smartctl exit_status is now honoured. Non-zero exit (permission denied, unsupported device, no SMART support) returns Unknown with the actual smartctl error message, instead of being mis-interpreted as \"self-assessment FAILED\".", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.4/mediadash_1.0.4.zip", "checksum": "942e84a6a32883cecd6b97a44d993232", "timestamp": "2026-08-19T22:27:23Z" }, { "version": "1.0.4.0", "changelog": "Reclaim totals now match across the plugin, heavy-transcode fixer works on well-encoded sources, SMART shows correctly on unprivileged Linux, and the History tab lets you slice failures by reason.\n\nFeatures\n- History tab\u0027s Failed filter now surfaces a \"search by reason\" dropdown listing the distinct failure reasons in your history with a count each (Permission denied, I/O error, Cross-device link, File no longer exists, etc.). Selecting one narrows the list; switching the top-level chip clears it.\n- SMART pill on the Overview drives now shows a specific hint when smartctl fails due to permissions on Linux: setcap \u0027cap_sys_rawio+ep\u0027 $(which smartctl) for native installs, --cap-add=SYS_RAWIO --device=... for Docker.\n\nBug fixes\n- Overview \"Reclaimed since install\" and History tab\u0027s summary + per-library chart now show the same number. History was summing the paginated 500-row window client-side while Overview summed the entire history server-side, causing the mismatch (e.g. 599 GB vs 8.1 GB). New /History/Stats endpoint aggregates over all history server-side; both panels source the total from it.\n- Heavy-transcode / failed-transcode fixes no longer refuse to swap when the re-encoded file is slightly larger than the original. Those fix types exist for direct-play compatibility, not disk savings — the size gate is now Quality-only, with a 30% hard cap on the transcode types to guard against misconfigured encode settings.\n- SMART pills now appear on library drives on Linux. Library-drive detection was using Path.GetPathRoot which always returns \"/\" on Linux — no library drive was ever flagged, so the SMART probe never ran there. Now uses the deepest-matching mount point via FindDriveForPath.\n- smartctl exit_status is now honoured. Non-zero exit (permission denied, unsupported device, no SMART support) returns Unknown with the actual smartctl error message, instead of being mis-interpreted as \"self-assessment FAILED\".", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.4/mediadash_1.0.4.zip", "checksum": "942e84a6a32883cecd6b97a44d993232", "timestamp": "2026-08-19T22:27:23Z" }, { "version": "1.0.3.0", "changelog": "Post-1.0.2 UX polish: inline access probes, better Overview labels, orphan-cleanup cross-volume fallback.\n\nFeatures\n- New \"Test read / write access\" buttons under Settings → Libraries and Settings → Recycle bin. Results render inline next to each library (green ✓ readable + writable, or red ✗ with the specific error in a hover tooltip). Same probe as the first-run wizard, re-runnable any time.\n- Libraries scoping list now shows every library type MediaDash can scan (movies, TV, music, audiobooks, books, comics, mixed) with a small type label next to each. Previously filtered to movies + TV only, hiding music / books / audiobooks even though every scanner has covered those since 0.9.\n- Overview \"Reclaimed since install\" panel labels replace the older \"Space saved to date\" phrasing; per-library chart header matches.\n\nBug fixes\n- OrphanCleanupFixer no longer errors out with \"Invalid cross-device link\" when a Jellyfin metadata folder (e.g. /var/lib/jellyfin/data/collections/*) is recycled and the recycle bin lives on a different volume. Directory.Move now falls back to the verified copy → rename → delete-source helper the file path uses.\n- Errors tab no longer flashes / clears / closes user-expanded \u003cdetails\u003e when a new error arrives. loadErrors fingerprints the response (source + creation timestamp + count) and only re-renders when the entry set actually changes.\n- Redundant \"Where the savings are\" bar section removed from Overview. The reclaim panel legend has shown the same per-type bytes breakdown since 1.0.2.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.3/mediadash_1.0.3.zip", "checksum": "721f2ca4015e58700afc05ac9e024e4d", "timestamp": "2026-08-19T15:42:56Z" }, { "version": "1.0.3.0", "changelog": "Post-1.0.2 UX polish: inline access probes, better Overview labels, orphan-cleanup cross-volume fallback.\n\nFeatures\n- New \"Test read / write access\" buttons under Settings → Libraries and Settings → Recycle bin. Results render inline next to each library (green ✓ readable + writable, or red ✗ with the specific error in a hover tooltip). Same probe as the first-run wizard, re-runnable any time.\n- Libraries scoping list now shows every library type MediaDash can scan (movies, TV, music, audiobooks, books, comics, mixed) with a small type label next to each. Previously filtered to movies + TV only, hiding music / books / audiobooks even though every scanner has covered those since 0.9.\n- Overview \"Reclaimed since install\" panel labels replace the older \"Space saved to date\" phrasing; per-library chart header matches.\n\nBug fixes\n- OrphanCleanupFixer no longer errors out with \"Invalid cross-device link\" when a Jellyfin metadata folder (e.g. /var/lib/jellyfin/data/collections/*) is recycled and the recycle bin lives on a different volume. Directory.Move now falls back to the verified copy → rename → delete-source helper the file path uses.\n- Errors tab no longer flashes / clears / closes user-expanded \u003cdetails\u003e when a new error arrives. loadErrors fingerprints the response (source + creation timestamp + count) and only re-renders when the entry set actually changes.\n- Redundant \"Where the savings are\" bar section removed from Overview. The reclaim panel legend has shown the same per-type bytes breakdown since 1.0.2.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.3/mediadash_1.0.3.zip", "checksum": "721f2ca4015e58700afc05ac9e024e4d", "timestamp": "2026-08-19T15:42:56Z" }, { "version": "1.0.2.0", "changelog": "Follow-up polish on 1.0.1: fewer noisy issues, sharper reclaim numbers, more control over dashboards banners.\n\nFeatures\n- Trickplay scanner has a configurable minimum-size threshold (Settings → Trickplay space savings). Default 10 MB filters out per-clip trickplay folders that swamp libraries with many short videos; 0 disables the threshold and flags every convertible folder.\n- Recycle-bin size-warning threshold is now user-configurable (Settings → Recycle bin). Default 10 GB matches the old hardcoded value; 0 disables the banner.\n- Recycle-bin cross-volume warning dismiss button now persists across browser sessions (localStorage). Other banners stay session-scoped because their conditions self-clear.\n\nBug fixes\n- Overview \"Space you could reclaim\" panel now shows reclaimable bytes per issue type (with the file count as a muted parenthetical), and the donut is sized by bytes instead of by count so the visual is proportional to actual reclaim. Types with zero savings (Ungrouped, MissingSubtitles, Stale) are filtered out — they belong on the Issues tab, not the space-reclaim summary.\n- Progress bar wrap on the masthead now spans the full width of the scan-state line above it (was previously capped at 36em).", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.2/mediadash_1.0.2.zip", "checksum": "253e103a3ad761c2a0dc5f824583720c", "timestamp": "2026-08-19T15:26:26Z" }, { "version": "1.0.2.0", "changelog": "Follow-up polish on 1.0.1: fewer noisy issues, sharper reclaim numbers, more control over dashboards banners.\n\nFeatures\n- Trickplay scanner has a configurable minimum-size threshold (Settings → Trickplay space savings). Default 10 MB filters out per-clip trickplay folders that swamp libraries with many short videos; 0 disables the threshold and flags every convertible folder.\n- Recycle-bin size-warning threshold is now user-configurable (Settings → Recycle bin). Default 10 GB matches the old hardcoded value; 0 disables the banner.\n- Recycle-bin cross-volume warning dismiss button now persists across browser sessions (localStorage). Other banners stay session-scoped because their conditions self-clear.\n\nBug fixes\n- Overview \"Space you could reclaim\" panel now shows reclaimable bytes per issue type (with the file count as a muted parenthetical), and the donut is sized by bytes instead of by count so the visual is proportional to actual reclaim. Types with zero savings (Ungrouped, MissingSubtitles, Stale) are filtered out — they belong on the Issues tab, not the space-reclaim summary.\n- Progress bar wrap on the masthead now spans the full width of the scan-state line above it (was previously capped at 36em).", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.2/mediadash_1.0.2.zip", "checksum": "253e103a3ad761c2a0dc5f824583720c", "timestamp": "2026-08-19T15:26:26Z" }, { "version": "1.0.1.0", "changelog": "Post-1.0 UI polish and a recycle-bin config regression fix.\n\nBug fixes\n- RecycleBin path no longer requires library-adjacency. Users can point the bin at any writable location (e.g. `/mnt/media/.mediadash-recycle` as a sibling of the library for cross-volume-free moves). Only OS-reserved roots (/etc, /bin, /usr, Windows System32, etc.) are refused.\n- Errors tab: badge no longer shows a stale count (e.g. \"691\") after the tab has been cleared. The periodic status poll now delegates to loadErrors() when the user is on the Errors tab, so badge + list update from the same fetch.\n- Issues tab: badge is now sourced from the actual issue list length, so \"999+\" no longer disagrees with the visible cards.\n- Overview issue-shortcut cards now show reclaimable space (bytes / MB / GB) as the primary number, with the file count as a subtitle. Types with no space-savings info still show the raw count.\n- Progress bar activity text now spans the full width of the scan-state line above it (was capped at 36em).\n- Removed the second empty \"Subtitles\" settings card that appeared post-1.0 (SubtitleFonts controls are already folded into the SubtitleLanguage card).\n- \"Collapse all\" / \"Expand all\" button on Settings now truthfully reflects what a click will do: it excludes force-collapsed Off-mode tasks from the state check, and hides itself entirely when nothing on the page is togglable.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.1/mediadash_1.0.1.zip", "checksum": "38fd2abce5ae1e13971432af70607972", "timestamp": "2026-08-19T15:04:35Z" }, { "version": "1.0.1.0", "changelog": "Post-1.0 UI polish and a recycle-bin config regression fix.\n\nBug fixes\n- RecycleBin path no longer requires library-adjacency. Users can point the bin at any writable location (e.g. `/mnt/media/.mediadash-recycle` as a sibling of the library for cross-volume-free moves). Only OS-reserved roots (/etc, /bin, /usr, Windows System32, etc.) are refused.\n- Errors tab: badge no longer shows a stale count (e.g. \"691\") after the tab has been cleared. The periodic status poll now delegates to loadErrors() when the user is on the Errors tab, so badge + list update from the same fetch.\n- Issues tab: badge is now sourced from the actual issue list length, so \"999+\" no longer disagrees with the visible cards.\n- Overview issue-shortcut cards now show reclaimable space (bytes / MB / GB) as the primary number, with the file count as a subtitle. Types with no space-savings info still show the raw count.\n- Progress bar activity text now spans the full width of the scan-state line above it (was capped at 36em).\n- Removed the second empty \"Subtitles\" settings card that appeared post-1.0 (SubtitleFonts controls are already folded into the SubtitleLanguage card).\n- \"Collapse all\" / \"Expand all\" button on Settings now truthfully reflects what a click will do: it excludes force-collapsed Off-mode tasks from the state check, and hides itself entirely when nothing on the page is togglable.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.1/mediadash_1.0.1.zip", "checksum": "38fd2abce5ae1e13971432af70607972", "timestamp": "2026-08-19T15:04:35Z" }, { "version": "1.0.0.0", "changelog": "Features\n- Full media coverage on Jellyfin 10.11 and 12.0 from one binary: movies, TV, music, audiobooks, books, comics.\n- Ungrouped-media grouper and Corrupt-artwork scanner now fully wired into the UI (types, settings card, per-type mode).\n- ISO 639-1 (2-letter) language tags fold to ISO 639-2 via CultureInfo so \"en\" matches [\"eng\"] and single-language audio tracks stop getting flagged for removal.\n- Opportunistic 15-minute fix scheduling with idle deferral; automatic migration from legacy DailyTrigger on first boot.\n- Post-Jellyfin-12 upgrade cleanup that sweeps orphaned trickplay folders on first launch.\n- Book (EPUB / PDF / MOBI / AZW3) and comic (CBZ / CBR / CB7) integrity probes.\n- Corrupt-artwork, orphan-cleanup, trickplay-optimize, embedded-cover-art, heavy-transcode, failed-transcode and NFO-integrity scanners.\n- File browser tab (rename / move / delete / upload inside library boundaries, deletes go to the recycle bin).\n- Per-GPU picker + hardware-accelerated re-encoding (AMF / NVENC / QSV / VideoToolbox) with automatic software fallback.\n- Errors tab with copy-diagnostics-for-bug-report button.\n\nBug fixes\n- RecycleBin cross-volume moves verify copy size before deleting the source (no more silent data loss on truncated writes).\n- MoveToBin folder names carry a per-batch GUID so same-millisecond recycles no longer collide.\n- FileBrowser rename / move now return 409 on concurrent-target creation instead of silently overwriting.\n- Upload endpoint rejects oversized bodies via Content-Length pre-flight before any disk I/O; 50 GB per-file cap.\n- LibraryGuard refuses paths whose ancestor chain contains a symlink or NTFS junction.\n- RecycleBinPath must sit inside the plugin data dir or a configured library; OS-reserved roots refused.\n- SweepOrphanSidecars enumerates with reparse-point skip and re-checks each candidate before delete.\n- IsSimpleName refuses Windows reserved names (CON, PRN, AUX, NUL, COM1-9, LPT1-9) and trailing dot / space.\n- RelocateIssuePaths uses COLLATE NOCASE on the boundary match so sibling issues re-point correctly after case-varying moves on Windows.\n- PlayabilityFixer re-verify is reason-driven (audio-kind files no longer recycled on \"no-audio\" false positives; size-truncated files now actually removed).\n- TrackFixer.IsSelfReferentialSubtitle normalises both paths via Path.GetFullPath so legacy relative-path issue rows can\u0027t trick the guard.\n- MediaSorterFixer cross-volume detection works on Linux (was previously blind because Path.GetPathRoot returns \"/\").\n- MissingSubtitleFixer catches TaskCanceledException from provider network stalls without aborting the whole fix run.\n- smartctl / nvidia-smi / df invocations use ArgumentList (no shell tokenization); absolute-path resolution on Linux where possible.\n- WMI drive-letter validated before WQL interpolation.\n- BulkUpdateOpenIssueStatus chunks at 500 params; controller caps requests at 50 k IDs.\n- SmartHealthProbe stdout and stderr drained concurrently before WaitForExit (no more pipe-buffer deadlocks on large SMART payloads).\n- Diagnostics ring buffer dedup keys off a hash of the pre-truncation message; entries are replaced (not mutated) so concurrent Recent() callers can\u0027t observe torn reads.\n- AssSubtitleFile.Parse caps input at 100 MB to prevent OOM on malformed sidecars.\n- Wizard i18n guard relaxed to Math.min so partial locale translations override index-by-index instead of falling back entirely to English.\n- Retention slider in Settings now runs to 365 days (matched the wizard, no more silent 90-day cap on save).\n- Update banner no longer fires on 0.0.0.0 dev builds.\n- AnalyticsEnabled default flipped to false to match every \"off by default\" string in the UI.\n- Task-active count derived from FIX_TYPES.length (previously hardcoded \"of 15\", now correct for all 18 fix types).\n- Obsolete ScheduledFixTime config field removed.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.0/mediadash_1.0.0.zip", "checksum": "b37e1e38a7cf841c29ccb29fdb55aa01", "timestamp": "2026-08-19T14:32:54Z" }, { "version": "1.0.0.0", "changelog": "Features\n- Full media coverage on Jellyfin 10.11 and 12.0 from one binary: movies, TV, music, audiobooks, books, comics.\n- Ungrouped-media grouper and Corrupt-artwork scanner now fully wired into the UI (types, settings card, per-type mode).\n- ISO 639-1 (2-letter) language tags fold to ISO 639-2 via CultureInfo so \"en\" matches [\"eng\"] and single-language audio tracks stop getting flagged for removal.\n- Opportunistic 15-minute fix scheduling with idle deferral; automatic migration from legacy DailyTrigger on first boot.\n- Post-Jellyfin-12 upgrade cleanup that sweeps orphaned trickplay folders on first launch.\n- Book (EPUB / PDF / MOBI / AZW3) and comic (CBZ / CBR / CB7) integrity probes.\n- Corrupt-artwork, orphan-cleanup, trickplay-optimize, embedded-cover-art, heavy-transcode, failed-transcode and NFO-integrity scanners.\n- File browser tab (rename / move / delete / upload inside library boundaries, deletes go to the recycle bin).\n- Per-GPU picker + hardware-accelerated re-encoding (AMF / NVENC / QSV / VideoToolbox) with automatic software fallback.\n- Errors tab with copy-diagnostics-for-bug-report button.\n\nBug fixes\n- RecycleBin cross-volume moves verify copy size before deleting the source (no more silent data loss on truncated writes).\n- MoveToBin folder names carry a per-batch GUID so same-millisecond recycles no longer collide.\n- FileBrowser rename / move now return 409 on concurrent-target creation instead of silently overwriting.\n- Upload endpoint rejects oversized bodies via Content-Length pre-flight before any disk I/O; 50 GB per-file cap.\n- LibraryGuard refuses paths whose ancestor chain contains a symlink or NTFS junction.\n- RecycleBinPath must sit inside the plugin data dir or a configured library; OS-reserved roots refused.\n- SweepOrphanSidecars enumerates with reparse-point skip and re-checks each candidate before delete.\n- IsSimpleName refuses Windows reserved names (CON, PRN, AUX, NUL, COM1-9, LPT1-9) and trailing dot / space.\n- RelocateIssuePaths uses COLLATE NOCASE on the boundary match so sibling issues re-point correctly after case-varying moves on Windows.\n- PlayabilityFixer re-verify is reason-driven (audio-kind files no longer recycled on \"no-audio\" false positives; size-truncated files now actually removed).\n- TrackFixer.IsSelfReferentialSubtitle normalises both paths via Path.GetFullPath so legacy relative-path issue rows can\u0027t trick the guard.\n- MediaSorterFixer cross-volume detection works on Linux (was previously blind because Path.GetPathRoot returns \"/\").\n- MissingSubtitleFixer catches TaskCanceledException from provider network stalls without aborting the whole fix run.\n- smartctl / nvidia-smi / df invocations use ArgumentList (no shell tokenization); absolute-path resolution on Linux where possible.\n- WMI drive-letter validated before WQL interpolation.\n- BulkUpdateOpenIssueStatus chunks at 500 params; controller caps requests at 50 k IDs.\n- SmartHealthProbe stdout and stderr drained concurrently before WaitForExit (no more pipe-buffer deadlocks on large SMART payloads).\n- Diagnostics ring buffer dedup keys off a hash of the pre-truncation message; entries are replaced (not mutated) so concurrent Recent() callers can\u0027t observe torn reads.\n- AssSubtitleFile.Parse caps input at 100 MB to prevent OOM on malformed sidecars.\n- Wizard i18n guard relaxed to Math.min so partial locale translations override index-by-index instead of falling back entirely to English.\n- Retention slider in Settings now runs to 365 days (matched the wizard, no more silent 90-day cap on save).\n- Update banner no longer fires on 0.0.0.0 dev builds.\n- AnalyticsEnabled default flipped to false to match every \"off by default\" string in the UI.\n- Task-active count derived from FIX_TYPES.length (previously hardcoded \"of 15\", now correct for all 18 fix types).\n- Obsolete ScheduledFixTime config field removed.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v1.0.0/mediadash_1.0.0.zip", "checksum": "b37e1e38a7cf841c29ccb29fdb55aa01", "timestamp": "2026-08-19T14:32:54Z" }, { "version": "0.9.9.4", "changelog": "Bug-fix bundle over 0.9.9.3.\n\nDuplicate detector no longer flags different files with a shared prefix as duplicates. Replaced the trailing-tag whitelist (which kept missing new suffix combos users reported) with file-name-based edition detection: any variation in the filename between two TMDb-matched files yields a different edition key when 'Treat editions as duplicates' is off. Covers 100% of possible suffix combinations. Byte-identical copies with the same filename still group as duplicates. Regression: 'StarWarsCloneWars2003 - Connecting the Dots.mkv' vs 'StarWarsCloneWars2003 - Bridging the Saga.mkv' — now stays as two separate entries.\n\nJellyfin sidecar files/folders are skipped by the Duplicate scanner before grouping — no more 'theme.mp3 in show1/ is a duplicate of theme.mp3 in show2/' reports. Covers theme/themevideo/poster/backdrop/logo/etc plus extras subfolders (extras, trailers, behind the scenes, deleted scenes, featurettes, ...) and per-item extras suffixes in both compact and spaced form ('-behindthescenes' and '- Behind the scenes'). Reference: https://jellyfin.org/docs/general/server/media/movies/#extras\n\nDismiss button on issue cards renamed to 'Ignore this' — the existing behaviour already blocks that file from re-reporting, the old label was just confusing.\n\nNew: notification badges on Issues (open count, cyan), History (failed rows count, amber), and Errors tabs (unchanged).\n\nVersion scheme: feature.feature.feature.bugfix — fourth digit increments for hotfixes.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.9.4/mediadash_0.9.9.4.zip", "checksum": "116ee95ff7007406ff95062c57888d41", "timestamp": "2026-08-07T06:15:00Z" }, { "version": "0.9.9.4", "changelog": "Bug-fix bundle over 0.9.9.3.\n\nDuplicate detector no longer flags different files with a shared prefix as duplicates. Replaced the trailing-tag whitelist (which kept missing new suffix combos users reported) with file-name-based edition detection: any variation in the filename between two TMDb-matched files yields a different edition key when 'Treat editions as duplicates' is off. Covers 100% of possible suffix combinations. Byte-identical copies with the same filename still group as duplicates. Regression: 'StarWarsCloneWars2003 - Connecting the Dots.mkv' vs 'StarWarsCloneWars2003 - Bridging the Saga.mkv' — now stays as two separate entries.\n\nJellyfin sidecar files/folders are skipped by the Duplicate scanner before grouping — no more 'theme.mp3 in show1/ is a duplicate of theme.mp3 in show2/' reports. Covers theme/themevideo/poster/backdrop/logo/etc plus extras subfolders (extras, trailers, behind the scenes, deleted scenes, featurettes, ...) and per-item extras suffixes in both compact and spaced form ('-behindthescenes' and '- Behind the scenes'). Reference: https://jellyfin.org/docs/general/server/media/movies/#extras\n\nDismiss button on issue cards renamed to 'Ignore this' — the existing behaviour already blocks that file from re-reporting, the old label was just confusing.\n\nNew: notification badges on Issues (open count, cyan), History (failed rows count, amber), and Errors tabs (unchanged).\n\nVersion scheme: feature.feature.feature.bugfix — fourth digit increments for hotfixes.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.9.4/mediadash_0.9.9.4.zip", "checksum": "116ee95ff7007406ff95062c57888d41", "timestamp": "2026-08-07T06:15:00Z" }, { "version": "0.9.9.0", "changelog": "New Overview banner warns when a MediaDash re-encode gets undone by something external (typically Sonarr/Radarr redownloading a \"too-small\" file whose size dropped below the quality profile minimum, but also fires on manual recycle-bin restores or backup-restore overwrites).\n\nDetection is evidence-based, not guessed: at the end of every scan MediaDash walks the last 30 days of successful non-dry-run history entries, and for each one where the ORIGINAL is still preserved in the recycle bin, compares the file currently at the same path against the recycled original. If the current file is within 10% of the original size — i.e. the same rough size we shrank down — the shrunk copy has been replaced. Only paths meeting that concrete size-match trigger the warning. False positives are limited to genuine restores, which are also worth surfacing.\n\nThe red banner shows the filename, the shrunk-to size, the current size, and the fix date. Dismissable per browser session; reappears on the next scan if the condition still holds.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.9/mediadash_0.9.9.zip", "checksum": "270f3278ba8679956d5009aecab09e38", "timestamp": "2026-08-06T14:56:00Z" }, { "version": "0.9.9.0", "changelog": "New Overview banner warns when a MediaDash re-encode gets undone by something external (typically Sonarr/Radarr redownloading a \"too-small\" file whose size dropped below the quality profile minimum, but also fires on manual recycle-bin restores or backup-restore overwrites).\n\nDetection is evidence-based, not guessed: at the end of every scan MediaDash walks the last 30 days of successful non-dry-run history entries, and for each one where the ORIGINAL is still preserved in the recycle bin, compares the file currently at the same path against the recycled original. If the current file is within 10% of the original size — i.e. the same rough size we shrank down — the shrunk copy has been replaced. Only paths meeting that concrete size-match trigger the warning. False positives are limited to genuine restores, which are also worth surfacing.\n\nThe red banner shows the filename, the shrunk-to size, the current size, and the fix date. Dismissable per browser session; reappears on the next scan if the condition still holds.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.9/mediadash_0.9.9.zip", "checksum": "270f3278ba8679956d5009aecab09e38", "timestamp": "2026-08-06T14:56:00Z" }, { "version": "0.9.8.0", "changelog": "Two fixes and a reclaim.\n\nVAAPI hardware encodes now pass -rc_mode VBR to hevc_vaapi / h264_vaapi / av1_vaapi. Mesa VAAPI\u0027s default rate-control is CQP, which ignores -b:v/-maxrate and picks a QP that routinely produces output LARGER than a modest-bitrate source — the \"the re-encoded file would be larger than the original, so the original was kept\" retry loop that some AMD iGPU users saw every 30-70 minutes on the same file. VBR honours -b:v as the target and -maxrate as the ceiling, so the encoder actually stays under the requested bitrate.\n\nOrphan sidecar sweep: at the end of every fix run (right after the recycle bin purge), MediaDash now walks each library root and deletes any *.mediadash.tmp*, *.mediadash.new*, mediadash.tmp.*, or mediadash.new.* file it finds. These are leftovers from a hard-killed encode (SIGKILL, container restart, Jellyfin crash) where the C# finally block that normally deletes them never ran. Deleted-count + reclaimed-bytes go into Jellyfin\u0027s log.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.8/mediadash_0.9.8.zip", "checksum": "028cf3ecc7099308d0342b44fcd2aeee", "timestamp": "2026-08-06T12:26:47Z" }, { "version": "0.9.8.0", "changelog": "Two fixes and a reclaim.\n\nVAAPI hardware encodes now pass -rc_mode VBR to hevc_vaapi / h264_vaapi / av1_vaapi. Mesa VAAPI\u0027s default rate-control is CQP, which ignores -b:v/-maxrate and picks a QP that routinely produces output LARGER than a modest-bitrate source — the \"the re-encoded file would be larger than the original, so the original was kept\" retry loop that some AMD iGPU users saw every 30-70 minutes on the same file. VBR honours -b:v as the target and -maxrate as the ceiling, so the encoder actually stays under the requested bitrate.\n\nOrphan sidecar sweep: at the end of every fix run (right after the recycle bin purge), MediaDash now walks each library root and deletes any *.mediadash.tmp*, *.mediadash.new*, mediadash.tmp.*, or mediadash.new.* file it finds. These are leftovers from a hard-killed encode (SIGKILL, container restart, Jellyfin crash) where the C# finally block that normally deletes them never ran. Deleted-count + reclaimed-bytes go into Jellyfin\u0027s log.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.8/mediadash_0.9.8.zip", "checksum": "028cf3ecc7099308d0342b44fcd2aeee", "timestamp": "2026-08-06T12:26:47Z" }, { "version": "0.9.7.0", "changelog": "FfmpegExecutor now sweeps for orphaned MediaDash ffmpeg processes before spawning a new encode. Linux only (reads /proc/\u003cpid\u003e/cmdline; Windows/macOS would need extra deps for a very rare failure mode). Any ffmpeg whose command line contains a mediadash.tmp or mediadash.new marker is killed with SIGKILL and its sidecar output file is deleted. Prevents the \"two ffmpegs writing to the same output\" scenario after a plugin hot-reload or a Jellyfin restart mid-encode. Also cleans up the interleaved-bytes .tmp file that would otherwise sit on disk until the next fix run on the same source overwrote it.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.7/mediadash_0.9.7.zip", "checksum": "b723fec74e85312caa61c22aa20fdab8", "timestamp": "2026-08-06T12:21:23Z" }, { "version": "0.9.7.0", "changelog": "FfmpegExecutor now sweeps for orphaned MediaDash ffmpeg processes before spawning a new encode. Linux only (reads /proc/\u003cpid\u003e/cmdline; Windows/macOS would need extra deps for a very rare failure mode). Any ffmpeg whose command line contains a mediadash.tmp or mediadash.new marker is killed with SIGKILL and its sidecar output file is deleted. Prevents the \"two ffmpegs writing to the same output\" scenario after a plugin hot-reload or a Jellyfin restart mid-encode. Also cleans up the interleaved-bytes .tmp file that would otherwise sit on disk until the next fix run on the same source overwrote it.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.7/mediadash_0.9.7.zip", "checksum": "b723fec74e85312caa61c22aa20fdab8", "timestamp": "2026-08-06T12:21:23Z" }, { "version": "0.9.6.0", "changelog": "Manual fix runs now pause instead of bailing when someone starts watching. Click \"Run fixes now\", the queue drains as before, but if the pause-on-playback check trips between files the run pauses (with an amber banner: \"Paused: someone is watching. Click \u0027Ignore activity\u0027 to resume anyway.\") and re-checks every 30 seconds. When the viewer stops or you hit the Ignore activity button, the run resumes from where it stopped. Scheduled runs keep the previous behaviour (break on activity, next 15-minute tick tries again). The Ignore flag only applies to the current run — a fresh Run fixes now click brings the pause behaviour back.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.6/mediadash_0.9.6.zip", "checksum": "93330f3d5fd09654d8301f6580521d45", "timestamp": "2026-08-06T12:09:51Z" }, { "version": "0.9.6.0", "changelog": "Manual fix runs now pause instead of bailing when someone starts watching. Click \"Run fixes now\", the queue drains as before, but if the pause-on-playback check trips between files the run pauses (with an amber banner: \"Paused: someone is watching. Click \u0027Ignore activity\u0027 to resume anyway.\") and re-checks every 30 seconds. When the viewer stops or you hit the Ignore activity button, the run resumes from where it stopped. Scheduled runs keep the previous behaviour (break on activity, next 15-minute tick tries again). The Ignore flag only applies to the current run — a fresh Run fixes now click brings the pause behaviour back.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.6/mediadash_0.9.6.zip", "checksum": "93330f3d5fd09654d8301f6580521d45", "timestamp": "2026-08-06T12:09:51Z" }, { "version": "0.9.5.0", "changelog": "Fix the \"Fix run finished with failures\" popup firing on every page load. The first-poll guard checked prevFinishedAt !== undefined but lastStatus starts as null, which short-circuited prevFinishedAt to null (not undefined) — so opening the plugin page always fired an alert if the most-recent completed run had any failures, even while a new run was still going. The alert now only fires when a poll\u0027s FinishedAtUtc actually changes from a prior poll.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.5/mediadash_0.9.5.zip", "checksum": "d0ebaff6176be47e485b8f027c768eae", "timestamp": "2026-08-06T09:25:24Z" }, { "version": "0.9.5.0", "changelog": "Fix the \"Fix run finished with failures\" popup firing on every page load. The first-poll guard checked prevFinishedAt !== undefined but lastStatus starts as null, which short-circuited prevFinishedAt to null (not undefined) — so opening the plugin page always fired an alert if the most-recent completed run had any failures, even while a new run was still going. The alert now only fires when a poll\u0027s FinishedAtUtc actually changes from a prior poll.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.5/mediadash_0.9.5.zip", "checksum": "d0ebaff6176be47e485b8f027c768eae", "timestamp": "2026-08-06T09:25:24Z" }, { "version": "0.9.4.0", "changelog": "Fix cascade after 0.9.3 hit real prod hardware. Track-remux fixer now uses the same hash-fallback sidecar name as the transcode fixer (v0.9.2 shipped it for one path, not both) — long-UTF-8 filenames (Cyrillic/CJK) no longer fail with ffmpeg \"Error opening output\" on Linux NAME_MAX. Free-disk-space check now looks at the actual mount containing the file via RecycleBin.FindDriveForPath, not the root filesystem — LXC/Docker setups where /mnt/media is a large bind-mount but / is a tiny rootfs no longer get false \"Not enough free disk space\" bailouts on 30-60 GB BDRemuxes. QualityScanner is less trigger-happy: dropped the container-level bitrate fallback (was flagging remuxes with big lossless audio as \"video too fat\"), and added a 15%-of-file-size minimum-savings gate so HEVC-\u003eHEVC recompression at close bitrates doesn\u0027t burn a 20-minute encode only for the fixer to abort with \"the re-encoded file would be larger than the original\". TrackFixer\u0027s error truncation matches TranscodeFixer now — keeps the ffmpeg-error tail (where the real reason lives), not the head.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.4/mediadash_0.9.4.zip", "checksum": "7c39553363e7b731ad7ab3d0df2452b4", "timestamp": "2026-08-06T09:00:40Z" }, { "version": "0.9.4.0", "changelog": "Fix cascade after 0.9.3 hit real prod hardware. Track-remux fixer now uses the same hash-fallback sidecar name as the transcode fixer (v0.9.2 shipped it for one path, not both) — long-UTF-8 filenames (Cyrillic/CJK) no longer fail with ffmpeg \"Error opening output\" on Linux NAME_MAX. Free-disk-space check now looks at the actual mount containing the file via RecycleBin.FindDriveForPath, not the root filesystem — LXC/Docker setups where /mnt/media is a large bind-mount but / is a tiny rootfs no longer get false \"Not enough free disk space\" bailouts on 30-60 GB BDRemuxes. QualityScanner is less trigger-happy: dropped the container-level bitrate fallback (was flagging remuxes with big lossless audio as \"video too fat\"), and added a 15%-of-file-size minimum-savings gate so HEVC-\u003eHEVC recompression at close bitrates doesn\u0027t burn a 20-minute encode only for the fixer to abort with \"the re-encoded file would be larger than the original\". TrackFixer\u0027s error truncation matches TranscodeFixer now — keeps the ffmpeg-error tail (where the real reason lives), not the head.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.4/mediadash_0.9.4.zip", "checksum": "7c39553363e7b731ad7ab3d0df2452b4", "timestamp": "2026-08-06T09:00:40Z" }, { "version": "0.9.3.0", "changelog": "Transcode fix now actually uses the GPU. v0.9.2 shipped without the hardware-encoder path wired in — the UseHardwareEncoder toggle had no effect and every re-encode ran on the CPU via libx265. This release wires the hw path through and adds full VAAPI support (device auto-picked from /dev/dri/renderD* or Jellyfin\u0027s VaapiDevice, with format=nv12,hwupload / scale_vaapi in the filter chain). When Jellyfin\u0027s own HardwareAccelerationType is unset, the plugin now autodetects: NVIDIA → NVENC, any Linux DRM device (Intel/AMD iGPU or dGPU) → VAAPI, Windows → AMF (or QSV for Intel iGPUs), macOS → VideoToolbox, and falls back to libx265 only when no GPU is present. Any hardware failure still retries with software so no encode gets stuck. Settings page tidy-up: \u0027Thorough playability check\u0027 no longer has the oversized inset box beside the disposal dropdown; Issues tab drops the redundant \u0027Show\u0027 type filter (the count pills already do that) and moves the filename search onto the same row.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.3/mediadash_0.9.3.zip", "checksum": "eac4a6a92580c85e67ac54cf0596dd25", "timestamp": "2026-08-06T04:09:53Z" }, { "version": "0.9.3.0", "changelog": "Transcode fix now actually uses the GPU. v0.9.2 shipped without the hardware-encoder path wired in — the UseHardwareEncoder toggle had no effect and every re-encode ran on the CPU via libx265. This release wires the hw path through and adds full VAAPI support (device auto-picked from /dev/dri/renderD* or Jellyfin\u0027s VaapiDevice, with format=nv12,hwupload / scale_vaapi in the filter chain). When Jellyfin\u0027s own HardwareAccelerationType is unset, the plugin now autodetects: NVIDIA → NVENC, any Linux DRM device (Intel/AMD iGPU or dGPU) → VAAPI, Windows → AMF (or QSV for Intel iGPUs), macOS → VideoToolbox, and falls back to libx265 only when no GPU is present. Any hardware failure still retries with software so no encode gets stuck. Settings page tidy-up: \u0027Thorough playability check\u0027 no longer has the oversized inset box beside the disposal dropdown; Issues tab drops the redundant \u0027Show\u0027 type filter (the count pills already do that) and moves the filename search onto the same row.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.3/mediadash_0.9.3.zip", "checksum": "eac4a6a92580c85e67ac54cf0596dd25", "timestamp": "2026-08-06T04:09:53Z" }, { "version": "0.9.2.0", "changelog": "Groups TV episodes into per-show folders and movie franchises (\u003e=2 siblings) into shared folders using Jellyfin\u0027s identified metadata. Fixes false-positive duplicate detection when Jellyfin derives Movie.Name from a folder (name-fallback keys now include the filename; also tightened for Book and Audio, with a required runtime for audio). Fixes transcode failure on filenames near Linux\u0027s 255-byte limit (Cyrillic/CJK) via hash-based sidecar names. Failed fixes that mean \u0027file no longer exists\u0027 or \u0027nothing left to remove\u0027 now auto-clear from the queue instead of retrying every 15 minutes. Move-style fixers now update sibling issues in the DB so they don\u0027t fail with \u0027no longer exists\u0027 after a rename. Issues tab: per-type total pills, \u0027Try to play\u0027 button on Playability cards, Duplicate cards show keeper location. ffmpeg error output now shows the tail (where the actual error is) instead of the codec startup banner.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.2/mediadash_0.9.2.zip", "checksum": "6645ed03f6e883f3fb4d1f8a7171f9af", "timestamp": "2026-08-05T10:41:04Z" }, { "version": "0.9.2.0", "changelog": "Groups TV episodes into per-show folders and movie franchises (\u003e=2 siblings) into shared folders using Jellyfin\u0027s identified metadata. Fixes false-positive duplicate detection when Jellyfin derives Movie.Name from a folder (name-fallback keys now include the filename; also tightened for Book and Audio, with a required runtime for audio). Fixes transcode failure on filenames near Linux\u0027s 255-byte limit (Cyrillic/CJK) via hash-based sidecar names. Failed fixes that mean \u0027file no longer exists\u0027 or \u0027nothing left to remove\u0027 now auto-clear from the queue instead of retrying every 15 minutes. Move-style fixers now update sibling issues in the DB so they don\u0027t fail with \u0027no longer exists\u0027 after a rename. Issues tab: per-type total pills, \u0027Try to play\u0027 button on Playability cards, Duplicate cards show keeper location. ffmpeg error output now shows the tail (where the actual error is) instead of the codec startup banner.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.2/mediadash_0.9.2.zip", "checksum": "6645ed03f6e883f3fb4d1f8a7171f9af", "timestamp": "2026-08-05T10:41:04Z" }, { "version": "0.9.1.0", "changelog": "Fix task now runs opportunistically. Instead of a daily-at-configured-time trigger, it fires every 15 minutes and defers immediately when anyone is watching or has been active in the last 15 minutes (existing \u0027Only run when idle\u0027 setting). Queued fixes now drain the moment the server goes idle instead of waiting for the nightly window. Existing installs auto-migrate their old daily trigger on first startup (30 s after boot). The \u0027Scheduled fix time\u0027 input is retired — no configuration needed.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.1/mediadash_0.9.1.zip", "checksum": "d7d3fda81dd15c589244cf0bf880f102", "timestamp": "2026-08-03T08:56:21Z" }, { "version": "0.9.1.0", "changelog": "Fix task now runs opportunistically. Instead of a daily-at-configured-time trigger, it fires every 15 minutes and defers immediately when anyone is watching or has been active in the last 15 minutes (existing \u0027Only run when idle\u0027 setting). Queued fixes now drain the moment the server goes idle instead of waiting for the nightly window. Existing installs auto-migrate their old daily trigger on first startup (30 s after boot). The \u0027Scheduled fix time\u0027 input is retired — no configuration needed.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.1/mediadash_0.9.1.zip", "checksum": "d7d3fda81dd15c589244cf0bf880f102", "timestamp": "2026-08-03T08:56:21Z" }, { "version": "0.9.0.0", "changelog": "New Virus scan (SuspiciousFile) surfaces executables/scripts inside media folders. Jellyfin 12 scoped-scanner fix: library-scoping now resolves correctly on v12 hosts where VirtualFolderInfo.ItemId was dropped. Media sorter typed for Audio/AudioBook/Book/Comic/Picture with per-kind target folders. Data-safety hardening: transcode/track fixers stage the encoded copy to a sidecar before disposing the original, so a failed final rename preserves the encoded file rather than losing both. Scanner resilience: a single throw no longer aborts a scan; the Errors tab shows the file and continues. RecycleBin/SkiaSharp/upload-cleanup silent catches now surface to the Errors tab.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.0/mediadash_0.9.0.zip", "checksum": "f01977cc18cefb0d561497767bf61718", "timestamp": "2026-08-03T07:53:51Z" }, { "version": "0.9.0.0", "changelog": "New Virus scan (SuspiciousFile) surfaces executables/scripts inside media folders. Jellyfin 12 scoped-scanner fix: library-scoping now resolves correctly on v12 hosts where VirtualFolderInfo.ItemId was dropped. Media sorter typed for Audio/AudioBook/Book/Comic/Picture with per-kind target folders. Data-safety hardening: transcode/track fixers stage the encoded copy to a sidecar before disposing the original, so a failed final rename preserves the encoded file rather than losing both. Scanner resilience: a single throw no longer aborts a scan; the Errors tab shows the file and continues. RecycleBin/SkiaSharp/upload-cleanup silent catches now surface to the Errors tab.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.9.0/mediadash_0.9.0.zip", "checksum": "f01977cc18cefb0d561497767bf61718", "timestamp": "2026-08-03T07:53:51Z" }, { "version": "0.8.5.0", "changelog": "Settings tab restructured into per-scanner task cards. Every scanner (Duplicate, Playability, Quality, Sub/Audio, Stale, Misplaced, Missing subs) is now one self-contained card that owns its own mode, disposal, and settings. Segmented mode picker replaces the How-it-runs dropdown; Off collapses and dims the card. Language pickers become chip inputs. Quality card carries every re-encode knob including a new Advanced disclosure for the fine-tuning ones. Stale card gains library and genre excludes; Duplicate gains a wait-N-days-after-import gate. Chip rail is per-task and dims when a task is Off; a Cleanup-tasks header adds Collapse-all and a live N-of-8-active counter. History tab replaces the cumulative savings chart with a per-library saved-bytes breakdown. Disposal dropdown greys out in Detect-only / Off since it doesn\u0027t apply. New GitHub Pages landing at crackruckles.github.io/MediaDash and a repo social-preview card in docs/.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.5/mediadash_0.8.5.zip", "checksum": "a01e286570fe2842e691ae8c055c6515", "timestamp": "2026-07-27T07:36:36Z" }, { "version": "0.8.5.0", "changelog": "Settings tab restructured into per-scanner task cards. Every scanner (Duplicate, Playability, Quality, Sub/Audio, Stale, Misplaced, Missing subs) is now one self-contained card that owns its own mode, disposal, and settings. Segmented mode picker replaces the How-it-runs dropdown; Off collapses and dims the card. Language pickers become chip inputs. Quality card carries every re-encode knob including a new Advanced disclosure for the fine-tuning ones. Stale card gains library and genre excludes; Duplicate gains a wait-N-days-after-import gate. Chip rail is per-task and dims when a task is Off; a Cleanup-tasks header adds Collapse-all and a live N-of-8-active counter. History tab replaces the cumulative savings chart with a per-library saved-bytes breakdown. Disposal dropdown greys out in Detect-only / Off since it doesn\u0027t apply. New GitHub Pages landing at crackruckles.github.io/MediaDash and a repo social-preview card in docs/.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.5/mediadash_0.8.5.zip", "checksum": "a01e286570fe2842e691ae8c055c6515", "timestamp": "2026-07-27T07:36:36Z" }, { "version": "0.8.4.0", "changelog": "History tab: replaced the cumulative savings chart with a per-library saved-bytes breakdown, sorted highest to lowest, so you can see which library each fixer has helped most. New GitHub Pages landing at crackruckles.github.io/MediaDash.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.4/mediadash_0.8.4.zip", "checksum": "b82eedfb92953e85b3c6a32ff1b1d9d8", "timestamp": "2026-07-27T02:41:12Z" }, { "version": "0.8.4.0", "changelog": "History tab: replaced the cumulative savings chart with a per-library saved-bytes breakdown, sorted highest to lowest, so you can see which library each fixer has helped most. New GitHub Pages landing at crackruckles.github.io/MediaDash.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.4/mediadash_0.8.4.zip", "checksum": "b82eedfb92953e85b3c6a32ff1b1d9d8", "timestamp": "2026-07-27T02:41:12Z" }, { "version": "0.8.3.0", "changelog": "Overview reclaim card is now a split hero with two donuts. Left side \"Space you could reclaim\" (open issues, cyan) has a donut sized by issue count with a per-type legend. Right side \"Reclaimed since install\" (green) has a donut sized by bytes-freed-per-type so you can see at a glance which fixer has done the most disk-wise (e.g. 7.6 MB Quality re-encodes, 684 KB post-v12 cleanup). Post-Jellyfin-12 one-shot cleanup: a purple banner appears on Overview for hosts running Jellyfin 12+ (once, until you run or dismiss it) offering to sweep orphaned trickplay image folders that survived the 10 to 12 library rewrite. The reclaim lands in History and adds to the lifetime tally. Errors tab: friendly per-error titles + actionable hints in an amber box telling you what to check. The raw source code and exception message collapse behind a Technical detail toggle so bug reports still have everything but day-to-day reading is a lot easier. Setup wizard defaults the stale-content threshold to 365 days when the scanner is off; a previously-saved value only surfaces if you have already opted in.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.3/mediadash_0.8.3.zip", "checksum": "0bb18fd37878e1b7230d176d53004ef1", "timestamp": "2026-07-26T16:05:34Z" }, { "version": "0.8.3.0", "changelog": "Overview reclaim card is now a split hero with two donuts. Left side \"Space you could reclaim\" (open issues, cyan) has a donut sized by issue count with a per-type legend. Right side \"Reclaimed since install\" (green) has a donut sized by bytes-freed-per-type so you can see at a glance which fixer has done the most disk-wise (e.g. 7.6 MB Quality re-encodes, 684 KB post-v12 cleanup). Post-Jellyfin-12 one-shot cleanup: a purple banner appears on Overview for hosts running Jellyfin 12+ (once, until you run or dismiss it) offering to sweep orphaned trickplay image folders that survived the 10 to 12 library rewrite. The reclaim lands in History and adds to the lifetime tally. Errors tab: friendly per-error titles + actionable hints in an amber box telling you what to check. The raw source code and exception message collapse behind a Technical detail toggle so bug reports still have everything but day-to-day reading is a lot easier. Setup wizard defaults the stale-content threshold to 365 days when the scanner is off; a previously-saved value only surfaces if you have already opted in.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.3/mediadash_0.8.3.zip", "checksum": "0bb18fd37878e1b7230d176d53004ef1", "timestamp": "2026-07-26T16:05:34Z" }, { "version": "0.8.2.0", "changelog": "Overview banners are now dismissible - both the cross-volume recycle bin warning and the \"bin is over 10 GB\" reminder grow a close button. Dismissal is session-scoped so a fresh browser session brings the reminder back if the underlying condition (bin still on a different drive, still over 10 GB) is still true. Per-item Restore in Settings \u003e Recycle bin \u003e View contents: every recycled file now has its own Restore button that puts it back at the original location. Backed by a join against the history table (matching bin path to history entry). The existing safety guard that refuses to overwrite a live file at the destination still applies - the conflict message surfaces inline on the row. Errors tab: the \"Copy diagnostics\" button is now \"Report an issue\" - one click copies diagnostics to the clipboard AND opens the GitHub issue tracker in a new tab. Tooltip pass across the plugin: added hover descriptions to Errors tab actions (Refresh, Retry all, Clear), Files tab bulk actions (Delete, Move, Download, Deselect), the New folder button, folder-picker buttons, and the dry-run banner action. Short but load-bearing.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.2/mediadash_0.8.2.zip", "checksum": "8db1a73981481a00c4b5d769ef7f7ce5", "timestamp": "2026-07-26T09:26:04Z" }, { "version": "0.8.2.0", "changelog": "Overview banners are now dismissible - both the cross-volume recycle bin warning and the \"bin is over 10 GB\" reminder grow a close button. Dismissal is session-scoped so a fresh browser session brings the reminder back if the underlying condition (bin still on a different drive, still over 10 GB) is still true. Per-item Restore in Settings \u003e Recycle bin \u003e View contents: every recycled file now has its own Restore button that puts it back at the original location. Backed by a join against the history table (matching bin path to history entry). The existing safety guard that refuses to overwrite a live file at the destination still applies - the conflict message surfaces inline on the row. Errors tab: the \"Copy diagnostics\" button is now \"Report an issue\" - one click copies diagnostics to the clipboard AND opens the GitHub issue tracker in a new tab. Tooltip pass across the plugin: added hover descriptions to Errors tab actions (Refresh, Retry all, Clear), Files tab bulk actions (Delete, Move, Download, Deselect), the New folder button, folder-picker buttons, and the dry-run banner action. Short but load-bearing.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.2/mediadash_0.8.2.zip", "checksum": "8db1a73981481a00c4b5d769ef7f7ce5", "timestamp": "2026-07-26T09:26:04Z" }, { "version": "0.8.1.0", "changelog": "Version-stamp hotfix. v0.8.0 shipped a DLL that self-identified as 0.0.0.0 on the Jellyfin dashboard because a stale Directory.Build.props was pinning AssemblyVersion. Same code as v0.8.0; the DLL now correctly stamps to 0.8.1.0 so the dashboard label matches the manifest. If you saw MediaDash 0.0.0.0 on your My Plugins page after updating to 0.8.0, this release fixes that.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.1/mediadash_0.8.1.zip", "checksum": "acfc37eba7bf91e90d2479a5d7796f0a", "timestamp": "2026-07-26T08:02:16Z" }, { "version": "0.8.1.0", "changelog": "Version-stamp hotfix. v0.8.0 shipped a DLL that self-identified as 0.0.0.0 on the Jellyfin dashboard because a stale Directory.Build.props was pinning AssemblyVersion. Same code as v0.8.0; the DLL now correctly stamps to 0.8.1.0 so the dashboard label matches the manifest. If you saw MediaDash 0.0.0.0 on your My Plugins page after updating to 0.8.0, this release fixes that.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.1/mediadash_0.8.1.zip", "checksum": "acfc37eba7bf91e90d2479a5d7796f0a", "timestamp": "2026-07-26T08:02:16Z" }, { "version": "0.8.0.0", "changelog": "Overview: recycle bin banner appears when the bin holds more than 10 GB with a one-click jump to Settings for review or empty.\n\nSettings polish: the \"When duplicates are found, keep\" select moved from the What to fix section into the Quality ceiling section since it scores duplicates using the resolution, codec, and bitrate configured directly below it.\n\nRolls up v0.7.3 for anyone who missed it - Stale content scanner (detect-only, flags media nobody has played in your configured window), Jellyfin 12.0 compatibility (one binary works on both 10.11 and 12.0 host lines via reflection bridge over the User entity changes; manifest advertises both targetAbi entries), and the deep playability checks that catch files that \"sort of play\" - stderr marker scan for \"File ended prematurely\" / \"Truncating packet\", container bitrate x duration vs actual file size sanity check, and decoded time vs requested segment comparison.\n\nDocumentation refresh across README, PLAN, CHANGELOG, and CLAUDE.md.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.0/mediadash_0.8.0.zip", "checksum": "57457c3b5c91e578ecf2b829b18b2c70", "timestamp": "2026-07-26T07:47:53Z" }, { "version": "0.8.0.0", "changelog": "Overview: recycle bin banner appears when the bin holds more than 10 GB with a one-click jump to Settings for review or empty.\n\nSettings polish: the \"When duplicates are found, keep\" select moved from the What to fix section into the Quality ceiling section since it scores duplicates using the resolution, codec, and bitrate configured directly below it.\n\nRolls up v0.7.3 for anyone who missed it - Stale content scanner (detect-only, flags media nobody has played in your configured window), Jellyfin 12.0 compatibility (one binary works on both 10.11 and 12.0 host lines via reflection bridge over the User entity changes; manifest advertises both targetAbi entries), and the deep playability checks that catch files that \"sort of play\" - stderr marker scan for \"File ended prematurely\" / \"Truncating packet\", container bitrate x duration vs actual file size sanity check, and decoded time vs requested segment comparison.\n\nDocumentation refresh across README, PLAN, CHANGELOG, and CLAUDE.md.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.8.0/mediadash_0.8.0.zip", "checksum": "57457c3b5c91e578ecf2b829b18b2c70", "timestamp": "2026-07-26T07:47:53Z" }, { "version": "0.7.3.0", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.7.3/mediadash_0.7.3.zip", "checksum": "381aa1e18c9503a02c2be6b742ce9382", "changelog": "New Stale-content scanner: flags media that has been on the server past a configured threshold (default 365 days) without any user playing it in that window. Detect-only - no auto-delete. Wizard grows a \"Stale content\" step with a threshold input, Settings > What to fix picks it up, Issues tab filter and Overview \"Space you could reclaim\" totals include it automatically. Jellyfin 12.0 compatibility: the User entity moved namespaces (Jellyfin.Data.Entities to Jellyfin.Database.Implementations.Entities) and IUserManager.Users was renamed to GetUsers(). One binary now works on both 10.11 and 12.0 via a reflection bridge over the User-touching API. Manifest advertises both targetAbi 10.11.0.0 and 12.0.0.0. Playability scanner: three new checks catch files that \"sort of play\" - files that ffprobe accepts but that stop short during decode. (1) stderr marker scan for \"File ended prematurely\" / \"Truncating packet\" (ffmpeg emits these but still exits 0, hiding truncation from the old exit-code-only check); (2) bitrate-vs-file-size sanity check when the container reports both; (3) decoded-time vs requested-segment check (-stats output parsed for the last time= value; flags anything more than 10% short). All three run only when Thorough playability check is on in Settings.", "timestamp": "2026-07-26T07:12:35Z" }, { "version": "0.7.3.0", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.7.3/mediadash_0.7.3.zip", "checksum": "381aa1e18c9503a02c2be6b742ce9382", "changelog": "New Stale-content scanner: flags media that has been on the server past a configured threshold (default 365 days) without any user playing it in that window. Detect-only - no auto-delete. Wizard grows a \"Stale content\" step with a threshold input, Settings > What to fix picks it up, Issues tab filter and Overview \"Space you could reclaim\" totals include it automatically. Jellyfin 12.0 compatibility: the User entity moved namespaces (Jellyfin.Data.Entities to Jellyfin.Database.Implementations.Entities) and IUserManager.Users was renamed to GetUsers(). One binary now works on both 10.11 and 12.0 via a reflection bridge over the User-touching API. Manifest advertises both targetAbi 10.11.0.0 and 12.0.0.0. Playability scanner: three new checks catch files that \"sort of play\" - files that ffprobe accepts but that stop short during decode. (1) stderr marker scan for \"File ended prematurely\" / \"Truncating packet\" (ffmpeg emits these but still exits 0, hiding truncation from the old exit-code-only check); (2) bitrate-vs-file-size sanity check when the container reports both; (3) decoded-time vs requested-segment check (-stats output parsed for the last time= value; flags anything more than 10% short). All three run only when Thorough playability check is on in Settings.", "timestamp": "2026-07-26T07:12:35Z" }, { "version": "0.7.2.0", "changelog": "Jellyfin 12.0 compatible entry (same binary as the 10.11 entry below). Jellyfin 12 is a version-scheme rename of what would have been 10.12, not a hard API break, so the same zip loads on both host lines. Verified against a running 12.0.0 server.", "targetAbi": "12.0.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.7.2/mediadash_0.7.2.zip", "checksum": "59fc44128bd52db5d2ca7bc65a5f428d", "timestamp": "2026-07-26T09:00:00Z" }, { "version": "0.7.2.0", "changelog": "Settings tab: fixes width squish on wide monitors. Jellyfin's core CSS caps every form at 54em on >=50em viewports, and the Settings tab wrapper is a form, so the whole settings surface (page header, nav chips, card grid) was stuck at ~800px on a 1080p monitor. Plugin-scoped `form { max-width: none }` overrides that. Community stats opt-in is now pre-ticked in the first-run wizard and on Settings > Safety - unticking + Save opts you out and clears the install UUID, and nothing about what is/isn't sent has changed (see docs/PRIVACY.md).", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.7.2/mediadash_0.7.2.zip", "checksum": "59fc44128bd52db5d2ca7bc65a5f428d", "timestamp": "2026-07-25T12:16:45Z" }, { "version": "0.7.1.0", "changelog": "Fixes v0.7.0 which shipped an incomplete zip (only the main dll, missing System.Diagnostics.PerformanceCounter.dll + 3 other dependency dlls). On Windows this made the plugin fail to load with a FileNotFoundException, showing as NotSupported in Dashboard > Plugins. v0.7.1 ships the full dependency set. Also two Settings tab polish fixes: page now uses the full window width instead of capping at 1400px, and the Scheduled fix time input is now visible against the dark card background (Chrome/Edge were rendering the clock indicator in a colour that vanished against the card).", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.7.1/mediadash_0.7.1.zip", "checksum": "311b96f38e3a547078719a5154c0e65e", "timestamp": "2026-07-25T09:53:04Z" }, { "version": "0.7.0.0", "changelog": "Two features. Configurable fix schedule: Settings > Safety now has a time picker for when the daily fix run fires (default 03:00, including re-encodes) - the existing 'Only run when the server is idle' flag still vetoes runs when someone is watching, and the change takes effect without a Jellyfin restart. UI localisation: the dashboard, tab labels, settings section headings, first-run wizard, and the plugin's scheduled-task names now translate to whichever UI language the current Jellyfin user has selected. English is the source of truth; de/es/fr/it/nl/pt-BR/ru/zh-CN ship as machine-translated seeds and are unproofread - community PRs to refine any locale are welcome. Falls back cleanly (de-AT to de to en) so an unknown locale never breaks the page. Deep settings tooltips (Quality, Advanced, Libraries, Recycle bin internals) stay English for now - the framework accepts new keys without any code change, so those get wrapped as needed.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.7.0/mediadash_0.7.0.zip", "checksum": "bc92c31cee8f488ea644748725abc86d", "timestamp": "2026-07-25T01:37:25Z" }, { "version": "0.6.1.0", "changelog": "Pre-beta polish. New 'Copy diagnostics' button on the Errors tab drops a clipboard-ready markdown blob (plugin/Jellyfin/OS/runtime versions plus all recorded errors) that pastes cleanly into a GitHub issue. New 'Report an issue' link in Settings > Maintenance opens the tracker in a new tab. Wizard step 5 and the Settings 'Missing subtitles' row now show a live indicator whether a subtitle provider is installed - green with the provider name when ready, amber with 'Install one from Dashboard > Plugins > Catalog, the API key lives on that plugin's page, not here' when not - closing the discovery gap about where subtitle providers are configured (they live inside Jellyfin proper, MediaDash inherits them). Media sorter gains an optional 'Anime folder' target: items with Jellyfin's 'Anime' genre tag (case-insensitive) route there instead of Movies or TV. Leave it empty to keep existing behaviour. If your anime isn't tagged, install the AniDB scraper from Dashboard > Plugins > Catalog and Jellyfin will apply the tag automatically. CHANGELOG.md refreshed to point at GitHub Releases.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.6.1/mediadash_0.6.1.zip", "checksum": "bc61110713b432ee2f44d6cae7d7c348", "timestamp": "2026-07-24T04:24:45Z" }, { "version": "0.6.0.0", "changelog": "New Missing subtitles fix type: flags videos with no subtitle in any wanted language and downloads one via Jellyfin's already-configured subtitle providers (OpenSubtitles etc.) - no new API keys. First-run experience is now a multi-step wizard that walks each feature one at a time (Welcome, Libraries + access-check, Duplicates, Broken files, Oversized files, Languages incl. missing-subs mode, Media sorter, Safety net, Done), triggered only on fresh installs (survives plugin updates via FirstRunDone). Preferred-GPU picker moved into the Oversized step alongside the hardware-encoder toggle. AMD APU (Rembrandt / Phoenix - Ryzen 6000/7000 iGPUs) GPU percentage now reads from /sys/class/drm/cardN/device/gpu_metrics when gpu_busy_percent is pinned at 0, fixing the 0.0% GPU reading on affected hosts. Overview 'Space you could reclaim' total now includes issues you've already approved (Queued), not just Detected ones - matches what the Issues tab shows. PLAN.md rewritten around a whole-library housekeeping scope with explicit non-goals (no acquisition, no metadata authoring) and a prioritised roadmap for the next scanners.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.6.0/mediadash_0.6.0.zip", "checksum": "6d4bdfb42ca71720a080e9834cd96452", "timestamp": "2026-07-24T01:45:02Z" }, { "version": "0.5.3.0", "changelog": "History tab grows an All / Succeeded / Failed / Dry run filter row with live per-bucket counts so you can jump straight to the failed items after a big fix run instead of scrolling. Backed by a new Success column on the history table (schema v2; legacy rows back-filled). Settings tab redesign: sticky page header with a gradient Save button, restyled chip nav, 2-column grid of glass-effect cards with tinted icon boxes, Plus Jakarta Sans typography, and sections re-ordered so Maintenance actions live in their own card instead of buried in Advanced. Whole plugin surface is now centred and widened to min(1400px, 96vw) so the 2-column grid and drive-storage cards have room to breathe.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.5.3/mediadash_0.5.3.zip", "checksum": "4e2d1c533fdf4c3776d7a08aaae2a44f", "timestamp": "2026-07-23T08:59:56Z" }, { "version": "0.5.2.0", "changelog": "The 'Run fixes now' button used to appear to do nothing when every attempted fix failed fast (typical on a Linux server where the jellyfin user doesn't own the media files) - the progress bar just flashed and the user was left to click through Errors to find out what happened. Fix runs now finish with a dashboard alert summarising attempted / succeeded / failed and the dominant reason, with reason-specific instructions (e.g. the exact chown command to grant Jellyfin write access). Manually-approved issues under types set to 'Detect only' now actually run - previously they were silently filtered out. The Overview drive list now always shows the drive the recycle bin lives on, even when it's on a Docker overlay / tmpfs / btrfs subvolume that DriveInfo filters out, so you notice when the bin is filling your system disk. New 'Check library access' button in first-run setup that probes read+write on every library folder and reports pass/fail per folder with a plain-language reason, so ownership/ACL problems get caught before you approve anything.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.5.2/mediadash_0.5.2.zip", "checksum": "5b61e5bfd897a86277e3f807f3f60893", "timestamp": "2026-07-23T01:50:48Z" }, { "version": "0.5.1.0", "changelog": "Media sorter now surfaces a clear, actionable error message on the Errors tab when a target folder is misconfigured (doesn't exist, sits outside every Jellyfin library, or isn't writable by the Jellyfin user) instead of silently creating hundreds of unfixable issues. The fixer also distinguishes those cases at fix time and pre-checks free disk space for cross-volume moves. 'Empty recycle bin now' used to freeze the UI on large bins and silently fail on older ApiClient builds - it now runs in the background with a determinate progress bar, and any per-batch permission or I/O errors show as a dashboard alert instead of tanking the whole operation on the first bad file.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.5.1/mediadash_0.5.1.zip", "checksum": "687a7a583af341bbe7639c75dc99f404", "timestamp": "2026-07-22T14:16:09Z" }, { "version": "0.5.0.0", "changelog": "New 'Misplaced files' fix type: MediaDash spots a movie sitting in your TV folder (or a TV episode sitting in Movies) and moves it into the correct folder. Set the two target folders under Settings > Libraries; classification uses Jellyfin's own metadata by default with a filename-pattern fallback (SxxExx / NxN => TV). LibraryGuard refuses moves outside your Jellyfin libraries. Optional new toggle to rename files after a successful re-encode to a canonical form: 'Name (Year) - 1080p.mkv' for movies, 'Series - S03E14 - 1080p.mkv' for TV episodes. Every primary button and settings chip now shows a tooltip on hover.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.5.0/mediadash_0.5.0.zip", "checksum": "77f79febc6b0b9c4c4350b13e616eade", "timestamp": "2026-07-22T13:18:49Z" }, { "version": "0.4.9.0", "changelog": "Recycle bin pre-checks free space on cross-volume moves and Overview warns when the bin lives on a different volume than your libraries. Issues tab now shows queued items alongside detected ones (they no longer vanish on approval) and refreshes live during a fix run so items disappear as they succeed. New 'Retry all fixes' button on the Errors tab clears the buffer and reruns the queue.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.9/mediadash_0.4.9.zip", "checksum": "2b0db8bdf731cc59a5dfd4197e691457", "timestamp": "2026-07-22T03:50:00Z" }, { "version": "0.4.8.0", "changelog": "Polish pass. File browser and fix task catch UnauthorizedAccessException with an actionable message (points at Jellyfin's user needing write access) instead of a generic 500; denied fixes also show in History. New Encode preset dropdown (Faster/Balanced/Best) for software re-encodes. Quality scanner ignores files smaller than a configurable threshold (100 MB default) and skips HDR content by default so naive transcodes don't destroy HDR metadata. Errors tab collapses repeated identical entries into a single row with a count. New live filter-by-filename search on the Issues tab.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.8/mediadash_0.4.8.zip", "checksum": "12740486970d7005dd76331bf47070b3", "timestamp": "2026-07-22T03:30:00Z" }, { "version": "0.4.7.0", "changelog": "Linux hotfix. /Status endpoint crashed on Linux because SystemStats referenced Windows-only PerformanceCounter at class-load time. Now loaded lazily so the type only resolves inside the Windows branch. Sample() also gains a top-level try/catch that surfaces future failures to the Errors tab instead of taking the tab down silently.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.7/mediadash_0.4.7.zip", "checksum": "ab9ab175e267c253905c723fef5331ae", "timestamp": "2026-07-21T03:45:00Z" }, { "version": "0.4.6.0", "changelog": "Multi-GPU monitoring (NVIDIA / Windows PDH / Linux sysfs, per-card) with per-GPU cells. New Preferred GPU dropdown routes re-encodes to a specific card via ffmpeg -gpu for NVENC/AMF. Windows GPU counter fix: PDH counters are cached across polls and aggregated max-across-engines so numbers match Task Manager. Overview polls every 3s while visible, and metric cells update in place so the tab no longer flickers. New Errors tab with red badge exposes swallowed plugin exceptions. Approve refreshes status so 'nothing to fix' isn't stale. Approve-all button restyled and aligned. 'Space you could reclaim' card no longer overhangs its container.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.6/mediadash_0.4.6.zip", "checksum": "b3a879b4f3ab685e2756df96f3cdc271", "timestamp": "2026-07-21T03:30:00Z" }, { "version": "0.4.5.0", "changelog": "GPU monitoring now covers AMD and modern Intel iGPUs on Linux via /sys/class/drm sysfs when nvidia-smi isn't available. GPU cell shows the data source (NVIDIA / Linux sysfs). Sidebar icon changed from generic 'dashboard' to 'auto_fix_high' so MediaDash stands out at a glance.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.5/mediadash_0.4.5.zip", "checksum": "c405f81429c8a2b712f1e24a38ae2224", "timestamp": "2026-07-21T02:15:00Z" }, { "version": "0.4.4.0", "changelog": "System performance card now reports whole-host CPU and RAM (Windows via GetSystemTimes/GlobalMemoryStatusEx, Linux via /proc). macOS and containers show N/A. Drives card now lists every fixed drive on the host, with a badge on library-hosting drives.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.4/mediadash_0.4.4.zip", "checksum": "dbfd0467c649399406c1667a0cf8066b", "timestamp": "2026-07-21T01:55:00Z" }, { "version": "0.4.3.0", "changelog": "Overview leads with a live System performance card (Jellyfin CPU%, memory, NVIDIA GPU% via nvidia-smi) at the top, then Library drive storage, then everything else. Themed to match the rest of the plugin with green→amber→red bar colouring.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.3/mediadash_0.4.3.zip", "checksum": "77b02d8af2e11cc46b8c7a5b64107fa9", "timestamp": "2026-07-21T00:10:00Z" }, { "version": "0.4.2.0", "changelog": "Overview polish. Scan/Fix buttons now cancel the running task (red Stop state) with a matching themed gradient look. Current file shown under the progress bar. Per-drive storage card. No more 3-second flicker while scanning/fixing. Fix run processes smallest files first so early completions free disk space for the big ones.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.2/mediadash_0.4.2.zip", "checksum": "e9fd851840a11a191a9402d64ad77fd7", "timestamp": "2026-07-20T14:55:00Z" }, { "version": "0.4.1.0", "changelog": "Files tab restyled to match the rest of the plugin: 14px rounded cards, Jellyfin-blue accent on headers/hover, tabular numbers for size/date, breadcrumb pill, refined bulk action bar and folder-picker modal. Visual only, no functional changes.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.1/mediadash_0.4.1.zip", "checksum": "34df123537e6c7e661d36d5429f8d8e1", "timestamp": "2026-07-20T12:35:00Z" }, { "version": "0.4.0.0", "changelog": "Files tab: multi-select with bulk delete/move/download, filter box, and a modal folder picker that replaces the raw path prompt for move/copy operations.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.4.0/mediadash_0.4.0.zip", "checksum": "ef7d1f4b58195abd5dc7c802502ce63c", "timestamp": "2026-07-20T12:15:00Z" }, { "version": "0.3.2.0", "changelog": "Files tab: sortable columns (Name, Size, Modified), directories stay on top. Up button fixed at library roots. Issues tab: click a file path to open its folder in the Files tab; new 'Approve all N issues (all types)' button when no type filter is set.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.3.2/mediadash_0.3.2.zip", "checksum": "35f86dcfa51d94c5f421b9a2524b0621", "timestamp": "2026-07-20T11:55:00Z" }, { "version": "0.3.1.0", "changelog": "Files tab: drag-and-drop uploads. Drop one or many files onto the list to upload into the current folder. Multi-file selection via the Upload button too. Admin-only, same safety as before.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.3.1/mediadash_0.3.1.zip", "checksum": "54072379a9596099f5e49b147f8f26d3", "timestamp": "2026-07-20T11:35:00Z" }, { "version": "0.3.0.0", "changelog": "New Files tab: browse, upload, download, rename, move, copy and delete files inside your library folders. Deletes go to the recycle bin. Every operation is refused if it targets anything outside a configured library.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.3.0/mediadash_0.3.0.zip", "checksum": "862fe134049b9004e3ddfcbaa31a737a", "timestamp": "2026-07-20T11:20:00Z" }, { "version": "0.2.0.0", "changelog": "Fewer false-positive unplayable flags; less aggressive re-encode disk check so batches can proceed on tighter drives; live progress bar during transcodes; helpful hint when 'Run fixes now' has nothing to do; new 'Reset scan data' button in Settings > Advanced to recover from stuck state without reinstalling. Existing installs get a one-time decode-cache wipe so the playability fix takes effect immediately.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.2.0/mediadash_0.2.0.zip", "checksum": "68bc5c99aef20b1f93610414d5e934df", "timestamp": "2026-07-20T09:00:00Z" }, { "version": "0.1.1.0", "changelog": "Initial public release.", "targetAbi": "10.11.0.0", "sourceUrl": "https://github.com/crackruckles/MediaDash/releases/download/v0.1.1/mediadash_0.1.1.zip", "checksum": "830a9075d427809864975255def245ad", "timestamp": "2026-07-20T02:00:00Z" } ] } ]