|
@@ -10,10 +10,7 @@ import 'package:doublefeel_flutter/core/constants/app_const.dart'; |
|
@@ -10,10 +10,7 @@ import 'package:doublefeel_flutter/core/constants/app_const.dart'; |
|
10
|
import 'package:doublefeel_flutter/core/logging/app_logger.dart';
|
10
|
import 'package:doublefeel_flutter/core/logging/app_logger.dart';
|
|
11
|
import 'package:doublefeel_flutter/core/services/app_config_service.dart';
|
11
|
import 'package:doublefeel_flutter/core/services/app_config_service.dart';
|
|
12
|
import 'package:doublefeel_flutter/core/services/thinking_data_service.dart';
|
12
|
import 'package:doublefeel_flutter/core/services/thinking_data_service.dart';
|
|
13
|
-import 'package:doublefeel_flutter/data/models/local/user_preferences.dart';
|
|
|
|
14
|
-import 'package:doublefeel_flutter/l10n/gen/app_localizations.dart';
|
|
|
|
15
|
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
|
13
|
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
|
|
16
|
-import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
|
|
|
|
17
|
import 'package:doublefeel_flutter/pigeon/wechat_api.g.dart';
|
14
|
import 'package:doublefeel_flutter/pigeon/wechat_api.g.dart';
|
|
18
|
import 'package:flutter/services.dart';
|
15
|
import 'package:flutter/services.dart';
|
|
19
|
import 'package:flutter/widgets.dart';
|
16
|
import 'package:flutter/widgets.dart';
|
|
@@ -23,23 +20,14 @@ import 'package:doublefeel_flutter/core/network/api/user_api.dart'; |
|
@@ -23,23 +20,14 @@ import 'package:doublefeel_flutter/core/network/api/user_api.dart'; |
|
23
|
import 'package:doublefeel_flutter/core/network/api/vip_api.dart';
|
20
|
import 'package:doublefeel_flutter/core/network/api/vip_api.dart';
|
|
24
|
import 'package:doublefeel_flutter/core/platform/pigeon_api_facade.dart';
|
21
|
import 'package:doublefeel_flutter/core/platform/pigeon_api_facade.dart';
|
|
25
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
22
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
|
26
|
-import 'package:doublefeel_flutter/core/services/app_config_service.dart';
|
|
|
|
27
|
import 'package:doublefeel_flutter/core/services/loading_service.dart';
|
23
|
import 'package:doublefeel_flutter/core/services/loading_service.dart';
|
|
28
|
-import 'package:doublefeel_flutter/core/services/thinking_data_service.dart';
|
|
|
|
29
|
import 'package:doublefeel_flutter/core/services/user_state_service.dart';
|
24
|
import 'package:doublefeel_flutter/core/services/user_state_service.dart';
|
|
30
|
-import 'package:doublefeel_flutter/core/util/app_toast.dart';
|
|
|
|
31
|
import 'package:doublefeel_flutter/data/local/local_storage.dart';
|
25
|
import 'package:doublefeel_flutter/data/local/local_storage.dart';
|
|
32
|
import 'package:doublefeel_flutter/data/local/user_account_storage.dart';
|
26
|
import 'package:doublefeel_flutter/data/local/user_account_storage.dart';
|
|
33
|
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
|
27
|
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
|
|
34
|
-import 'package:doublefeel_flutter/data/models/local/user_preferences.dart';
|
|
|
|
35
|
import 'package:doublefeel_flutter/data/models/user/user_models.dart';
|
28
|
import 'package:doublefeel_flutter/data/models/user/user_models.dart';
|
|
36
|
import 'package:doublefeel_flutter/data/models/vip/vip_info.dart';
|
29
|
import 'package:doublefeel_flutter/data/models/vip/vip_info.dart';
|
|
37
|
-import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
|
|
|
|
38
|
-import 'package:doublefeel_flutter/pigeon/wechat_api.g.dart';
|
|
|
|
39
|
-import 'package:flutter/services.dart';
|
|
|
|
40
|
-import 'package:flutter/widgets.dart';
|
|
|
|
41
|
import 'package:flutter_timezone/flutter_timezone.dart';
|
30
|
import 'package:flutter_timezone/flutter_timezone.dart';
|
|
42
|
-import 'package:get/get.dart';
|
|
|
|
43
|
|
31
|
|
|
44
|
class LoginController extends GetxController {
|
32
|
class LoginController extends GetxController {
|
|
45
|
final UserApi _userApi = Get.find<UserApi>();
|
33
|
final UserApi _userApi = Get.find<UserApi>();
|
|
@@ -381,21 +369,39 @@ class LoginController extends GetxController { |
|
@@ -381,21 +369,39 @@ class LoginController extends GetxController { |
|
381
|
}
|
369
|
}
|
|
382
|
|
370
|
|
|
383
|
isLoggingIn.value = true;
|
371
|
isLoggingIn.value = true;
|
|
|
|
372
|
+ final loginStopwatch = Stopwatch()..start();
|
|
|
|
373
|
+ _logLoginTiming('phone_login.start');
|
|
384
|
try {
|
374
|
try {
|
|
385
|
await LoadingService.instance.run(() async {
|
375
|
await LoadingService.instance.run(() async {
|
|
386
|
- final loginRes = await _userApi.login(
|
|
|
|
387
|
- telephone: cleanPhone,
|
|
|
|
388
|
- verifyCode: codeInput.value,
|
376
|
+ final loginRes = await _measureLoginStep(
|
|
|
|
377
|
+ 'phone_login.api',
|
|
|
|
378
|
+ () => _userApi.login(
|
|
|
|
379
|
+ telephone: cleanPhone,
|
|
|
|
380
|
+ verifyCode: codeInput.value,
|
|
|
|
381
|
+ ),
|
|
389
|
);
|
382
|
);
|
|
390
|
|
383
|
|
|
391
|
if (loginRes is AppSuccess<LoginResponse>) {
|
384
|
if (loginRes is AppSuccess<LoginResponse>) {
|
|
392
|
- await _handleLoginSuccess(loginRes.data);
|
|
|
|
393
|
- await Get.find<LocalStorage>().setLastLoginMethod('phone');
|
|
|
|
394
|
- await environmentConfig.updateHideChooseRegion(true);
|
385
|
+ await _measureLoginStep(
|
|
|
|
386
|
+ 'phone_login.handle_success',
|
|
|
|
387
|
+ () => _handleLoginSuccess(loginRes.data),
|
|
|
|
388
|
+ );
|
|
|
|
389
|
+ await _measureLoginStep(
|
|
|
|
390
|
+ 'phone_login.persist_login_method',
|
|
|
|
391
|
+ () => Get.find<LocalStorage>().setLastLoginMethod('phone'),
|
|
|
|
392
|
+ );
|
|
|
|
393
|
+ await _measureLoginStep(
|
|
|
|
394
|
+ 'phone_login.persist_region_choice',
|
|
|
|
395
|
+ () => environmentConfig.updateHideChooseRegion(true),
|
|
|
|
396
|
+ );
|
|
395
|
}
|
397
|
}
|
|
396
|
});
|
398
|
});
|
|
397
|
} finally {
|
399
|
} finally {
|
|
398
|
isLoggingIn.value = false;
|
400
|
isLoggingIn.value = false;
|
|
|
|
401
|
+ loginStopwatch.stop();
|
|
|
|
402
|
+ _logLoginTiming(
|
|
|
|
403
|
+ 'phone_login.finish total_ms=${loginStopwatch.elapsedMilliseconds}',
|
|
|
|
404
|
+ );
|
|
399
|
}
|
405
|
}
|
|
400
|
}
|
406
|
}
|
|
401
|
|
407
|
|
|
@@ -595,7 +601,10 @@ class LoginController extends GetxController { |
|
@@ -595,7 +601,10 @@ class LoginController extends GetxController { |
|
595
|
}
|
601
|
}
|
|
596
|
}
|
602
|
}
|
|
597
|
|
603
|
|
|
598
|
- final regRes = await _userApi.register(registerData);
|
604
|
+ final regRes = await _measureLoginStep(
|
|
|
|
605
|
+ 'login_success.register',
|
|
|
|
606
|
+ () => _userApi.register(registerData),
|
|
|
|
607
|
+ );
|
|
599
|
if (regRes is AppSuccess<RegisterResponse>) {
|
608
|
if (regRes is AppSuccess<RegisterResponse>) {
|
|
600
|
accessToken = regRes.data.accessToken;
|
609
|
accessToken = regRes.data.accessToken;
|
|
601
|
} else {
|
610
|
} else {
|
|
@@ -605,12 +614,21 @@ class LoginController extends GetxController { |
|
@@ -605,12 +614,21 @@ class LoginController extends GetxController { |
|
605
|
}
|
614
|
}
|
|
606
|
|
615
|
|
|
607
|
// Fetch user info and VIP info
|
616
|
// Fetch user info and VIP info
|
|
608
|
- final userInfoResFuture = _userApi.getUserInfo(accessToken: accessToken);
|
617
|
+ final userInfoResFuture = _measureLoginStep(
|
|
|
|
618
|
+ 'login_success.get_user_info',
|
|
|
|
619
|
+ () => _userApi.getUserInfo(accessToken: accessToken),
|
|
|
|
620
|
+ );
|
|
609
|
final vipInfoResFuture = isRegister
|
621
|
final vipInfoResFuture = isRegister
|
|
610
|
? Future.value(null)
|
622
|
? Future.value(null)
|
|
611
|
- : _vipApi.getVipInfo(accessToken: accessToken);
|
623
|
+ : _measureLoginStep(
|
|
|
|
624
|
+ 'login_success.get_vip_info',
|
|
|
|
625
|
+ () => _vipApi.getVipInfo(accessToken: accessToken),
|
|
|
|
626
|
+ );
|
|
612
|
|
627
|
|
|
613
|
- final results = await Future.wait([userInfoResFuture, vipInfoResFuture]);
|
628
|
+ final results = await _measureLoginStep(
|
|
|
|
629
|
+ 'login_success.wait_user_and_vip',
|
|
|
|
630
|
+ () => Future.wait([userInfoResFuture, vipInfoResFuture]),
|
|
|
|
631
|
+ );
|
|
614
|
final userInfoRes = results[0];
|
632
|
final userInfoRes = results[0];
|
|
615
|
final vipInfoRes = results[1];
|
633
|
final vipInfoRes = results[1];
|
|
616
|
|
634
|
|
|
@@ -631,51 +649,36 @@ class LoginController extends GetxController { |
|
@@ -631,51 +649,36 @@ class LoginController extends GetxController { |
|
631
|
vip = vipInfoRes.data;
|
649
|
vip = vipInfoRes.data;
|
|
632
|
}
|
650
|
}
|
|
633
|
|
651
|
|
|
634
|
- await _userPrefs.updateFromLogin(
|
|
|
|
635
|
- accessToken: accessToken,
|
|
|
|
636
|
- me: me,
|
|
|
|
637
|
- partner: partner,
|
|
|
|
638
|
- vip: vip,
|
652
|
+ await _measureLoginStep(
|
|
|
|
653
|
+ 'login_success.persist_user_preferences',
|
|
|
|
654
|
+ () => _userPrefs.updateFromLogin(
|
|
|
|
655
|
+ accessToken: accessToken,
|
|
|
|
656
|
+ me: me,
|
|
|
|
657
|
+ partner: partner,
|
|
|
|
658
|
+ vip: vip,
|
|
|
|
659
|
+ ),
|
|
639
|
);
|
660
|
);
|
|
640
|
|
661
|
|
|
641
|
- try {
|
|
|
|
642
|
- if (Get.isRegistered<AppEnvironmentConfig>()) {
|
|
|
|
643
|
- var env = Get.find<AppEnvironmentConfig>();
|
|
|
|
644
|
- unawaited(
|
|
|
|
645
|
- AppPlatformHostApi()
|
|
|
|
646
|
- .updateLoginInfo(
|
|
|
|
647
|
- jsonEncode(UserPreferences(
|
|
|
|
648
|
- accessToken: accessToken,
|
|
|
|
649
|
- meUserInfo: me,
|
|
|
|
650
|
- partnerUserInfo: partner,
|
|
|
|
651
|
- vipInfo: vip != null
|
|
|
|
652
|
- ? UserPreferencesVipInfo.fromVipInfo(vip)
|
|
|
|
653
|
- : null,
|
|
|
|
654
|
- )),
|
|
|
|
655
|
- env.serverBaseUrl,
|
|
|
|
656
|
- )
|
|
|
|
657
|
- .catchError((Object error, StackTrace stackTrace) {
|
|
|
|
658
|
- AppLogger.e('Native login info sync failed', error, stackTrace);
|
|
|
|
659
|
- }),
|
|
|
|
660
|
- );
|
|
|
|
661
|
- }
|
|
|
|
662
|
- } on Exception catch (e) {
|
|
|
|
663
|
- AppLogger.e(e);
|
|
|
|
664
|
- }
|
|
|
|
665
|
-
|
|
|
|
666
|
- await _userStateService.onLogin();
|
662
|
+ await _measureLoginStep(
|
|
|
|
663
|
+ 'login_success.user_state_on_login',
|
|
|
|
664
|
+ _userStateService.onLogin,
|
|
|
|
665
|
+ );
|
|
667
|
if (isRegister) {
|
666
|
if (isRegister) {
|
|
668
|
ta.track('success_regist');
|
667
|
ta.track('success_regist');
|
|
669
|
}
|
668
|
}
|
|
670
|
|
669
|
|
|
671
|
// 用户登录成功即代表同意了协议,持久化到本地供冷启动时 SDK 初始化判断使用
|
670
|
// 用户登录成功即代表同意了协议,持久化到本地供冷启动时 SDK 初始化判断使用
|
|
672
|
- await Get.find<LocalStorage>().setTermsAgreed(true);
|
671
|
+ await _measureLoginStep(
|
|
|
|
672
|
+ 'login_success.persist_terms_agreed',
|
|
|
|
673
|
+ () => Get.find<LocalStorage>().setTermsAgreed(true),
|
|
|
|
674
|
+ );
|
|
673
|
|
675
|
|
|
674
|
// 根据引导完成状态决定跳转目标
|
676
|
// 根据引导完成状态决定跳转目标
|
|
675
|
final userId = me.id ?? 0;
|
677
|
final userId = me.id ?? 0;
|
|
676
|
if (_userAccount.hasCompletedOnboarding(userId) ||
|
678
|
if (_userAccount.hasCompletedOnboarding(userId) ||
|
|
677
|
me.isPassNoviceGuide == 1) {
|
679
|
me.isPassNoviceGuide == 1) {
|
|
678
|
// 该账号已完成引导,直接进主页
|
680
|
// 该账号已完成引导,直接进主页
|
|
|
|
681
|
+ _logLoginTiming('login_success.route_home');
|
|
679
|
Get.offAllNamed(AppRoutes.home);
|
682
|
Get.offAllNamed(AppRoutes.home);
|
|
680
|
} else {
|
683
|
} else {
|
|
681
|
// 新用户或未完成引导,进入引导页(支持断点续做)
|
684
|
// 新用户或未完成引导,进入引导页(支持断点续做)
|
|
@@ -689,4 +692,30 @@ class LoginController extends GetxController { |
|
@@ -689,4 +692,30 @@ class LoginController extends GetxController { |
|
689
|
// userInfoRes 失败,外层 finally 会重置 isLoggingIn
|
692
|
// userInfoRes 失败,外层 finally 会重置 isLoggingIn
|
|
690
|
}
|
693
|
}
|
|
691
|
}
|
694
|
}
|
|
|
|
695
|
+
|
|
|
|
696
|
+ Future<T> _measureLoginStep<T>(
|
|
|
|
697
|
+ String name,
|
|
|
|
698
|
+ Future<T> Function() operation,
|
|
|
|
699
|
+ ) async {
|
|
|
|
700
|
+ if (!environmentConfig.isDebug) return operation();
|
|
|
|
701
|
+ final stopwatch = Stopwatch()..start();
|
|
|
|
702
|
+ AppLogger.i('[LoginTiming] $name.start');
|
|
|
|
703
|
+ try {
|
|
|
|
704
|
+ return await operation();
|
|
|
|
705
|
+ } catch (error, stackTrace) {
|
|
|
|
706
|
+ AppLogger.e('[LoginTiming] $name.error', error, stackTrace);
|
|
|
|
707
|
+ rethrow;
|
|
|
|
708
|
+ } finally {
|
|
|
|
709
|
+ stopwatch.stop();
|
|
|
|
710
|
+ AppLogger.i(
|
|
|
|
711
|
+ '[LoginTiming] $name.finish elapsed_ms=${stopwatch.elapsedMilliseconds}',
|
|
|
|
712
|
+ );
|
|
|
|
713
|
+ }
|
|
|
|
714
|
+ }
|
|
|
|
715
|
+
|
|
|
|
716
|
+ void _logLoginTiming(String message) {
|
|
|
|
717
|
+ if (environmentConfig.isDebug) {
|
|
|
|
718
|
+ AppLogger.i('[LoginTiming] $message');
|
|
|
|
719
|
+ }
|
|
|
|
720
|
+ }
|
|
692
|
} |
721
|
} |