splash_controller.dart
3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import 'package:doublefeel_flutter/core/logging/app_diagnostic_log_store.dart';
import 'package:doublefeel_flutter/core/services/raw_data_service/health_raw_data_core_service.dart';
import 'package:doublefeel_flutter/core/util/app_toast.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import '../../../routes/app_pages.dart';
import '../../../../core/error/app_error.dart';
import '../../../../core/network/api/user_api.dart';
import '../../../../core/network/api/vip_api.dart';
import '../../../../core/result/app_result.dart';
import '../../../../core/services/user_state_service.dart';
import '../../../../data/local/user_preferences_storage.dart';
import '../../../../data/models/local/user_preferences.dart';
/// Cold-start routing: restore session or open login.
class SplashController extends GetxController {
SplashController(
this._userPrefs,
this._userApi,
this._vipApi,
this._userStateService,
);
final UserPreferencesStorage _userPrefs;
final UserApi _userApi;
final VipApi _vipApi;
final UserStateService _userStateService;
final HealthRawDataCoreService _healthRawDataCoreService =
Get.find<HealthRawDataCoreService>();
@override
void onInit() {
super.onInit();
SchedulerBinding.instance.addPostFrameCallback((_) {
_resolveInitialRoute();
});
}
Future<void> _resolveInitialRoute() async {
final token = _userPrefs.accessToken;
if (token.isEmpty) {
final splashDelay =
Get.testMode ? Duration.zero : const Duration(milliseconds: 800);
await Future<void>.delayed(splashDelay);
AppDiagnosticLogStore.instance.log(
category: 'Splash',
action: 'navigate_to_login_due_to_empty_token',
details: {},
);
Get.offAllNamed(AppRoutes.login);
return;
}
final ok = await _refreshSession();
if (ok) {
await _userStateService.onLogin();
try {
_healthRawDataCoreService.startCoreCaculate();
} catch (_) {}
await Get.offAllNamed(AppRoutes.home);
} else {
AppDiagnosticLogStore.instance.log(
category: 'Splash',
action: 'navigate_to_login_due_to_session_refresh_failed',
details: {
'tokenLength': token.length,
},
);
Get.offAllNamed(AppRoutes.login);
}
}
Future<bool> _refreshSession() async {
final userResult = await _userApi.getUserInfo(errorHandlingPolicy: null);
switch (userResult) {
case AppSuccess(:final data):
try {
await _userPrefs.updateMeUserInfo(data);
} catch (_) {}
// 刷新 VIP 信息缓存(失败不影响进入主页)
final vipResult = await _vipApi.getVipInfo();
if (vipResult case AppSuccess(data: final vip)) {
await _userPrefs
.updateVipInfo(UserPreferencesVipInfo.fromVipInfo(vip));
}
return true;
case AppFailure(:final error):
AppDiagnosticLogStore.instance.log(
category: 'Splash',
action: 'refresh_session_failure',
details: {
'errorType': error.runtimeType.toString(),
'displayMessage': error.displayMessage,
},
);
if (error.isAccessTokenInvalid) {
return false;
}
AppToast.show(
l10n.noInternetConnectionPleaseCheckYourInternetConnection);
return true;
}
}
}