fix router bug
This commit is contained in:
parent
0919ded628
commit
8ed21ca4a4
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -48,4 +48,4 @@ final class GoRouterProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$goRouterHash() => r'b559a84bcf9ae1ffda1deba4cf213f31a4006782';
|
String _$goRouterHash() => r'8e620e452bb81f2c6ed87b136283a9e508dca2e9';
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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(),
|
||||||
|
|||||||
@ -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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user