diff --git a/lib/features/reports/reports_page.dart b/lib/features/reports/reports_page.dart index 68b8a9c..a6c779c 100644 --- a/lib/features/reports/reports_page.dart +++ b/lib/features/reports/reports_page.dart @@ -47,33 +47,22 @@ class ReportsPage extends HookConsumerWidget { final theme = ShadTheme.of(context); final searchController = useTextEditingController(); final query = ref.watch(reportFilterProvider); - final snapshot = ref.watch(filteredReportsProvider); - final allReportsSnapshot = ref.watch(reportsProvider); + final snapshot = ref.watch(reportsProvider); final institutionsSnapshot = ref.watch(institutionsProvider); final controller = ref.read(reportFilterProvider.notifier); - final allReports = allReportsSnapshot.maybeWhen( - data: (items) => items, - orElse: () => const [], - ); final institutions = institutionsSnapshot.maybeWhen( data: (items) => items, orElse: () => const [], ); - useEffect(() { - if (searchController.text != query.search) { - searchController.text = query.search; - } - return null; - }, [query.search]); - return snapshot.when( - loading: () => const LoadingState(label: '正在搜索研报'), + loading: () => const LoadingState(label: '正在加载研报'), error: (error, _) => ErrorState( message: error.toString(), - onRetry: () => ref.invalidate(filteredReportsProvider), + onRetry: () => ref.invalidate(reportsProvider), ), - data: (items) { + data: (allReports) { + final items = _applyReportQuery(allReports, query); return SingleChildScrollView( padding: const EdgeInsets.fromLTRB( YantingSpacing.screenX, @@ -220,6 +209,39 @@ class ReportsPage extends HookConsumerWidget { } } +List _applyReportQuery( + List items, + ReportQuery query, +) { + final search = query.search.trim().toLowerCase(); + final filtered = items.where((item) { + final haystack = + '${item.titleCn} ${item.subtitleCn} ${item.oneLiner} ' + '${item.institution.nameCn} ${item.institution.nameEn} ' + '${item.topics.join(' ')}' + .toLowerCase(); + if (search.isNotEmpty && !haystack.contains(search)) { + return false; + } + if (query.topic != null && !item.topics.contains(query.topic)) { + return false; + } + if (query.institutionId != null && + item.institution.id != query.institutionId) { + return false; + } + if (query.hasAudio && !item.hasAudio) { + return false; + } + return true; + }).toList(); + filtered.sort((a, b) { + final result = (b.releasedAt ?? '').compareTo(a.releasedAt ?? ''); + return query.sort == ReportSort.oldest ? -result : result; + }); + return filtered; +} + void _openFilterSheet( BuildContext context, { required List items,