169 lines
4.3 KiB
Dart
169 lines
4.3 KiB
Dart
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<String> {
|
|
RecommendTopicController() : super('全部');
|
|
|
|
void select(String topic) {
|
|
state = topic;
|
|
}
|
|
}
|
|
|
|
class ReportFilterController extends StateNotifier<ReportQuery> {
|
|
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<AuthState> {
|
|
AuthController(this._repository) : super(const AuthState()) {
|
|
_load();
|
|
}
|
|
|
|
final UserStateRepository _repository;
|
|
|
|
Future<void> _load() async {
|
|
state = state.copyWith(
|
|
loggedIn: await _repository.isLoggedIn(),
|
|
phone: await _repository.getPhone(),
|
|
loginMethod: await _repository.getLoginMethod(),
|
|
);
|
|
}
|
|
|
|
void requireLogin(PendingLoginAction action) {
|
|
if (state.loggedIn) return;
|
|
state = state.copyWith(pendingAction: action);
|
|
}
|
|
|
|
Future<PendingLoginAction?> login(LoginMethod method, {String? phone}) async {
|
|
final pending = state.pendingAction;
|
|
await _repository.login(method, phone: phone);
|
|
state = AuthState(
|
|
loggedIn: true,
|
|
phone: phone ?? await _repository.getPhone(),
|
|
loginMethod: method,
|
|
);
|
|
return pending;
|
|
}
|
|
|
|
Future<void> logout() async {
|
|
await _repository.logout();
|
|
state = const AuthState();
|
|
}
|
|
|
|
void clearPending() {
|
|
state = state.copyWith(pendingAction: null);
|
|
}
|
|
}
|
|
|
|
class ProfileController extends StateNotifier<ProfileState> {
|
|
ProfileController(this._repository) : super(const ProfileState()) {
|
|
refresh();
|
|
}
|
|
|
|
final UserStateRepository _repository;
|
|
|
|
Future<void> refresh() async {
|
|
state = ProfileState(
|
|
favorites: await _repository.getFavorites(),
|
|
savedListens: await _repository.getSavedListens(),
|
|
history: await _repository.getHistory(),
|
|
);
|
|
}
|
|
|
|
Future<void> toggleFavorite(String reportId) async {
|
|
await _repository.toggleFavorite(reportId);
|
|
await refresh();
|
|
}
|
|
|
|
Future<void> toggleSavedListen(String reportId) async {
|
|
await _repository.toggleSavedListen(reportId);
|
|
await refresh();
|
|
}
|
|
|
|
Future<void> addHistory(String reportId) async {
|
|
await _repository.addHistory(reportId);
|
|
await refresh();
|
|
}
|
|
}
|
|
|
|
class DetailNavigationController extends StateNotifier<DetailNavigationState> {
|
|
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<SheetState> {
|
|
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<ReportCardModel> reports;
|
|
|
|
List<ReportCardModel> byIds(Iterable<String> ids) {
|
|
final byId = {for (final report in reports) report.id: report};
|
|
return ids.map((id) => byId[id]).whereType<ReportCardModel>().toList();
|
|
}
|
|
}
|