Fix QuickFilters not loading from disk after restart (#1979) - #1980
Merged
Conversation
Commit 065118c deleted Migrations.migrate_to_v11_5_0, which despite its name ran on every startup and was the only code that read QuickFilters.json into QuickFilters.InMemoryState. Since v13.7.6, saved quick filters were never loaded after a restart, and adding a new filter overwrote the file. Make QuickFilters load its state lazily from disk on first access so it no longer depends on a startup hook. Restore the pre-v11.5.0 format fallback (plain string filters without names) that the deleted migration provided, and add regression tests covering load formats and restart persistence. Co-authored-by: rmcrackan <rmcrackan@gmail.com>
rmcrackan
marked this pull request as ready for review
August 19, 2026 19:59
Matches the existing usage in PersistentDictionary and LibationAvalonia.Program; the lock statement now emits Lock.EnterScope() instead of Monitor. Co-authored-by: rmcrackan <rmcrackan@gmail.com>
Commit 065118c also deleted migrate_to_v11_6_5, which clamped MaxSampleRate into LAME's supported [Hz_8000, Hz_48000] range on every startup (the fix for #1116). Its replacement, ValidateEnumSettings, only rejects values that fail to parse - but AAXClean.SampleRate defines Hz_7350, Hz_64000, Hz_88200 and Hz_96000, so a hand-edited or pre-v11.6.5 Settings.json could carry a valid-but-unsupported rate straight into the encoder. Clamp in the property getter and setter instead of a startup hook, following the DailyDownloadLimitQuantity pattern. Co-authored-by: rmcrackan <rmcrackan@gmail.com>
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.
Summary
Fixes #1979: quick filters saved to
QuickFilters.jsonwere no longer available after restarting the app, and adding a new filter after a restart overwrote the file.Auditing the commit that caused it turned up a second, latent regression from the same migration cleanup, also fixed here (see below).
Root cause
Commit 065118c (first shipped in v13.7.6) deleted
Migrations.migrate_to_v11_5_0as a dead migration. Despite its name, that method ran on every startup fromRunPostConfigMigrationsand was the only code that readQuickFilters.jsonintoQuickFilters.InMemoryState. With it gone,InMemoryStatestayednull:QuickFilters.Filtersreturned an empty enumerable, so the Quick Filters menu was empty after restart.AdddidInMemoryState ??= new()and then saved, overwriting the file with only the new filter.Fix
QuickFiltersnow lazily loads its state fromQuickFilters.jsonon first access (guarded by the existing lock), so it no longer depends on a startup hook that looks like removable migration code.UseDefaultsetter previously no-oped whileInMemoryStatewas null).QuickFilterslocker is now aSystem.Threading.Lock, matchingPersistentDictionaryandLibationAvalonia.Program.Second regression from the same cleanup: MaxSampleRate clamp
Commit 065118c also deleted
migrate_to_v11_6_5, which clampedMaxSampleRateinto LAME's supported [Hz_8000,Hz_48000] range on every startup (the fix for #1116). Its replacement,ValidateEnumSettings, only rejects values that fail to parse - butAAXClean.SampleRatedefinesHz_7350,Hz_64000,Hz_88200andHz_96000, so a hand-edited or pre-v11.6.5Settings.jsoncould carry a valid-but-unsupported rate straight into the encoder viaGetLameOptions. The clamp is restored in theMaxSampleRateproperty getter and setter (following theDailyDownloadLimitQuantitypattern), so it too no longer depends on a startup hook.(The third deleted migration,
migrate_to_v6_6_9's Serilog fixups, was left alone: its removal only softens log quality for configs that predate v6.6.9 and never ran a version in between, and force-rewritingoutputTemplateclashed with the commit's intent of not clobbering hand-edited configs.)Testing
Source/_Tests/LibationFileManager.Tests/QuickFiltersTests.cs: loading the exact JSON attached to the issue, the legacy string format, missing/malformed files, and restart-persistence scenarios (add -> reset -> still present; add after reset appends instead of overwriting;UseDefaultpersistence).Source/_Tests/LibationFileManager.Tests/MaxSampleRateTests.cs: default, in-range round-trips, setter clamping, and getter clamping of hand-edited out-of-range values.dotnet testfromSource/, all 8 projects, 1492 tests).!IsPodcast&!IsLiberated&!Absent, closed the app, relaunched, and the filter is present in the Quick Filters menu and applies correctly (Visible Books 30 -> 18).Filter added in the first session:
Quick filter added before restart
After restarting the app, the menu still has it and clicking it filters the grid:
quick_filter_persists_after_restart.mp4
WinForms note: the fixes are entirely in shared
LibationFileManagercode and the solution (includingLibationWinForms, which consumesMaxSampleRatein its settings dialog) compiles with 0 errors, but WinForms behaviour was not run on Windows.To show artifacts inline, enable in settings.