Showing
7 changed files
with
108 additions
and
36 deletions
| @@ -38,6 +38,7 @@ class ActivityBurnReportLogic extends ReportPeriodLogic { | @@ -38,6 +38,7 @@ class ActivityBurnReportLogic extends ReportPeriodLogic { | ||
| 38 | final weeklyReport = Rxn<WeeklyActivityBurnReport>(); | 38 | final weeklyReport = Rxn<WeeklyActivityBurnReport>(); |
| 39 | final monthlyReport = Rxn<MonthlyActivityBurnReport>(); | 39 | final monthlyReport = Rxn<MonthlyActivityBurnReport>(); |
| 40 | final _myUserId = Get.find<UserStateService>().userId; | 40 | final _myUserId = Get.find<UserStateService>().userId; |
| 41 | + int _reportRequestId = 0; | ||
| 41 | bool get isMySelf => | 42 | bool get isMySelf => |
| 42 | targetUserId.value == null || _myUserId == targetUserId.value; | 43 | targetUserId.value == null || _myUserId == targetUserId.value; |
| 43 | 44 | ||
| @@ -50,28 +51,40 @@ class ActivityBurnReportLogic extends ReportPeriodLogic { | @@ -50,28 +51,40 @@ class ActivityBurnReportLogic extends ReportPeriodLogic { | ||
| 50 | 51 | ||
| 51 | @override | 52 | @override |
| 52 | Future<void> loadReport() async { | 53 | Future<void> loadReport() async { |
| 53 | - isLoading.value = !isMySelf; | 54 | + final requestId = ++_reportRequestId; |
| 55 | + final period = selectedPeriod.value; | ||
| 56 | + final currentTargetUserId = targetUserId.value; | ||
| 57 | + final isCurrentUser = | ||
| 58 | + currentTargetUserId == null || _myUserId == currentTargetUserId; | ||
| 59 | + isLoading.value = !isCurrentUser; | ||
| 54 | 60 | ||
| 55 | try { | 61 | try { |
| 56 | - if (selectedPeriod.value == ReportPeriod.week) { | ||
| 57 | - weeklyReport.value = await repository.getWeeklyReport( | 62 | + if (period == ReportPeriod.week) { |
| 63 | + final result = await repository.getWeeklyReport( | ||
| 58 | weekStart, | 64 | weekStart, |
| 59 | - targetUserId: targetUserId.value, | 65 | + targetUserId: currentTargetUserId, |
| 60 | ); | 66 | ); |
| 61 | - } else if (selectedPeriod.value == ReportPeriod.month) { | 67 | + if (requestId != _reportRequestId) return; |
| 68 | + weeklyReport.value = result; | ||
| 69 | + } else if (period == ReportPeriod.month) { | ||
| 62 | final result = await repository.getMonthlyReport( | 70 | final result = await repository.getMonthlyReport( |
| 63 | monthStart, | 71 | monthStart, |
| 64 | - targetUserId: targetUserId.value, | 72 | + targetUserId: currentTargetUserId, |
| 65 | ); | 73 | ); |
| 74 | + if (requestId != _reportRequestId) return; | ||
| 66 | monthlyReport.value = result; | 75 | monthlyReport.value = result; |
| 67 | } else { | 76 | } else { |
| 68 | - report.value = await repository.getDailyReport( | 77 | + final result = await repository.getDailyReport( |
| 69 | selectedDate.value, | 78 | selectedDate.value, |
| 70 | - targetUserId: targetUserId.value, | 79 | + targetUserId: currentTargetUserId, |
| 71 | ); | 80 | ); |
| 81 | + if (requestId != _reportRequestId) return; | ||
| 82 | + report.value = result; | ||
| 72 | } | 83 | } |
| 73 | } finally { | 84 | } finally { |
| 74 | - isLoading.value = false; | 85 | + if (requestId == _reportRequestId) { |
| 86 | + isLoading.value = false; | ||
| 87 | + } | ||
| 75 | } | 88 | } |
| 76 | } | 89 | } |
| 77 | 90 |
| @@ -261,6 +261,8 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> { | @@ -261,6 +261,8 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> { | ||
| 261 | 261 | ||
| 262 | Future<void> _syncExternalQuery() async { | 262 | Future<void> _syncExternalQuery() async { |
| 263 | _syncingExternalQuery = true; | 263 | _syncingExternalQuery = true; |
| 264 | + final targetUserChanged = | ||
| 265 | + _logic.targetUserId.value != widget.query.targetUserId; | ||
| 264 | _logic.targetUserId.value = widget.query.targetUserId; | 266 | _logic.targetUserId.value = widget.query.targetUserId; |
| 265 | _logHrvTrend( | 267 | _logHrvTrend( |
| 266 | 'section_syncExternalQuery_start period=${widget.query.period.name} ' | 268 | 'section_syncExternalQuery_start period=${widget.query.period.name} ' |
| @@ -272,7 +274,9 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> { | @@ -272,7 +274,9 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> { | ||
| 272 | await _logic.selectQuery( | 274 | await _logic.selectQuery( |
| 273 | widget.query.period, | 275 | widget.query.period, |
| 274 | widget.query.date, | 276 | widget.query.date, |
| 275 | - forceRefresh: false, | 277 | + // A user switch can keep the same period and date. Refresh in that |
| 278 | + // case so the report is not left showing the previous user's data. | ||
| 279 | + forceRefresh: targetUserChanged, | ||
| 276 | ); | 280 | ); |
| 277 | } else { | 281 | } else { |
| 278 | _logic.initializeQuery(widget.query.period, widget.query.date); | 282 | _logic.initializeQuery(widget.query.period, widget.query.date); |
| @@ -387,9 +391,15 @@ class _ActivityBurnTrendSectionState extends State<_ActivityBurnTrendSection> { | @@ -387,9 +391,15 @@ class _ActivityBurnTrendSectionState extends State<_ActivityBurnTrendSection> { | ||
| 387 | 391 | ||
| 388 | Future<void> _syncExternalQuery() async { | 392 | Future<void> _syncExternalQuery() async { |
| 389 | _syncingExternalQuery = true; | 393 | _syncingExternalQuery = true; |
| 394 | + final targetUserChanged = | ||
| 395 | + _logic.targetUserId.value != widget.query.targetUserId; | ||
| 390 | _logic.targetUserId.value = widget.query.targetUserId; | 396 | _logic.targetUserId.value = widget.query.targetUserId; |
| 391 | try { | 397 | try { |
| 392 | - await _logic.selectQuery(widget.query.period, widget.query.date); | 398 | + await _logic.selectQuery( |
| 399 | + widget.query.period, | ||
| 400 | + widget.query.date, | ||
| 401 | + forceRefresh: targetUserChanged, | ||
| 402 | + ); | ||
| 393 | } finally { | 403 | } finally { |
| 394 | _syncingExternalQuery = false; | 404 | _syncingExternalQuery = false; |
| 395 | } | 405 | } |
| @@ -492,9 +502,15 @@ class _SleepTrendSectionState extends State<_SleepTrendSection> { | @@ -492,9 +502,15 @@ class _SleepTrendSectionState extends State<_SleepTrendSection> { | ||
| 492 | 502 | ||
| 493 | Future<void> _syncExternalQuery() async { | 503 | Future<void> _syncExternalQuery() async { |
| 494 | _syncingExternalQuery = true; | 504 | _syncingExternalQuery = true; |
| 505 | + final targetUserChanged = | ||
| 506 | + _logic.targetUserId.value != widget.query.targetUserId; | ||
| 495 | _logic.targetUserId.value = widget.query.targetUserId; | 507 | _logic.targetUserId.value = widget.query.targetUserId; |
| 496 | try { | 508 | try { |
| 497 | - await _logic.selectQuery(widget.query.period, widget.query.date); | 509 | + await _logic.selectQuery( |
| 510 | + widget.query.period, | ||
| 511 | + widget.query.date, | ||
| 512 | + forceRefresh: targetUserChanged, | ||
| 513 | + ); | ||
| 498 | } finally { | 514 | } finally { |
| 499 | _syncingExternalQuery = false; | 515 | _syncingExternalQuery = false; |
| 500 | } | 516 | } |
| @@ -63,6 +63,10 @@ class TrendController extends GetxController with HealthTrendControl { | @@ -63,6 +63,10 @@ class TrendController extends GetxController with HealthTrendControl { | ||
| 63 | final previousIndex = selectedTypeIndex.value; | 63 | final previousIndex = selectedTypeIndex.value; |
| 64 | super.changeType(index); | 64 | super.changeType(index); |
| 65 | if (_isPageVisible && selectedTypeIndex.value != previousIndex) { | 65 | if (_isPageVisible && selectedTypeIndex.value != previousIndex) { |
| 66 | + // The other report sections may have loaded while this tab was hidden. | ||
| 67 | + // Refresh only the newly selected section through its selected-state | ||
| 68 | + // guard so it does not show stale preloaded data. | ||
| 69 | + refreshToken.value++; | ||
| 66 | _trackEnterPage(); | 70 | _trackEnterPage(); |
| 67 | } | 71 | } |
| 68 | } | 72 | } |
| @@ -32,6 +32,7 @@ class HrvReportLogic extends ReportPeriodLogic { | @@ -32,6 +32,7 @@ class HrvReportLogic extends ReportPeriodLogic { | ||
| 32 | final yearlyReport = Rxn<YearlyHrvReport>(); | 32 | final yearlyReport = Rxn<YearlyHrvReport>(); |
| 33 | final HrvReportRepository repository; | 33 | final HrvReportRepository repository; |
| 34 | final _myUserId = Get.find<UserStateService>().userId; | 34 | final _myUserId = Get.find<UserStateService>().userId; |
| 35 | + int _reportRequestId = 0; | ||
| 35 | static const _logMarker = '[OHOS_HRV_TREND_PROFILE]'; | 36 | static const _logMarker = '[OHOS_HRV_TREND_PROFILE]'; |
| 36 | bool get isMySelf => | 37 | bool get isMySelf => |
| 37 | targetUserId.value == null || _myUserId == targetUserId.value; | 38 | targetUserId.value == null || _myUserId == targetUserId.value; |
| @@ -51,41 +52,51 @@ class HrvReportLogic extends ReportPeriodLogic { | @@ -51,41 +52,51 @@ class HrvReportLogic extends ReportPeriodLogic { | ||
| 51 | 52 | ||
| 52 | @override | 53 | @override |
| 53 | Future<void> loadReport() async { | 54 | Future<void> loadReport() async { |
| 55 | + final requestId = ++_reportRequestId; | ||
| 54 | final stopwatch = Stopwatch()..start(); | 56 | final stopwatch = Stopwatch()..start(); |
| 55 | final period = selectedPeriod.value; | 57 | final period = selectedPeriod.value; |
| 56 | final date = selectedDate.value; | 58 | final date = selectedDate.value; |
| 59 | + final currentTargetUserId = targetUserId.value; | ||
| 60 | + final isCurrentUser = | ||
| 61 | + currentTargetUserId == null || _myUserId == currentTargetUserId; | ||
| 57 | _log( | 62 | _log( |
| 58 | 'logic_load_start period=${period.name} date=$date ' | 63 | 'logic_load_start period=${period.name} date=$date ' |
| 59 | - 'targetUserId=${targetUserId.value} isMySelf=$isMySelf', | 64 | + 'targetUserId=$currentTargetUserId isMySelf=$isCurrentUser', |
| 60 | ); | 65 | ); |
| 61 | - isLoading.value = !isMySelf; | 66 | + isLoading.value = !isCurrentUser; |
| 62 | 67 | ||
| 63 | try { | 68 | try { |
| 64 | if (period == ReportPeriod.year) { | 69 | if (period == ReportPeriod.year) { |
| 65 | - yearlyReport.value = await repository.getYearlyReport( | 70 | + final result = await repository.getYearlyReport( |
| 66 | date.year, | 71 | date.year, |
| 67 | - targetUserId: targetUserId.value, | 72 | + targetUserId: currentTargetUserId, |
| 68 | ); | 73 | ); |
| 74 | + if (requestId != _reportRequestId) return; | ||
| 75 | + yearlyReport.value = result; | ||
| 69 | _log( | 76 | _log( |
| 70 | 'logic_assign_finish period=${period.name} ' | 77 | 'logic_assign_finish period=${period.name} ' |
| 71 | 'days=${yearlyReport.value?.days.length ?? 0} ' | 78 | 'days=${yearlyReport.value?.days.length ?? 0} ' |
| 72 | 'elapsedMs=${stopwatch.elapsedMilliseconds}', | 79 | 'elapsedMs=${stopwatch.elapsedMilliseconds}', |
| 73 | ); | 80 | ); |
| 74 | } else if (period == ReportPeriod.month) { | 81 | } else if (period == ReportPeriod.month) { |
| 75 | - monthlyReport.value = await repository.getMonthlyReport( | 82 | + final result = await repository.getMonthlyReport( |
| 76 | monthStart, | 83 | monthStart, |
| 77 | - targetUserId: targetUserId.value, | 84 | + targetUserId: currentTargetUserId, |
| 78 | ); | 85 | ); |
| 86 | + if (requestId != _reportRequestId) return; | ||
| 87 | + monthlyReport.value = result; | ||
| 79 | _log( | 88 | _log( |
| 80 | 'logic_assign_finish period=${period.name} ' | 89 | 'logic_assign_finish period=${period.name} ' |
| 81 | 'days=${monthlyReport.value?.days.length ?? 0} ' | 90 | 'days=${monthlyReport.value?.days.length ?? 0} ' |
| 82 | 'elapsedMs=${stopwatch.elapsedMilliseconds}', | 91 | 'elapsedMs=${stopwatch.elapsedMilliseconds}', |
| 83 | ); | 92 | ); |
| 84 | } else { | 93 | } else { |
| 85 | - weeklyReport.value = await repository.getWeeklyReport( | 94 | + final result = await repository.getWeeklyReport( |
| 86 | weekStart, | 95 | weekStart, |
| 87 | - targetUserId: targetUserId.value, | 96 | + targetUserId: currentTargetUserId, |
| 88 | ); | 97 | ); |
| 98 | + if (requestId != _reportRequestId) return; | ||
| 99 | + weeklyReport.value = result; | ||
| 89 | _log( | 100 | _log( |
| 90 | 'logic_assign_finish period=${period.name} ' | 101 | 'logic_assign_finish period=${period.name} ' |
| 91 | 'days=${weeklyReport.value?.days.length ?? 0} ' | 102 | 'days=${weeklyReport.value?.days.length ?? 0} ' |
| @@ -93,7 +104,9 @@ class HrvReportLogic extends ReportPeriodLogic { | @@ -93,7 +104,9 @@ class HrvReportLogic extends ReportPeriodLogic { | ||
| 93 | ); | 104 | ); |
| 94 | } | 105 | } |
| 95 | } finally { | 106 | } finally { |
| 96 | - isLoading.value = false; | 107 | + if (requestId == _reportRequestId) { |
| 108 | + isLoading.value = false; | ||
| 109 | + } | ||
| 97 | _log( | 110 | _log( |
| 98 | 'logic_load_finish period=$period date=$date ' | 111 | 'logic_load_finish period=$period date=$date ' |
| 99 | 'elapsedMs=${stopwatch.elapsedMilliseconds}', | 112 | 'elapsedMs=${stopwatch.elapsedMilliseconds}', |
| @@ -38,6 +38,7 @@ class SleepReportLogic extends ReportPeriodLogic { | @@ -38,6 +38,7 @@ class SleepReportLogic extends ReportPeriodLogic { | ||
| 38 | final weeklyReport = Rxn<WeeklySleepReport>(); | 38 | final weeklyReport = Rxn<WeeklySleepReport>(); |
| 39 | final monthlyReport = Rxn<MonthlySleepReport>(); | 39 | final monthlyReport = Rxn<MonthlySleepReport>(); |
| 40 | final _myUserId = Get.find<UserStateService>().userId; | 40 | final _myUserId = Get.find<UserStateService>().userId; |
| 41 | + int _reportRequestId = 0; | ||
| 41 | bool get isMySelf => | 42 | bool get isMySelf => |
| 42 | targetUserId.value == null || _myUserId == targetUserId.value; | 43 | targetUserId.value == null || _myUserId == targetUserId.value; |
| 43 | 44 | ||
| @@ -60,39 +61,64 @@ class SleepReportLogic extends ReportPeriodLogic { | @@ -60,39 +61,64 @@ class SleepReportLogic extends ReportPeriodLogic { | ||
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | Future<void> loadDailyReport() async { | 63 | Future<void> loadDailyReport() async { |
| 63 | - isLoading.value = !isMySelf; | 64 | + final requestId = ++_reportRequestId; |
| 65 | + final date = selectedDate.value; | ||
| 66 | + final currentTargetUserId = targetUserId.value; | ||
| 67 | + final isCurrentUser = | ||
| 68 | + currentTargetUserId == null || _myUserId == currentTargetUserId; | ||
| 69 | + isLoading.value = !isCurrentUser; | ||
| 64 | try { | 70 | try { |
| 65 | - report.value = await repository.getDailyReport( | ||
| 66 | - selectedDate.value, | ||
| 67 | - targetUserId: targetUserId.value, | 71 | + final result = await repository.getDailyReport( |
| 72 | + date, | ||
| 73 | + targetUserId: currentTargetUserId, | ||
| 68 | ); | 74 | ); |
| 75 | + if (requestId != _reportRequestId) return; | ||
| 76 | + report.value = result; | ||
| 69 | } finally { | 77 | } finally { |
| 70 | - isLoading.value = false; | 78 | + if (requestId == _reportRequestId) { |
| 79 | + isLoading.value = false; | ||
| 80 | + } | ||
| 71 | } | 81 | } |
| 72 | } | 82 | } |
| 73 | 83 | ||
| 74 | Future<void> loadWeeklyReport() async { | 84 | Future<void> loadWeeklyReport() async { |
| 75 | - isLoading.value = !isMySelf; | 85 | + final requestId = ++_reportRequestId; |
| 86 | + final currentTargetUserId = targetUserId.value; | ||
| 87 | + final isCurrentUser = | ||
| 88 | + currentTargetUserId == null || _myUserId == currentTargetUserId; | ||
| 89 | + isLoading.value = !isCurrentUser; | ||
| 76 | try { | 90 | try { |
| 77 | - weeklyReport.value = await repository.getWeeklyReport( | 91 | + final result = await repository.getWeeklyReport( |
| 78 | weekStart, | 92 | weekStart, |
| 79 | - targetUserId: targetUserId.value, | 93 | + targetUserId: currentTargetUserId, |
| 80 | ); | 94 | ); |
| 95 | + if (requestId != _reportRequestId) return; | ||
| 96 | + weeklyReport.value = result; | ||
| 81 | } finally { | 97 | } finally { |
| 82 | - isLoading.value = false; | 98 | + if (requestId == _reportRequestId) { |
| 99 | + isLoading.value = false; | ||
| 100 | + } | ||
| 83 | } | 101 | } |
| 84 | } | 102 | } |
| 85 | 103 | ||
| 86 | Future<void> loadMonthlyReport() async { | 104 | Future<void> loadMonthlyReport() async { |
| 87 | - isLoading.value = !isMySelf; | 105 | + final requestId = ++_reportRequestId; |
| 106 | + final currentTargetUserId = targetUserId.value; | ||
| 107 | + final isCurrentUser = | ||
| 108 | + currentTargetUserId == null || _myUserId == currentTargetUserId; | ||
| 109 | + isLoading.value = !isCurrentUser; | ||
| 88 | monthlyReport.value = null; | 110 | monthlyReport.value = null; |
| 89 | try { | 111 | try { |
| 90 | - monthlyReport.value = await repository.getMonthlyReport( | 112 | + final result = await repository.getMonthlyReport( |
| 91 | monthStart, | 113 | monthStart, |
| 92 | - targetUserId: targetUserId.value, | 114 | + targetUserId: currentTargetUserId, |
| 93 | ); | 115 | ); |
| 116 | + if (requestId != _reportRequestId) return; | ||
| 117 | + monthlyReport.value = result; | ||
| 94 | } finally { | 118 | } finally { |
| 95 | - isLoading.value = false; | 119 | + if (requestId == _reportRequestId) { |
| 120 | + isLoading.value = false; | ||
| 121 | + } | ||
| 96 | } | 122 | } |
| 97 | } | 123 | } |
| 98 | 124 |
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | "app": { | 2 | "app": { |
| 3 | "bundleName": "com.doublefeel.hmapp", | 3 | "bundleName": "com.doublefeel.hmapp", |
| 4 | "vendor": "DiDi", | 4 | "vendor": "DiDi", |
| 5 | - "versionCode": 103, | 5 | + "versionCode": 104, |
| 6 | "versionName": "2.7.0", | 6 | "versionName": "2.7.0", |
| 7 | "icon": "$media:layered_image", | 7 | "icon": "$media:layered_image", |
| 8 | "label": "$string:app_name" | 8 | "label": "$string:app_name" |
| @@ -2,7 +2,7 @@ name: doublefeel_flutter | @@ -2,7 +2,7 @@ name: doublefeel_flutter | ||
| 2 | description: "A new Flutter project." | 2 | description: "A new Flutter project." |
| 3 | publish_to: 'none' | 3 | publish_to: 'none' |
| 4 | 4 | ||
| 5 | -version: 2.7.0+103 | 5 | +version: 2.7.0+104 |
| 6 | 6 | ||
| 7 | environment: | 7 | environment: |
| 8 | sdk: ^3.6.2 | 8 | sdk: ^3.6.2 |
-
Please register or login to post a comment