diff --git a/lib/pages/download_page.dart b/lib/pages/download_page.dart index b252fb9..0cbb438 100644 --- a/lib/pages/download_page.dart +++ b/lib/pages/download_page.dart @@ -791,10 +791,10 @@ class _DownloadPageState extends State { } } if (!mounted || widget.runtime != runtime) return; - final count = groups.values.fold( - 0, - (sum, tasks) => sum + tasks.length, - ); + final selected = groups.values.expand((tasks) => tasks).toList(); + final count = selected.length; + final hiddenSelected = + count - _matchingDownloads(selected, _downloadFilter).length; final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( @@ -803,6 +803,7 @@ class _DownloadPageState extends State { content: Text( '共 ${groups.length} 个路径,预计释放 ${_bytes(estimatedBytes)}' '${unknownSizes > 0 ? "(另有 $unknownSizes 个路径大小未知或文件已缺失)" : ""}。\n\n' + '${hiddenSelected > 0 ? "其中 $hiddenSelected 条已选声音不在当前搜索结果中,也将删除其音频。\n\n" : ""}' '正在使用这些文件的播放会停止。任务和扣时记录保留;缺失文件不会记为主动删除。', ), actions: [ @@ -1145,30 +1146,41 @@ class _DownloadPageState extends State { } } - Widget _downloadedLibrary(List completed) { - final compact = MediaQuery.sizeOf(context).width < 320; - final query = _downloadFilter; + List _matchingDownloads( + List tasks, + String query, + ) { + if (query.isEmpty) return tasks; final tokens = query .split(RegExp(r'\s+')) .where((value) => value.isNotEmpty); - final matches = query.isEmpty - ? const [] - : completed.where((task) { - final track = task.track; - final text = [ - _downloadAlbumTitle(task), - track.album, - track.title, - for (final ordinal in { - track.officialPosition, - track.orderNo, - track.episode, - }.whereType()) - '$ordinal 第${ordinal}集', - ].join(' ').toLowerCase(); - return tokens.every(text.contains); - }).toList(); - final visible = query.isEmpty ? completed : matches; + return tasks.where((task) { + final track = task.track; + final text = [ + _downloadAlbumTitle(task), + track.album, + track.title, + for (final ordinal in { + track.officialPosition, + track.orderNo, + track.episode, + }.whereType()) + '$ordinal 第${ordinal}集', + ].join(' ').toLowerCase(); + return tokens.every(text.contains); + }).toList(); + } + + Widget _downloadedLibrary(List completed) { + final compact = MediaQuery.sizeOf(context).width < 320; + final query = _downloadFilter; + final visible = _matchingDownloads(completed, query); + final hiddenSelected = query.isEmpty || _selectedDownloads.isEmpty + ? 0 + : _selectedDownloads.length - + visible + .where((task) => _selectedDownloads.contains(task.id)) + .length; return LayoutBuilder( builder: (context, constraints) => Column( children: [ @@ -1248,7 +1260,10 @@ class _DownloadPageState extends State { label: const Text('多选音频'), ) else ...[ - Text('已选 ${_selectedDownloads.length} 条'), + Text( + '已选 ${_selectedDownloads.length} 条' + '${hiddenSelected > 0 ? "(含 $hiddenSelected 条未显示)" : ""}', + ), TextButton( onPressed: _deletingAudio || visible.isEmpty ? null @@ -1293,7 +1308,7 @@ class _DownloadPageState extends State { Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), child: Text( - '本地下载记录:匹配 ${matches.length} / 共 ${completed.length} 条', + '本地下载记录:匹配 ${visible.length} / 共 ${completed.length} 条', ), ), if (query.isNotEmpty && _error != null) @@ -1313,14 +1328,14 @@ class _DownloadPageState extends State { Expanded( child: query.isEmpty ? _albumList(completed, downloaded: true) - : matches.isEmpty + : visible.isEmpty ? const Center(child: Text('未找到匹配的本地下载记录')) : Scrollbar( child: ListView.builder( key: ValueKey('downloadSearch:$query'), - itemCount: matches.length, + itemCount: visible.length, itemBuilder: (context, index) => _downloadedTrack( - matches[index], + visible[index], compact, searchResult: true, ),