fix router bug

This commit is contained in:
zyc 2026-02-10 09:41:40 +08:00
parent 0919ded628
commit 8ed21ca4a4
7 changed files with 23 additions and 33 deletions

View File

@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -11,7 +12,7 @@ TokenManager tokenManager(Ref ref) {
return TokenManager(); return TokenManager();
} }
class TokenManager { class TokenManager extends ChangeNotifier {
SharedPreferences? _prefs; SharedPreferences? _prefs;
Future<SharedPreferences> get _preferences async { Future<SharedPreferences> get _preferences async {
@ -26,6 +27,7 @@ class TokenManager {
final prefs = await _preferences; final prefs = await _preferences;
await prefs.setString(_keyAccessToken, access); await prefs.setString(_keyAccessToken, access);
await prefs.setString(_keyRefreshToken, refresh); await prefs.setString(_keyRefreshToken, refresh);
notifyListeners();
} }
Future<String?> getAccessToken() async { Future<String?> getAccessToken() async {
@ -47,5 +49,6 @@ class TokenManager {
final prefs = await _preferences; final prefs = await _preferences;
await prefs.remove(_keyAccessToken); await prefs.remove(_keyAccessToken);
await prefs.remove(_keyRefreshToken); await prefs.remove(_keyRefreshToken);
notifyListeners();
} }
} }

View File

@ -18,6 +18,7 @@ GoRouter goRouter(Ref ref) {
return GoRouter( return GoRouter(
initialLocation: '/login', initialLocation: '/login',
refreshListenable: tokenManager,
redirect: (context, state) async { redirect: (context, state) async {
final hasToken = await tokenManager.hasToken(); final hasToken = await tokenManager.hasToken();
final isLoginRoute = state.matchedLocation == '/login'; final isLoginRoute = state.matchedLocation == '/login';

View File

@ -48,4 +48,4 @@ final class GoRouterProvider
} }
} }
String _$goRouterHash() => r'b559a84bcf9ae1ffda1deba4cf213f31a4006782'; String _$goRouterHash() => r'8e620e452bb81f2c6ed87b136283a9e508dca2e9';

View File

@ -14,6 +14,7 @@ class AuthController extends _$AuthController {
state = const AsyncLoading(); state = const AsyncLoading();
final repository = ref.read(authRepositoryProvider); final repository = ref.read(authRepositoryProvider);
final result = await repository.sendCode(phone); final result = await repository.sendCode(phone);
if (!ref.mounted) return;
state = result.fold( state = result.fold(
(failure) => AsyncError(failure.message, StackTrace.current), (failure) => AsyncError(failure.message, StackTrace.current),
(_) => const AsyncData(null), (_) => const AsyncData(null),
@ -24,6 +25,7 @@ class AuthController extends _$AuthController {
state = const AsyncLoading(); state = const AsyncLoading();
final repository = ref.read(authRepositoryProvider); final repository = ref.read(authRepositoryProvider);
final result = await repository.codeLogin(phone, code); final result = await repository.codeLogin(phone, code);
if (!ref.mounted) return false;
return result.fold( return result.fold(
(failure) { (failure) {
state = AsyncError(failure.message, StackTrace.current); state = AsyncError(failure.message, StackTrace.current);
@ -40,6 +42,7 @@ class AuthController extends _$AuthController {
state = const AsyncLoading(); state = const AsyncLoading();
final repository = ref.read(authRepositoryProvider); final repository = ref.read(authRepositoryProvider);
final result = await repository.tokenLogin(token); final result = await repository.tokenLogin(token);
if (!ref.mounted) return false;
return result.fold( return result.fold(
(failure) { (failure) {
state = AsyncError(failure.message, StackTrace.current); state = AsyncError(failure.message, StackTrace.current);
@ -56,6 +59,7 @@ class AuthController extends _$AuthController {
state = const AsyncLoading(); state = const AsyncLoading();
final repository = ref.read(authRepositoryProvider); final repository = ref.read(authRepositoryProvider);
final result = await repository.logout(); final result = await repository.logout();
if (!ref.mounted) return;
state = result.fold( state = result.fold(
(failure) => AsyncError(failure.message, StackTrace.current), (failure) => AsyncError(failure.message, StackTrace.current),
(_) => const AsyncData(null), (_) => const AsyncData(null),
@ -66,6 +70,7 @@ class AuthController extends _$AuthController {
state = const AsyncLoading(); state = const AsyncLoading();
final repository = ref.read(authRepositoryProvider); final repository = ref.read(authRepositoryProvider);
final result = await repository.deleteAccount(); final result = await repository.deleteAccount();
if (!ref.mounted) return false;
return result.fold( return result.fold(
(failure) { (failure) {
state = AsyncError(failure.message, StackTrace.current); state = AsyncError(failure.message, StackTrace.current);

View File

@ -33,7 +33,7 @@ final class AuthControllerProvider
AuthController create() => AuthController(); AuthController create() => AuthController();
} }
String _$authControllerHash() => r'fac48518f4825055a266b5ea7e11163320342153'; String _$authControllerHash() => r'3a290ddd5b4b091786d5020ecb57b7fb1d3a287a';
abstract class _$AuthController extends $AsyncNotifier<void> { abstract class _$AuthController extends $AsyncNotifier<void> {
FutureOr<void> build(); FutureOr<void> build();

View File

@ -35,13 +35,16 @@ class _ProfileInfoPageState extends ConsumerState<ProfileInfoPage> {
super.dispose(); super.dispose();
} }
static const _genderToDisplay = {'male': '', 'female': ''};
static const _displayToGender = {'': 'male', '': 'female'};
void _initFromUser() { void _initFromUser() {
if (_initialized) return; if (_initialized) return;
final userAsync = ref.read(userControllerProvider); final userAsync = ref.read(userControllerProvider);
final user = userAsync.value; final user = userAsync.value;
if (user != null) { if (user != null) {
_nicknameController.text = user.nickname ?? ''; _nicknameController.text = user.nickname ?? '';
_gender = user.gender ?? ''; _gender = _genderToDisplay[user.gender] ?? user.gender ?? '';
_birthday = user.birthday ?? ''; _birthday = user.birthday ?? '';
_avatarUrl = user.avatar; _avatarUrl = user.avatar;
_initialized = true; _initialized = true;
@ -153,12 +156,7 @@ class _ProfileInfoPageState extends ConsumerState<ProfileInfoPage> {
Future<void> _saveProfile() async { Future<void> _saveProfile() async {
// //
String? genderCode; final genderCode = _displayToGender[_gender];
if (_gender == '') {
genderCode = 'M';
} else if (_gender == '') {
genderCode = 'F';
}
final success = await ref.read(userControllerProvider.notifier).updateProfile( final success = await ref.read(userControllerProvider.notifier).updateProfile(
nickname: _nicknameController.text.trim(), nickname: _nicknameController.text.trim(),

View File

@ -1,30 +1,13 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:airhub_app/main.dart'; import 'package:airhub_app/main.dart';
void main() { void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async { testWidgets('App smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame. await tester.pumpWidget(
await tester.pumpWidget(const MyApp()); const ProviderScope(child: AirhubApp()),
);
// Verify that our counter starts at 0. await tester.pumpAndSettle();
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
}); });
} }