Commit dc2ea068cd28130ba7a192e2b725202b30760719

Authored by 常守达
1 parent 528f3532

fix(login): 苹果登录loading

@@ -335,7 +335,7 @@ class TodayController extends GetMaterialController { @@ -335,7 +335,7 @@ class TodayController extends GetMaterialController {
335 335
336 Future<void> onAuthorizeTap() async { 336 Future<void> onAuthorizeTap() async {
337 ta.track('click_doublefeel_today_status', properties: {'ita': '授权访问健康数据'}); 337 ta.track('click_doublefeel_today_status', properties: {'ita': '授权访问健康数据'});
338 - if (showHealthDataAuthCardStatus.value == 1) { 338 + if (showHealthDataAuthCardStatus.value == 1 && hrvChartData.isNotEmpty) {
339 return; 339 return;
340 } else if (showHealthDataAuthCardStatus.value == 0) { 340 } else if (showHealthDataAuthCardStatus.value == 0) {
341 await requestHealthAuthorization(isFromNoPermissionPage: true); 341 await requestHealthAuthorization(isFromNoPermissionPage: true);
@@ -344,6 +344,9 @@ class TodayController extends GetMaterialController { @@ -344,6 +344,9 @@ class TodayController extends GetMaterialController {
344 await Get.to(NoHealthDataPage( 344 await Get.to(NoHealthDataPage(
345 onRefresh: () { 345 onRefresh: () {
346 refreshTab(); 346 refreshTab();
  347 + Future.delayed(const Duration(milliseconds: 800), () {
  348 + AppToast.show(l10n.refreshComplete);
  349 + });
347 }, 350 },
348 onHelp: () { 351 onHelp: () {
349 Get.toNamed(Routes.HELP); 352 Get.toNamed(Routes.HELP);
@@ -61,24 +61,27 @@ class LoginController extends GetxController { @@ -61,24 +61,27 @@ class LoginController extends GetxController {
61 61
62 final newValue = !termsChecked.value; 62 final newValue = !termsChecked.value;
63 termsChecked.value = newValue; 63 termsChecked.value = newValue;
  64 +
  65 + // ① 写盘不 await,避免阻塞(SharedPrefs 写失败影响极小)
  66 + unawaited(Get.find<LocalStorage>().setTermsAgreed(newValue).catchError(
  67 + (e) => AppLogger.e('setTermsAgreed error: $e'),
  68 + ));
  69 +
  70 + if (newValue && !_userStateService.sdksInitialized) {
  71 + // ② SDK 初始化完全异步,不阻塞任何点击
  72 + unawaited(_initSdksAndTrack());
  73 + }
  74 + }
  75 +
  76 + Future<void> _initSdksAndTrack() async {
64 try { 77 try {
65 - final local = Get.find<LocalStorage>();  
66 - await local.setTermsAgreed(newValue);  
67 - if (newValue) {  
68 - unawaited(() async {  
69 - // 等待 Flutter 完成当前帧渲染,让勾选图标先显示  
70 - await WidgetsBinding.instance.endOfFrame;  
71 - if (!_userStateService.sdksInitialized) {  
72 - await _userStateService.initializeSdks();  
73 - }  
74 - if (needTrackWelcomepage) {  
75 - ta.track('enter_doublefeel_welcome_page');  
76 - needTrackWelcomepage = false;  
77 - }  
78 - }()); 78 + await _userStateService.initializeSdks();
  79 + if (needTrackWelcomepage) {
  80 + ta.track('enter_doublefeel_welcome_page');
  81 + needTrackWelcomepage = false;
79 } 82 }
80 } catch (e) { 83 } catch (e) {
81 - AppLogger.e(e.toString()); 84 + AppLogger.e('initializeSdks error: $e');
82 } 85 }
83 } 86 }
84 87
@@ -99,7 +102,7 @@ class LoginController extends GetxController { @@ -99,7 +102,7 @@ class LoginController extends GetxController {
99 try { 102 try {
100 final result = await LoadingService.instance.run(() async { 103 final result = await LoadingService.instance.run(() async {
101 return await PlatformHostApi().requestAppleSignIn(); 104 return await PlatformHostApi().requestAppleSignIn();
102 - }); 105 + }, type: LoadingType.circular);
103 // result 为 null 或 identityToken 为空,说明用户取消或苹果授权失败 106 // result 为 null 或 identityToken 为空,说明用户取消或苹果授权失败
104 if (result == null || 107 if (result == null ||
105 result.identityToken?.isNotEmpty != true || 108 result.identityToken?.isNotEmpty != true ||
@@ -2,6 +2,11 @@ import 'package:flutter/material.dart'; @@ -2,6 +2,11 @@ import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 import 'package:lottie/lottie.dart'; 3 import 'package:lottie/lottie.dart';
4 4
  5 +/// Loading 动画类型
  6 +/// - [lottie] 默认,使用 Lottie 动画(现有行为,保持不变)
  7 +/// - [circular] 使用系统 CircularProgressIndicator
  8 +enum LoadingType { lottie, circular }
  9 +
5 class LoadingService { 10 class LoadingService {
6 OverlayEntry? _entry; 11 OverlayEntry? _entry;
7 int _counter = 0; 12 int _counter = 0;
@@ -13,8 +18,9 @@ class LoadingService { @@ -13,8 +18,9 @@ class LoadingService {
13 static LoadingService get instance => Get.find(); 18 static LoadingService get instance => Get.find();
14 19
15 /// 包装一个异步操作,执行期间显示 Loading,完成后自动隐藏。 20 /// 包装一个异步操作,执行期间显示 Loading,完成后自动隐藏。
16 - Future<T> run<T>(Future<T> Function() block) async {  
17 - show(); 21 + Future<T> run<T>(Future<T> Function() block,
  22 + {LoadingType type = LoadingType.lottie}) async {
  23 + show(type: type);
18 try { 24 try {
19 return await block(); 25 return await block();
20 } finally { 26 } finally {
@@ -22,7 +28,7 @@ class LoadingService { @@ -22,7 +28,7 @@ class LoadingService {
22 } 28 }
23 } 29 }
24 30
25 - void show() { 31 + void show({LoadingType type = LoadingType.lottie}) {
26 _counter++; 32 _counter++;
27 if (_counter > 1) return; 33 if (_counter > 1) return;
28 34
@@ -35,7 +41,9 @@ class LoadingService { @@ -35,7 +41,9 @@ class LoadingService {
35 41
36 // 防御:清理可能残留的旧 entry 42 // 防御:清理可能残留的旧 entry
37 _entry?.remove(); 43 _entry?.remove();
38 - _entry = OverlayEntry(builder: (_) => const _GlobalLoadingWidget()); 44 + _entry = OverlayEntry(
  45 + builder: (_) => _GlobalLoadingWidget(type: type),
  46 + );
39 overlay.insert(_entry!); 47 overlay.insert(_entry!);
40 } 48 }
41 49
@@ -50,7 +58,9 @@ class LoadingService { @@ -50,7 +58,9 @@ class LoadingService {
50 } 58 }
51 59
52 class _GlobalLoadingWidget extends StatelessWidget { 60 class _GlobalLoadingWidget extends StatelessWidget {
53 - const _GlobalLoadingWidget(); 61 + const _GlobalLoadingWidget({this.type = LoadingType.lottie});
  62 +
  63 + final LoadingType type;
54 64
55 @override 65 @override
56 Widget build(BuildContext context) { 66 Widget build(BuildContext context) {
@@ -63,16 +73,27 @@ class _GlobalLoadingWidget extends StatelessWidget { @@ -63,16 +73,27 @@ class _GlobalLoadingWidget extends StatelessWidget {
63 color: Colors.black.withValues(alpha: 0.3), 73 color: Colors.black.withValues(alpha: 0.3),
64 child: Align( 74 child: Align(
65 alignment: const Alignment(0.0, -0.1), 75 alignment: const Alignment(0.0, -0.1),
66 - child: Lottie.asset(  
67 - 'assets/lottie/loading.json',  
68 - width: 130,  
69 - height: 90,  
70 - repeat: true,  
71 - animate: true,  
72 - ), 76 + child: _buildIndicator(),
73 ), 77 ),
74 ), 78 ),
75 ), 79 ),
76 ); 80 );
77 } 81 }
  82 +
  83 + Widget _buildIndicator() {
  84 + switch (type) {
  85 + case LoadingType.lottie:
  86 + return Lottie.asset(
  87 + 'assets/lottie/loading.json',
  88 + width: 130,
  89 + height: 90,
  90 + repeat: true,
  91 + animate: true,
  92 + );
  93 + case LoadingType.circular:
  94 + return const CircularProgressIndicator(
  95 + strokeWidth: 3,
  96 + );
  97 + }
  98 + }
78 } 99 }
@@ -771,5 +771,6 @@ @@ -771,5 +771,6 @@
771 "healthLocalNotificationRealtimeStressAttentionContent": "Your stress was elevated over the past 60 minutes. Consider relaxing and making time for rest and recovery.", 771 "healthLocalNotificationRealtimeStressAttentionContent": "Your stress was elevated over the past 60 minutes. Consider relaxing and making time for rest and recovery.",
772 "healthLocalNotificationRealtimeStressOverloadContent": "You stayed in a high-stress state over the past 60 minutes. Reduce exertion and prioritize rest and sleep.", 772 "healthLocalNotificationRealtimeStressOverloadContent": "You stayed in a high-stress state over the past 60 minutes. Reduce exertion and prioritize rest and sleep.",
773 "turnOnNotifications": "Turn on Notifications", 773 "turnOnNotifications": "Turn on Notifications",
774 - "stayUpToDateOnChangesInYourOwnAndYourFriendsHealth": "Stay up to date on changes in your own and your friends' health"  
775 -} 774 + "stayUpToDateOnChangesInYourOwnAndYourFriendsHealth": "Stay up to date on changes in your own and your friends' health",
  775 + "refreshComplete": "Refresh Complete"
  776 +}
@@ -1164,5 +1164,6 @@ @@ -1164,5 +1164,6 @@
1164 "healthLocalNotificationRealtimeStressAttentionContent": "你过去60分钟压力偏高,建议适当放松,并注意休息与恢复。", 1164 "healthLocalNotificationRealtimeStressAttentionContent": "你过去60分钟压力偏高,建议适当放松,并注意休息与恢复。",
1165 "healthLocalNotificationRealtimeStressOverloadContent": "你过去60分钟持续处于高压力状态,建议减少消耗,并优先保证休息与睡眠。", 1165 "healthLocalNotificationRealtimeStressOverloadContent": "你过去60分钟持续处于高压力状态,建议减少消耗,并优先保证休息与睡眠。",
1166 "turnOnNotifications": "开启通知", 1166 "turnOnNotifications": "开启通知",
1167 - "stayUpToDateOnChangesInYourOwnAndYourFriendsHealth": "及时了解自己和好友的健康波动"  
1168 -} 1167 + "stayUpToDateOnChangesInYourOwnAndYourFriendsHealth": "及时了解自己和好友的健康波动",
  1168 + "refreshComplete": "刷新完成"
  1169 +}
@@ -4149,6 +4149,12 @@ abstract class AppLocalizations { @@ -4149,6 +4149,12 @@ abstract class AppLocalizations {
4149 /// In zh, this message translates to: 4149 /// In zh, this message translates to:
4150 /// **'及时了解自己和好友的健康波动'** 4150 /// **'及时了解自己和好友的健康波动'**
4151 String get stayUpToDateOnChangesInYourOwnAndYourFriendsHealth; 4151 String get stayUpToDateOnChangesInYourOwnAndYourFriendsHealth;
  4152 +
  4153 + /// No description provided for @refreshComplete.
  4154 + ///
  4155 + /// In zh, this message translates to:
  4156 + /// **'刷新完成'**
  4157 + String get refreshComplete;
4152 } 4158 }
4153 4159
4154 class _AppLocalizationsDelegate 4160 class _AppLocalizationsDelegate
@@ -2336,4 +2336,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -2336,4 +2336,7 @@ class AppLocalizationsEn extends AppLocalizations {
2336 @override 2336 @override
2337 String get stayUpToDateOnChangesInYourOwnAndYourFriendsHealth => 2337 String get stayUpToDateOnChangesInYourOwnAndYourFriendsHealth =>
2338 'Stay up to date on changes in your own and your friends\' health'; 2338 'Stay up to date on changes in your own and your friends\' health';
  2339 +
  2340 + @override
  2341 + String get refreshComplete => 'Refresh Complete';
2339 } 2342 }
@@ -2232,4 +2232,7 @@ class AppLocalizationsZh extends AppLocalizations { @@ -2232,4 +2232,7 @@ class AppLocalizationsZh extends AppLocalizations {
2232 @override 2232 @override
2233 String get stayUpToDateOnChangesInYourOwnAndYourFriendsHealth => 2233 String get stayUpToDateOnChangesInYourOwnAndYourFriendsHealth =>
2234 '及时了解自己和好友的健康波动'; 2234 '及时了解自己和好友的健康波动';
  2235 +
  2236 + @override
  2237 + String get refreshComplete => '刷新完成';
2235 } 2238 }