Commit ce6f54be3581d43afa5dd77544e890d263838567

Authored by 权海
1 parent ed5df73e

feat(ui):修复首页卡片点击异常

... ... @@ -100,6 +100,7 @@ class TodayController extends GetMaterialController {
final showHealthDataAuthCardStatus = 1.obs;
final stressSubtitle = ''.obs;
bool _isFirstLoad = true;
bool _isHandlingHealthAuthorizationTap = false;
// ── HRV 表盘引导 Banner ───────────────────
final showHrvAdBanner = false.obs;
... ... @@ -133,6 +134,8 @@ class TodayController extends GetMaterialController {
final v2RealtimeStress = Rxn<V2RealtimeStressData>();
final v2ActivityTarget = Rxn<V2ActivityTarget>();
int _currentStatus = 0;
@override
void onReady() {
super.onReady();
... ... @@ -160,9 +163,11 @@ class TodayController extends GetMaterialController {
unawaited(loadDataForDate(today));
// _checkHealthAuthStatus();
checkAddFriendVisible();
checkHrvAdBannerVisible();
checkHealthDataAuthCardVisible();
checkHealthDataAuthCardVisible(shouldCaculateAndUpload: true);
checkNotificationAuthorizationBannerVisible();
checkNotificationCardVisible();
if (!Get.find<UserStateService>().isVip) {
... ... @@ -290,40 +295,66 @@ class TodayController extends GetMaterialController {
}
}
Future<void> requestHealthAuthorization(
Future<void> _checkHealthAuthStatus(
{bool isPullToRefresh = false,
bool shouldCaculateAndUpload = false}) async {
final result = await _hostApi.checkHealthAppAuthorization();
_currentStatus = result.status;
_refreshHealthDataAuthCardStatus(status: _currentStatus);
if (_currentStatus != 1) {
return;
}
if (!shouldCaculateAndUpload) {
return;
}
_performCaculateAndUpload(isPullToRefresh: isPullToRefresh);
}
_performCaculateAndUpload({
bool isPullToRefresh = false,
}) {
_performHealthDataUpload();
_calculateHealthDataWithoutLoading(
uploaded: () async {
_refreshHealthDataAuthCardStatus(status: 1);
},
isPullToRefresh: isPullToRefresh,
);
}
Future<bool> requestHealthAuthorization(
{bool isFromNoPermissionPage = false}) async {
if (GetPlatform.isIOS) {
try {
final result = await _hostApi.checkHealthAppAuthorization();
AppLogger.d("checkHealthAppAuthorization : $result");
if (result.status == 0) {
await _checkHealthAuthStatus();
AppLogger.d("checkHealthAppAuthorization : $_currentStatus");
if (_currentStatus == 0) {
bool success = await _hostApi.requestHealthClientAuthorization();
AppLogger.d("requestHealthClientAuthorization : $success");
if (success) {
_currentStatus = 1;
_refreshHealthDataAuthCardStatus(status: 1);
// await LoadingService.instance.run(() async {
_performHealthDataUpload();
_startCoreCaculate(refreshAfterComplete: true);
_performCaculateAndUpload();
// });
// result.status = 1;
// AppToast.show('刷新完成');
if (isFromNoPermissionPage) {
Get.back();
}
return true;
} else {
// Get.to(NoHealthDataPage(
// onRefresh: _performDataUpload,
// ));
}
return;
} else if (result.status == 1) {
// await LoadingService.instance.run(() async {
_performHealthDataUpload();
_startCoreCaculate(refreshAfterComplete: true);
// });
return false;
} else if (_currentStatus == 1) {
_refreshHealthDataAuthCardStatus(status: 1);
if (isFromNoPermissionPage) {
Get.back();
}
return;
return true;
}
// 打开苹果健康
_platformHostApi.nativeHandleUrl('x-apple-health://');
... ... @@ -331,34 +362,54 @@ class TodayController extends GetMaterialController {
AppToast.show(e.toString());
}
}
return false;
}
Future<void> onAuthorizeTap() async {
if (_isHandlingHealthAuthorizationTap) {
AppLogger.d('TodayController.onAuthorizeTap ignored: handling');
return;
}
_isHandlingHealthAuthorizationTap = true;
ta.track('click_doublefeel_today_status', properties: {'ita': '授权访问健康数据'});
// if (showHealthDataAuthCardStatus.value == 1) {
// return;
// } else
if (showHealthDataAuthCardStatus.value == 0) {
await requestHealthAuthorization(isFromNoPermissionPage: true);
checkHealthDataAuthCardVisible();
} else {
await Get.to(NoHealthDataPage(
onRefresh: () {
refreshTab();
Future.delayed(const Duration(milliseconds: 800), () {
AppToast.show(l10n.refreshComplete);
});
},
onHelp: () {
Get.toNamed(Routes.HELP);
},
));
checkHealthDataAuthCardVisible();
try {
if (_currentStatus == 1 && hrvChartData.isNotEmpty) {
return;
} else if (_currentStatus == 0) {
final success = await requestHealthAuthorization();
if (success) {
_currentStatus = 1;
_refreshHealthDataAuthCardStatus(status: 1);
}
} else {
await Get.to(NoHealthDataPage(
onRefresh: () {
refreshTab();
Future.delayed(const Duration(milliseconds: 800), () {
AppToast.show(l10n.refreshComplete);
});
},
onHelp: () {
Get.toNamed(Routes.HELP);
},
));
checkHealthDataAuthCardVisible();
}
} finally {
_isHandlingHealthAuthorizationTap = false;
}
}
_refreshHealthDataAuthCardStatus({required int status}) {
if (status != 1) {
showHealthDataAuthCardStatus.value = status;
}
showHealthDataAuthCardStatus.value = hrvChartData.isEmpty ? -1 : status;
}
Future<void> checkHealthDataAuthCardVisible(
{bool isPullToRefresh = false}) async {
{bool isPullToRefresh = false,
bool shouldCaculateAndUpload = false}) async {
final firstTime = DateUtils.dateOnly(
DateTime(lastSelectableDay.value.year, lastSelectableDay.value.month - 6,
lastSelectableDay.value.day),
... ... @@ -368,27 +419,13 @@ class TodayController extends GetMaterialController {
firstSelectableDay.value = firstTime;
} else {
try {
final result = await _hostApi.checkHealthAppAuthorization();
ta.setSuperProperties(
{'health_data_permission': result.status.clamp(0, 1)});
if (result.status == 1) {
_calculateHealthDataWithoutLoading(
uploaded: () async {
if (DateUtils.isSameDay(
selectedDate.value, lastSelectableDay.value) &&
hrvChartData.isEmpty) {
showHealthDataAuthCardStatus.value = -1;
} else {
showHealthDataAuthCardStatus.value = result.status;
}
},
await _checkHealthAuthStatus(
isPullToRefresh: isPullToRefresh,
);
} else {
unawaited(loadDataForDate(selectedDate.value,
isPullToRefresh: isPullToRefresh));
showHealthDataAuthCardStatus.value = result.status;
}
shouldCaculateAndUpload: shouldCaculateAndUpload);
ta.setSuperProperties(
{'health_data_permission': _currentStatus.clamp(0, 1)});
unawaited(loadDataForDate(selectedDate.value,
isPullToRefresh: isPullToRefresh));
} catch (error, stackTrace) {
AppLogger.e(
'TodayController.checkHealthDataAuthCardVisible failed',
... ... @@ -415,11 +452,13 @@ class TodayController extends GetMaterialController {
}
case AppFailure():
}
showHealthDataAuthCardStatus.value = !hasUploaded ? -1 : result.status;
_refreshHealthDataAuthCardStatus(status: result.status);
}
void _calculateHealthDataWithoutLoading(
{Future<void> Function()? uploaded, bool isPullToRefresh = false}) {
{Future<void> Function()? uploaded,
bool isPullToRefresh = false,
bool refreshAfterComplete = true}) {
unawaited(
(() async {
try {
... ... @@ -427,6 +466,9 @@ class TodayController extends GetMaterialController {
await loadDataForDate(selectedDate.value,
isPullToRefresh: isPullToRefresh);
await uploaded?.call();
if (refreshAfterComplete) {
await loadDataForDate(selectedDate.value);
}
} catch (error, stackTrace) {
AppLogger.e('Apple Health calculate failed', error, stackTrace);
}
... ... @@ -749,7 +791,7 @@ class TodayController extends GetMaterialController {
changeDate(today);
checkAddFriendVisible();
checkHrvAdBannerVisible();
checkHealthDataAuthCardVisible();
checkHealthDataAuthCardVisible(shouldCaculateAndUpload: true);
checkNotificationAuthorizationBannerVisible();
_performHealthDataUpload();
// _startCoreCaculate();
... ... @@ -789,7 +831,7 @@ class TodayController extends GetMaterialController {
}
// 未决定 → 弹出系统授权弹窗
final result = await _platformHostApi.requestNotificationAuth();
await _platformHostApi.requestNotificationAuth();
// AppLogger.d(result.isGranted
// ? 'Notification authorization granted'
// : 'Notification authorization skipped');
... ...