Fix critical data loss bugs and improve error handling
## Critical Fixes - Fix CRITICAL-1: Empty scans no longer delete entire library - Use timestamp-based tombstone logic instead of path-based - Only mark missing if livePaths is not empty - Fix CRITICAL-2: Re-scanned files now return from deleted state - Add deleted=false to SongsCompanion.insert in both scanners ## High Priority Fixes - HIGH-1: Fix SQLite variable limit crash on large libraries - Replace isNotIn() with timestamp comparison (O(1) not O(n)) - HIGH-2: Fix UI freezing during scan - Throttle progress updates (every 50 files or end of scan) - HIGH-3: Add error handling for scan failures - Wrap scanFolders/scanAndroidMediaStore in try/catch - Display scanError banner in LibraryScreen - HIGH-4: Add error handling for playback failures - Wrap loadPlaylist in try/catch ## Medium Priority Fixes - MEDIUM-1: Replace ! with ?? to handle unknown ProcessingState - MEDIUM-2: Escape LIKE wildcards in search queries - MEDIUM-4: Display StreamBuilder errors instead of treating as empty - MEDIUM-8: Add tooltips to all IconButtons for accessibility - Add doc comments to public database APIs ## Testing - Add regression tests for CRITICAL-1 and CRITICAL-2 - All 9 existing tests pass Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
b5ab7bd9dd
commit
4fa8d12fa0
@@ -98,6 +98,8 @@ class _ProgressBar extends StatelessWidget {
|
||||
Slider(
|
||||
value: valueMs,
|
||||
max: maxMs,
|
||||
semanticFormatterCallback: (v) =>
|
||||
_fmt(Duration(milliseconds: v.round())),
|
||||
onChanged: hasDuration
|
||||
? (v) => handler.seek(Duration(milliseconds: v.round()))
|
||||
: null,
|
||||
@@ -146,6 +148,7 @@ class _Controls extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: 'Zufallswiedergabe',
|
||||
icon: Icon(Icons.shuffle,
|
||||
color: shuffle ? MeloTheme.red : Colors.white54),
|
||||
onPressed: () => handler.setShuffleMode(shuffle
|
||||
@@ -153,22 +156,26 @@ class _Controls extends StatelessWidget {
|
||||
: AudioServiceShuffleMode.all),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Vorheriger Titel',
|
||||
iconSize: 40,
|
||||
icon: const Icon(Icons.skip_previous),
|
||||
onPressed: handler.skipToPrevious,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: playing ? 'Pause' : 'Abspielen',
|
||||
iconSize: 64,
|
||||
icon: Icon(playing ? Icons.pause_circle : Icons.play_circle,
|
||||
color: MeloTheme.red),
|
||||
onPressed: playing ? handler.pause : handler.play,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Nächster Titel',
|
||||
iconSize: 40,
|
||||
icon: const Icon(Icons.skip_next),
|
||||
onPressed: handler.skipToNext,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Wiederholen',
|
||||
icon: Icon(
|
||||
repeat == AudioServiceRepeatMode.one
|
||||
? Icons.repeat_one
|
||||
|
||||
Reference in New Issue
Block a user