import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../models/models.dart'; import '../repositories/user_state_repository.dart'; import 'app_interaction_state.dart'; import 'report_query.dart'; class RecommendTopicController extends StateNotifier { RecommendTopicController() : super('全部'); void select(String topic) { state = topic; } } class ReportFilterController extends StateNotifier { ReportFilterController() : super(const ReportQuery()); void setSearch(String value) { state = state.copyWith(search: value); } void setTopic(String? topic) { state = state.copyWith(topic: topic); } void setInstitution(String? institutionId) { state = state.copyWith(institutionId: institutionId); } void toggleAudio() { state = state.copyWith(hasAudio: !state.hasAudio); } void setSort(ReportSort sort) { state = state.copyWith(sort: sort); } void reset() { state = const ReportQuery(); } } class AuthController extends StateNotifier { AuthController(this._repository) : super(const AuthState()) { _load(); } final UserStateRepository _repository; Future _load() async { state = state.copyWith(loggedIn: await _repository.isLoggedIn()); } void requireLogin(PendingLoginAction action) { if (state.loggedIn) return; state = state.copyWith(pendingAction: action); } Future login(LoginMethod method) async { final pending = state.pendingAction; await _repository.login(method); state = const AuthState(loggedIn: true); return pending; } Future logout() async { await _repository.logout(); state = const AuthState(); } void clearPending() { state = state.copyWith(pendingAction: null); } } class ProfileController extends StateNotifier { ProfileController(this._repository) : super(const ProfileState()) { refresh(); } final UserStateRepository _repository; Future refresh() async { state = ProfileState( favorites: await _repository.getFavorites(), savedListens: await _repository.getSavedListens(), history: await _repository.getHistory(), ); } Future toggleFavorite(String reportId) async { await _repository.toggleFavorite(reportId); await refresh(); } Future toggleSavedListen(String reportId) async { await _repository.toggleSavedListen(reportId); await refresh(); } Future addHistory(String reportId) async { await _repository.addHistory(reportId); await refresh(); } } class DetailNavigationController extends StateNotifier { DetailNavigationController() : super(const DetailNavigationState()); void rememberTabScroll(AppTab tab, double scrollTop) { state = state.copyWith(tabScroll: {...state.tabScroll, tab: scrollTop}); } void push(DetailStackEntry entry, {required AppTab originTab}) { final stack = [...state.stack, entry]; state = state.copyWith(originTab: originTab, stack: stack); } void updateCurrentScroll(double scrollTop) { if (state.stack.isEmpty) return; final stack = [...state.stack]; stack[stack.length - 1] = stack.last.copyWith(scrollTop: scrollTop); state = state.copyWith(stack: stack); } DetailStackEntry? pop() { if (state.stack.isEmpty) return null; final stack = [...state.stack]..removeLast(); state = state.copyWith(stack: stack); return stack.isEmpty ? null : stack.last; } void reset() { state = const DetailNavigationState(); } } class SheetController extends StateNotifier { SheetController() : super(const SheetState.hidden()); void show(SheetIntent intent) { state = SheetState.visible(intent); } void hide() { state = const SheetState.hidden(); } } class ProfileListBuilder { const ProfileListBuilder(this.reports); final List reports; List byIds(Iterable ids) { final byId = {for (final report in reports) report.id: report}; return ids.map((id) => byId[id]).whereType().toList(); } }