From 3470e1bfefc26541e65e92f57cd9e81ddd756441 Mon Sep 17 00:00:00 2001 From: JulianAlcala Date: Wed, 22 Apr 2026 22:45:18 +0200 Subject: [PATCH] refactor(device_management): migrate activity_meter to Riverpod --- .../presentation/activity_meter_screen.dart | 83 ++++------ .../activity_meter_aggregator.dart | 6 +- .../activity_meter_controller.dart} | 148 +++++++----------- .../activity_meter_controller.g.dart | 64 ++++++++ .../activity_meter_state.dart} | 28 ++-- .../activity_meter_state.freezed.dart} | 117 +++++++------- .../providers/pedometer_controller.dart | 38 +++++ .../providers/pedometer_controller.g.dart | 56 +++++++ .../widgets/activity_footers.dart | 2 +- .../widgets/hourly_bar_chart.dart | 2 +- .../widgets/pedometer_toggle.dart | 44 +++--- .../widgets/period_stats_cards.dart | 2 +- .../presentation/widgets/steps_bar_chart.dart | 2 +- .../widgets/steps_history_section.dart | 2 +- .../pedometer_controller_test.dart | 90 +++++++++++ 15 files changed, 438 insertions(+), 246 deletions(-) rename modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/{state => providers}/activity_meter_aggregator.dart (91%) rename modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/{state/activity_meter_view_model.dart => providers/activity_meter_controller.dart} (54%) create mode 100644 modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.g.dart rename modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/{state/activity_meter_view_state.dart => providers/activity_meter_state.dart} (65%) rename modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/{state/activity_meter_view_state.freezed.dart => providers/activity_meter_state.freezed.dart} (82%) create mode 100644 modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.dart create mode 100644 modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.g.dart create mode 100644 modules/legacy/modules/device_management/test/features/activity_meter/pedometer_controller_test.dart diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart index 1ca0a5ed..f88675ac 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/activity_meter_screen.dart @@ -1,48 +1,28 @@ -import 'package:design_system/design_system.dart'; +import 'package:device_management/src/core/presentation/format_date.dart'; +import 'package:device_management/src/core/presentation/time_range.dart'; +import 'package:device_management/src/core/presentation/widgets/time_range_selector.dart'; +import 'package:device_management/src/features/activity_meter/presentation/providers/activity_meter_controller.dart'; +import 'package:device_management/src/features/activity_meter/presentation/providers/activity_meter_state.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/activity_footers.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/hourly_bar_chart.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/pedometer_toggle.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/section_header.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/steps_history_section.dart'; +import 'package:device_management/src/features/activity_meter/presentation/widgets/steps_progress_ring.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:legacy_ui/legacy_ui.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; -import '../../../core/presentation/format_date.dart'; -import '../../../core/presentation/time_range.dart'; -import '../../../core/presentation/widgets/time_range_selector.dart'; -import 'state/activity_meter_view_model.dart'; -import 'state/activity_meter_view_state.dart'; -import 'widgets/activity_footers.dart'; -import 'widgets/hourly_bar_chart.dart'; -import 'widgets/pedometer_toggle.dart'; -import 'widgets/section_header.dart'; -import 'widgets/steps_bar_chart.dart'; -import 'widgets/steps_history_section.dart'; -import 'widgets/steps_progress_ring.dart'; - class ActivityMeterScreen extends ConsumerWidget { const ActivityMeterScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final isLoading = ref.watch( - activityMeterViewModelProvider.select((s) => s.isLoading), - ); - - ref.listen(activityMeterViewModelProvider.select((s) => s.errorEvent), ( - _, - next, - ) { - if (next == null) return; - final message = switch (next) { - ActivityMeterErrorEvent.loadData || - ActivityMeterErrorEvent.loadMore => context.translate( - I18n.errorActivityData, - ), - ActivityMeterErrorEvent.pedometer => context.translate( - I18n.errorPedometer, - ), - }; - showTopSnackbar(context, message: message, type: MessageType.error); - }); + final isLoading = + ref.watch(activityMeterControllerProvider.select((s) => s.isLoading)); return LegacyPageLayout( title: context.translate(I18n.activityMeter), @@ -58,10 +38,9 @@ class _ActivityMeterBody extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final vm = ref.read(activityMeterViewModelProvider.notifier); - final timeRange = ref.watch( - activityMeterViewModelProvider.select((s) => s.timeRange), - ); + final timeRange = ref + .watch(activityMeterControllerProvider.select((s) => s.timeRange)); + final notifier = ref.read(activityMeterControllerProvider.notifier); return SingleChildScrollView( child: Column( @@ -73,8 +52,8 @@ class _ActivityMeterBody extends ConsumerWidget { const _ActivityRangeHeader(), TimeRangeSelector( selected: timeRange, - onSelected: vm.selectTimeRange, - onCustomTap: () => _pickCustomRange(context, vm), + onSelected: notifier.selectTimeRange, + onCustomTap: () => _pickCustomRange(context, notifier), ), const _ActivitySection(), if (timeRange != TimeRange.today) const _HistorySection(), @@ -86,7 +65,7 @@ class _ActivityMeterBody extends ConsumerWidget { Future _pickCustomRange( BuildContext context, - ActivityMeterViewModel vm, + ActivityMeterController notifier, ) async { final now = DateTime.now(); final picked = await showDateRangePicker( @@ -95,7 +74,7 @@ class _ActivityMeterBody extends ConsumerWidget { lastDate: now, ); if (picked != null) { - vm.selectCustomRange(picked.start, picked.end); + notifier.selectCustomRange(picked.start, picked.end); } } } @@ -106,7 +85,7 @@ class _TodaySection extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final (todayTotal, dailyGoal) = ref.watch( - activityMeterViewModelProvider.select( + activityMeterControllerProvider.select( (s) => (s.todayTotal, s.dailyGoal), ), ); @@ -125,7 +104,9 @@ class _TodaySection extends ConsumerWidget { textAlign: TextAlign.center, style: TextStyle( fontSize: SizeUtils.getByScreen(small: 13, big: 12), - color: Theme.of(context).colorScheme.onSurface + color: Theme.of(context) + .colorScheme + .onSurface .withValues(alpha: 0.5), ), ), @@ -141,7 +122,7 @@ class _ActivityRangeHeader extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final (start, end, timeRange) = ref.watch( - activityMeterViewModelProvider.select( + activityMeterControllerProvider.select( (s) => (s.rangeStart, s.rangeEnd, s.timeRange), ), ); @@ -174,7 +155,7 @@ class _ActivitySection extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final (timeRange, hourly, daily, stats, activeHours, hasData) = ref.watch( - activityMeterViewModelProvider.select( + activityMeterControllerProvider.select( (s) => ( s.timeRange, s.hourlyData, @@ -199,7 +180,9 @@ class _ActivitySection extends ConsumerWidget { textAlign: TextAlign.center, style: TextStyle( fontSize: SizeUtils.getByScreen(small: 13, big: 12), - color: Theme.of(context).colorScheme.onSurface + color: Theme.of(context) + .colorScheme + .onSurface .withValues(alpha: 0.5), ), ), @@ -228,9 +211,9 @@ class _HistorySection extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final vm = ref.read(activityMeterViewModelProvider.notifier); + final notifier = ref.read(activityMeterControllerProvider.notifier); final (history, dailyGoal, hasMore, isLoadingMore) = ref.watch( - activityMeterViewModelProvider.select( + activityMeterControllerProvider.select( (s) => (s.historyData, s.dailyGoal, s.hasMoreHistory, s.isLoadingMore), ), ); @@ -248,7 +231,7 @@ class _HistorySection extends ConsumerWidget { dailyGoal: dailyGoal, hasMore: hasMore, isLoadingMore: isLoadingMore, - onLoadMore: vm.loadMoreHistory, + onLoadMore: notifier.loadMoreHistory, ), ], ); diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_aggregator.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_aggregator.dart similarity index 91% rename from modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_aggregator.dart rename to modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_aggregator.dart index 4cf8821a..38b4436a 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_aggregator.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_aggregator.dart @@ -1,6 +1,6 @@ -import '../../../../core/domain/entities/steps_entity.dart'; -import '../../../../core/presentation/time_range.dart'; -import 'activity_meter_view_state.dart'; +import 'package:device_management/src/core/domain/entities/steps_entity.dart'; +import 'package:device_management/src/core/presentation/time_range.dart'; +import 'package:device_management/src/features/activity_meter/presentation/providers/activity_meter_state.dart'; List groupByDay(List steps) { final Map groups = {}; diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.dart similarity index 54% rename from modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart rename to modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.dart index f35a0317..974ae3c9 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_model.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.dart @@ -1,36 +1,26 @@ import 'dart:async'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:legacy_device_state/legacy_device_state.dart'; +import 'package:device_management/src/core/data/datasources/health_query_builder.dart'; +import 'package:device_management/src/core/domain/entities/steps_entity.dart'; +import 'package:device_management/src/core/domain/repositories/steps_repository.dart'; +import 'package:device_management/src/core/presentation/time_range.dart'; +import 'package:device_management/src/core/providers/steps_repository_provider.dart'; +import 'package:device_management/src/features/activity_meter/presentation/providers/activity_meter_aggregator.dart'; +import 'package:device_management/src/features/activity_meter/presentation/providers/activity_meter_state.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:sf_shared/sf_shared.dart'; import 'package:sf_tracking/sf_tracking.dart'; -import '../../../../core/data/datasources/health_query_builder.dart'; -import '../../../../core/domain/entities/steps_entity.dart'; -import '../../../../core/domain/repositories/steps_repository.dart'; -import '../../../../core/presentation/time_range.dart'; -import '../../../../core/providers/steps_repository_provider.dart'; -import 'activity_meter_aggregator.dart'; -import 'activity_meter_view_state.dart'; +part 'activity_meter_controller.g.dart'; -final activityMeterViewModelProvider = - NotifierProvider.autoDispose< - ActivityMeterViewModel, - ActivityMeterViewState - >(ActivityMeterViewModel.new); - -class ActivityMeterViewModel extends Notifier { - late final StepsRepository _repository; - late final SfTrackingRepository _tracking; - - static const int _historyPageSize = 20; +const int _historyPageSize = 20; +@riverpod +class ActivityMeterController extends _$ActivityMeterController { @override - ActivityMeterViewState build() { - _repository = ref.read(stepsRepositoryProvider); - _tracking = ref.read(sfTrackingProvider); + ActivityMeterState build() { Future.microtask(_loadFilteredData); - return const ActivityMeterViewState(); + return const ActivityMeterState(); } String? get _identificator => @@ -40,9 +30,9 @@ class ActivityMeterViewModel extends Notifier { if (range == state.timeRange) return; state = state.copyWith(timeRange: range, isLoading: true); unawaited( - _tracking.legacyDeviceActivityMeterTimeRangeChanged( - _timeRangeName(range), - ), + ref + .read(sfTrackingProvider) + .legacyDeviceActivityMeterTimeRangeChanged(_timeRangeName(range)), ); await _loadFilteredData(); } @@ -54,22 +44,20 @@ class ActivityMeterViewModel extends Notifier { customEnd: end, isLoading: true, ); - unawaited(_tracking.legacyDeviceActivityMeterTimeRangeChanged('custom')); + unawaited( + ref + .read(sfTrackingProvider) + .legacyDeviceActivityMeterTimeRangeChanged('custom'), + ); await _loadFilteredData(); } - String _timeRangeName(TimeRange range) { - switch (range) { - case TimeRange.today: - return 'today'; - case TimeRange.sevenDays: - return 'seven_days'; - case TimeRange.thirtyDays: - return 'thirty_days'; - case TimeRange.custom: - return 'custom'; - } - } + String _timeRangeName(TimeRange range) => switch (range) { + TimeRange.today => 'today', + TimeRange.sevenDays => 'seven_days', + TimeRange.thirtyDays => 'thirty_days', + TimeRange.custom => 'custom', + }; Future loadMoreHistory() async { if (state.isLoadingMore || !state.hasMoreHistory) return; @@ -86,15 +74,16 @@ class ActivityMeterViewModel extends Notifier { end: end, ); - final steps = await _repository.getSteps( - identificator: identificator, - queryParameters: HealthQueryBuilder.build( - orderDirection: OrderDirection.desc, - page: nextPage, - pageSize: _historyPageSize, - filters: filters, - ), - ); + final steps = + await ref.read(stepsRepositoryProvider).getSteps( + identificator: identificator, + queryParameters: HealthQueryBuilder.build( + orderDirection: OrderDirection.desc, + page: nextPage, + pageSize: _historyPageSize, + filters: filters, + ), + ); if (!ref.mounted) return; final newDaily = groupByDay(steps); @@ -108,10 +97,7 @@ class ActivityMeterViewModel extends Notifier { ); } catch (_) { if (!ref.mounted) return; - state = state.copyWith( - isLoadingMore: false, - errorEvent: ActivityMeterErrorEvent.loadMore, - ); + state = state.copyWith(isLoadingMore: false); } } @@ -122,6 +108,7 @@ class ActivityMeterViewModel extends Notifier { return; } + final repo = ref.read(stepsRepositoryProvider); try { final (start, end) = _resolveRange(); final filters = HealthQueryBuilder.timeRangeFilters( @@ -130,14 +117,14 @@ class ActivityMeterViewModel extends Notifier { ); final (chartSteps, histSteps, todaySteps) = await ( - _repository.getSteps( + repo.getSteps( identificator: identificator, queryParameters: HealthQueryBuilder.build( orderDirection: OrderDirection.asc, filters: filters, ), ), - _repository.getSteps( + repo.getSteps( identificator: identificator, queryParameters: HealthQueryBuilder.build( orderDirection: OrderDirection.desc, @@ -146,7 +133,7 @@ class ActivityMeterViewModel extends Notifier { filters: filters, ), ), - _fetchTodaySteps(identificator), + _fetchTodaySteps(repo, identificator), ).wait; if (!ref.mounted) return; @@ -174,21 +161,20 @@ class ActivityMeterViewModel extends Notifier { rangeStart: start, rangeEnd: end, isLoading: false, - errorEvent: null, ); } catch (_) { if (!ref.mounted) return; - state = state.copyWith( - isLoading: false, - errorEvent: ActivityMeterErrorEvent.loadData, - ); + state = state.copyWith(isLoading: false); } } - Future> _fetchTodaySteps(String identificator) { + Future> _fetchTodaySteps( + StepsRepository repo, + String identificator, + ) { final now = DateTime.now(); final todayStart = DateTime(now.year, now.month, now.day); - return _repository.getSteps( + return repo.getSteps( identificator: identificator, queryParameters: HealthQueryBuilder.build( orderDirection: OrderDirection.asc, @@ -201,35 +187,9 @@ class ActivityMeterViewModel extends Notifier { } (DateTime, DateTime) _resolveRange() => resolveRange( - state.timeRange, - now: DateTime.now(), - customStart: state.customStart, - customEnd: state.customEnd, - ); - - Future togglePedometer({required bool enabled}) async { - final device = ref.read(selectedDeviceProvider).value; - if (device == null) return false; - - state = state.copyWith(errorEvent: null); - try { - final updatedSettings = device.settings.copyWith(pedometer: enabled); - await ref - .read(deviceSettingsUpdateProvider) - .updateDeviceSettings( - device: device, - updatedSettings: updatedSettings, - ); - if (!ref.mounted) return false; - ref.syncDeviceSettings(device, updatedSettings); - - unawaited(_tracking.legacyDeviceActivityPedometerToggled(enabled)); - - return true; - } catch (_) { - if (!ref.mounted) return false; - state = state.copyWith(errorEvent: ActivityMeterErrorEvent.pedometer); - return false; - } - } + state.timeRange, + now: DateTime.now(), + customStart: state.customStart, + customEnd: state.customEnd, + ); } diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.g.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.g.dart new file mode 100644 index 00000000..954cf18b --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_controller.g.dart @@ -0,0 +1,64 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'activity_meter_controller.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(ActivityMeterController) +const activityMeterControllerProvider = ActivityMeterControllerProvider._(); + +final class ActivityMeterControllerProvider + extends $NotifierProvider { + const ActivityMeterControllerProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'activityMeterControllerProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$activityMeterControllerHash(); + + @$internal + @override + ActivityMeterController create() => ActivityMeterController(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(ActivityMeterState value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$activityMeterControllerHash() => + r'693b7f7a3d5f2aca66d69fcba538cd3e5f2d9498'; + +abstract class _$ActivityMeterController extends $Notifier { + ActivityMeterState build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + ActivityMeterState, + Object?, + Object? + >; + element.handleValue(ref, created); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_state.dart similarity index 65% rename from modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.dart rename to modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_state.dart index 59706421..55f2b13a 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_state.dart @@ -1,21 +1,22 @@ +import 'package:device_management/src/core/presentation/time_range.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import '../../../../core/presentation/time_range.dart'; - -part 'activity_meter_view_state.freezed.dart'; - -enum ActivityMeterErrorEvent { loadData, loadMore, pedometer } +part 'activity_meter_state.freezed.dart'; @freezed abstract class DailySteps with _$DailySteps { - const factory DailySteps({required DateTime date, required int totalSteps}) = - _DailySteps; + const factory DailySteps({ + required DateTime date, + required int totalSteps, + }) = _DailySteps; } @freezed abstract class HourlySteps with _$HourlySteps { - const factory HourlySteps({required int hour, required int totalSteps}) = - _HourlySteps; + const factory HourlySteps({ + required int hour, + required int totalSteps, + }) = _HourlySteps; } @freezed @@ -30,8 +31,8 @@ abstract class StepsStats with _$StepsStats { } @freezed -abstract class ActivityMeterViewState with _$ActivityMeterViewState { - const factory ActivityMeterViewState({ +abstract class ActivityMeterState with _$ActivityMeterState { + const factory ActivityMeterState({ @Default(0) int todayTotal, @Default(8000) int dailyGoal, @Default([]) List chartData, @@ -48,11 +49,10 @@ abstract class ActivityMeterViewState with _$ActivityMeterViewState { DateTime? rangeEnd, @Default(true) bool isLoading, @Default(false) bool isLoadingMore, - ActivityMeterErrorEvent? errorEvent, - }) = _ActivityMeterViewState; + }) = _ActivityMeterState; } -extension ActivityMeterViewStateX on ActivityMeterViewState { +extension ActivityMeterStateX on ActivityMeterState { bool get hasActivityData => timeRange == TimeRange.today ? hourlyData.any((h) => h.totalSteps > 0) : stats.total > 0; diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.freezed.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_state.freezed.dart similarity index 82% rename from modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.freezed.dart rename to modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_state.freezed.dart index d34cd7ee..61dd13e1 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/state/activity_meter_view_state.freezed.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/activity_meter_state.freezed.dart @@ -3,7 +3,7 @@ // ignore_for_file: type=lint // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark -part of 'activity_meter_view_state.dart'; +part of 'activity_meter_state.dart'; // ************************************************************************** // FreezedGenerator @@ -825,40 +825,40 @@ $DailyStepsCopyWith<$Res>? get bestDay { } /// @nodoc -mixin _$ActivityMeterViewState { +mixin _$ActivityMeterState { - int get todayTotal; int get dailyGoal; List get chartData; List get hourlyData; int get activeHoursToday; List get historyData; int get currentHistoryPage; bool get hasMoreHistory; StepsStats get stats; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; DateTime? get rangeStart; DateTime? get rangeEnd; bool get isLoading; bool get isLoadingMore; ActivityMeterErrorEvent? get errorEvent; -/// Create a copy of ActivityMeterViewState + int get todayTotal; int get dailyGoal; List get chartData; List get hourlyData; int get activeHoursToday; List get historyData; int get currentHistoryPage; bool get hasMoreHistory; StepsStats get stats; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; DateTime? get rangeStart; DateTime? get rangeEnd; bool get isLoading; bool get isLoadingMore; +/// Create a copy of ActivityMeterState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -$ActivityMeterViewStateCopyWith get copyWith => _$ActivityMeterViewStateCopyWithImpl(this as ActivityMeterViewState, _$identity); +$ActivityMeterStateCopyWith get copyWith => _$ActivityMeterStateCopyWithImpl(this as ActivityMeterState, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other.chartData, chartData)&&const DeepCollectionEquality().equals(other.hourlyData, hourlyData)&&(identical(other.activeHoursToday, activeHoursToday) || other.activeHoursToday == activeHoursToday)&&const DeepCollectionEquality().equals(other.historyData, historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.rangeStart, rangeStart) || other.rangeStart == rangeStart)&&(identical(other.rangeEnd, rangeEnd) || other.rangeEnd == rangeEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityMeterState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other.chartData, chartData)&&const DeepCollectionEquality().equals(other.hourlyData, hourlyData)&&(identical(other.activeHoursToday, activeHoursToday) || other.activeHoursToday == activeHoursToday)&&const DeepCollectionEquality().equals(other.historyData, historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.rangeStart, rangeStart) || other.rangeStart == rangeStart)&&(identical(other.rangeEnd, rangeEnd) || other.rangeEnd == rangeEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)); } @override -int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(chartData),const DeepCollectionEquality().hash(hourlyData),activeHoursToday,const DeepCollectionEquality().hash(historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,rangeStart,rangeEnd,isLoading,isLoadingMore,errorEvent); +int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(chartData),const DeepCollectionEquality().hash(hourlyData),activeHoursToday,const DeepCollectionEquality().hash(historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,rangeStart,rangeEnd,isLoading,isLoadingMore); @override String toString() { - return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, hourlyData: $hourlyData, activeHoursToday: $activeHoursToday, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, rangeStart: $rangeStart, rangeEnd: $rangeEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorEvent: $errorEvent)'; + return 'ActivityMeterState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, hourlyData: $hourlyData, activeHoursToday: $activeHoursToday, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, rangeStart: $rangeStart, rangeEnd: $rangeEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore)'; } } /// @nodoc -abstract mixin class $ActivityMeterViewStateCopyWith<$Res> { - factory $ActivityMeterViewStateCopyWith(ActivityMeterViewState value, $Res Function(ActivityMeterViewState) _then) = _$ActivityMeterViewStateCopyWithImpl; +abstract mixin class $ActivityMeterStateCopyWith<$Res> { + factory $ActivityMeterStateCopyWith(ActivityMeterState value, $Res Function(ActivityMeterState) _then) = _$ActivityMeterStateCopyWithImpl; @useResult $Res call({ - int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent + int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore }); @@ -866,16 +866,16 @@ $StepsStatsCopyWith<$Res> get stats; } /// @nodoc -class _$ActivityMeterViewStateCopyWithImpl<$Res> - implements $ActivityMeterViewStateCopyWith<$Res> { - _$ActivityMeterViewStateCopyWithImpl(this._self, this._then); +class _$ActivityMeterStateCopyWithImpl<$Res> + implements $ActivityMeterStateCopyWith<$Res> { + _$ActivityMeterStateCopyWithImpl(this._self, this._then); - final ActivityMeterViewState _self; - final $Res Function(ActivityMeterViewState) _then; + final ActivityMeterState _self; + final $Res Function(ActivityMeterState) _then; -/// Create a copy of ActivityMeterViewState +/// Create a copy of ActivityMeterState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? hourlyData = null,Object? activeHoursToday = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? rangeStart = freezed,Object? rangeEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorEvent = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? hourlyData = null,Object? activeHoursToday = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? rangeStart = freezed,Object? rangeEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,}) { return _then(_self.copyWith( todayTotal: null == todayTotal ? _self.todayTotal : todayTotal // ignore: cast_nullable_to_non_nullable as int,dailyGoal: null == dailyGoal ? _self.dailyGoal : dailyGoal // ignore: cast_nullable_to_non_nullable @@ -893,11 +893,10 @@ as DateTime?,rangeStart: freezed == rangeStart ? _self.rangeStart : rangeStart / as DateTime?,rangeEnd: freezed == rangeEnd ? _self.rangeEnd : rangeEnd // ignore: cast_nullable_to_non_nullable as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable -as bool,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable -as ActivityMeterErrorEvent?, +as bool, )); } -/// Create a copy of ActivityMeterViewState +/// Create a copy of ActivityMeterState /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') @@ -910,8 +909,8 @@ $StepsStatsCopyWith<$Res> get stats { } -/// Adds pattern-matching-related methods to [ActivityMeterViewState]. -extension ActivityMeterViewStatePatterns on ActivityMeterViewState { +/// Adds pattern-matching-related methods to [ActivityMeterState]. +extension ActivityMeterStatePatterns on ActivityMeterState { /// A variant of `map` that fallback to returning `orElse`. /// /// It is equivalent to doing: @@ -924,10 +923,10 @@ extension ActivityMeterViewStatePatterns on ActivityMeterViewState { /// } /// ``` -@optionalTypeArgs TResult maybeMap(TResult Function( _ActivityMeterViewState value)? $default,{required TResult orElse(),}){ +@optionalTypeArgs TResult maybeMap(TResult Function( _ActivityMeterState value)? $default,{required TResult orElse(),}){ final _that = this; switch (_that) { -case _ActivityMeterViewState() when $default != null: +case _ActivityMeterState() when $default != null: return $default(_that);case _: return orElse(); @@ -946,10 +945,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult map(TResult Function( _ActivityMeterViewState value) $default,){ +@optionalTypeArgs TResult map(TResult Function( _ActivityMeterState value) $default,){ final _that = this; switch (_that) { -case _ActivityMeterViewState(): +case _ActivityMeterState(): return $default(_that);case _: throw StateError('Unexpected subclass'); @@ -967,10 +966,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ActivityMeterViewState value)? $default,){ +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ActivityMeterState value)? $default,){ final _that = this; switch (_that) { -case _ActivityMeterViewState() when $default != null: +case _ActivityMeterState() when $default != null: return $default(_that);case _: return null; @@ -988,10 +987,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { -case _ActivityMeterViewState() when $default != null: -return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyData,_that.activeHoursToday,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.rangeStart,_that.rangeEnd,_that.isLoading,_that.isLoadingMore,_that.errorEvent);case _: +case _ActivityMeterState() when $default != null: +return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyData,_that.activeHoursToday,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.rangeStart,_that.rangeEnd,_that.isLoading,_that.isLoadingMore);case _: return orElse(); } @@ -1009,10 +1008,10 @@ return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyDat /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore) $default,) {final _that = this; switch (_that) { -case _ActivityMeterViewState(): -return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyData,_that.activeHoursToday,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.rangeStart,_that.rangeEnd,_that.isLoading,_that.isLoadingMore,_that.errorEvent);case _: +case _ActivityMeterState(): +return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyData,_that.activeHoursToday,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.rangeStart,_that.rangeEnd,_that.isLoading,_that.isLoadingMore);case _: throw StateError('Unexpected subclass'); } @@ -1029,10 +1028,10 @@ return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyDat /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore)? $default,) {final _that = this; switch (_that) { -case _ActivityMeterViewState() when $default != null: -return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyData,_that.activeHoursToday,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.rangeStart,_that.rangeEnd,_that.isLoading,_that.isLoadingMore,_that.errorEvent);case _: +case _ActivityMeterState() when $default != null: +return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyData,_that.activeHoursToday,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.rangeStart,_that.rangeEnd,_that.isLoading,_that.isLoadingMore);case _: return null; } @@ -1043,8 +1042,8 @@ return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.hourlyDat /// @nodoc -class _ActivityMeterViewState implements ActivityMeterViewState { - const _ActivityMeterViewState({this.todayTotal = 0, this.dailyGoal = 8000, final List chartData = const [], final List hourlyData = const [], this.activeHoursToday = 0, final List historyData = const [], this.currentHistoryPage = 1, this.hasMoreHistory = false, this.stats = const StepsStats(), this.timeRange = TimeRange.today, this.customStart, this.customEnd, this.rangeStart, this.rangeEnd, this.isLoading = true, this.isLoadingMore = false, this.errorEvent}): _chartData = chartData,_hourlyData = hourlyData,_historyData = historyData; +class _ActivityMeterState implements ActivityMeterState { + const _ActivityMeterState({this.todayTotal = 0, this.dailyGoal = 8000, final List chartData = const [], final List hourlyData = const [], this.activeHoursToday = 0, final List historyData = const [], this.currentHistoryPage = 1, this.hasMoreHistory = false, this.stats = const StepsStats(), this.timeRange = TimeRange.today, this.customStart, this.customEnd, this.rangeStart, this.rangeEnd, this.isLoading = true, this.isLoadingMore = false}): _chartData = chartData,_hourlyData = hourlyData,_historyData = historyData; @override@JsonKey() final int todayTotal; @@ -1081,39 +1080,38 @@ class _ActivityMeterViewState implements ActivityMeterViewState { @override final DateTime? rangeEnd; @override@JsonKey() final bool isLoading; @override@JsonKey() final bool isLoadingMore; -@override final ActivityMeterErrorEvent? errorEvent; -/// Create a copy of ActivityMeterViewState +/// Create a copy of ActivityMeterState /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) @pragma('vm:prefer-inline') -_$ActivityMeterViewStateCopyWith<_ActivityMeterViewState> get copyWith => __$ActivityMeterViewStateCopyWithImpl<_ActivityMeterViewState>(this, _$identity); +_$ActivityMeterStateCopyWith<_ActivityMeterState> get copyWith => __$ActivityMeterStateCopyWithImpl<_ActivityMeterState>(this, _$identity); @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other._chartData, _chartData)&&const DeepCollectionEquality().equals(other._hourlyData, _hourlyData)&&(identical(other.activeHoursToday, activeHoursToday) || other.activeHoursToday == activeHoursToday)&&const DeepCollectionEquality().equals(other._historyData, _historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.rangeStart, rangeStart) || other.rangeStart == rangeStart)&&(identical(other.rangeEnd, rangeEnd) || other.rangeEnd == rangeEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityMeterState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other._chartData, _chartData)&&const DeepCollectionEquality().equals(other._hourlyData, _hourlyData)&&(identical(other.activeHoursToday, activeHoursToday) || other.activeHoursToday == activeHoursToday)&&const DeepCollectionEquality().equals(other._historyData, _historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.rangeStart, rangeStart) || other.rangeStart == rangeStart)&&(identical(other.rangeEnd, rangeEnd) || other.rangeEnd == rangeEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)); } @override -int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(_chartData),const DeepCollectionEquality().hash(_hourlyData),activeHoursToday,const DeepCollectionEquality().hash(_historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,rangeStart,rangeEnd,isLoading,isLoadingMore,errorEvent); +int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(_chartData),const DeepCollectionEquality().hash(_hourlyData),activeHoursToday,const DeepCollectionEquality().hash(_historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,rangeStart,rangeEnd,isLoading,isLoadingMore); @override String toString() { - return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, hourlyData: $hourlyData, activeHoursToday: $activeHoursToday, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, rangeStart: $rangeStart, rangeEnd: $rangeEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorEvent: $errorEvent)'; + return 'ActivityMeterState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, hourlyData: $hourlyData, activeHoursToday: $activeHoursToday, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, rangeStart: $rangeStart, rangeEnd: $rangeEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore)'; } } /// @nodoc -abstract mixin class _$ActivityMeterViewStateCopyWith<$Res> implements $ActivityMeterViewStateCopyWith<$Res> { - factory _$ActivityMeterViewStateCopyWith(_ActivityMeterViewState value, $Res Function(_ActivityMeterViewState) _then) = __$ActivityMeterViewStateCopyWithImpl; +abstract mixin class _$ActivityMeterStateCopyWith<$Res> implements $ActivityMeterStateCopyWith<$Res> { + factory _$ActivityMeterStateCopyWith(_ActivityMeterState value, $Res Function(_ActivityMeterState) _then) = __$ActivityMeterStateCopyWithImpl; @override @useResult $Res call({ - int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent + int todayTotal, int dailyGoal, List chartData, List hourlyData, int activeHoursToday, List historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, DateTime? rangeStart, DateTime? rangeEnd, bool isLoading, bool isLoadingMore }); @@ -1121,17 +1119,17 @@ $Res call({ } /// @nodoc -class __$ActivityMeterViewStateCopyWithImpl<$Res> - implements _$ActivityMeterViewStateCopyWith<$Res> { - __$ActivityMeterViewStateCopyWithImpl(this._self, this._then); +class __$ActivityMeterStateCopyWithImpl<$Res> + implements _$ActivityMeterStateCopyWith<$Res> { + __$ActivityMeterStateCopyWithImpl(this._self, this._then); - final _ActivityMeterViewState _self; - final $Res Function(_ActivityMeterViewState) _then; + final _ActivityMeterState _self; + final $Res Function(_ActivityMeterState) _then; -/// Create a copy of ActivityMeterViewState +/// Create a copy of ActivityMeterState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? hourlyData = null,Object? activeHoursToday = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? rangeStart = freezed,Object? rangeEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorEvent = freezed,}) { - return _then(_ActivityMeterViewState( +@override @pragma('vm:prefer-inline') $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? hourlyData = null,Object? activeHoursToday = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? rangeStart = freezed,Object? rangeEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,}) { + return _then(_ActivityMeterState( todayTotal: null == todayTotal ? _self.todayTotal : todayTotal // ignore: cast_nullable_to_non_nullable as int,dailyGoal: null == dailyGoal ? _self.dailyGoal : dailyGoal // ignore: cast_nullable_to_non_nullable as int,chartData: null == chartData ? _self._chartData : chartData // ignore: cast_nullable_to_non_nullable @@ -1148,12 +1146,11 @@ as DateTime?,rangeStart: freezed == rangeStart ? _self.rangeStart : rangeStart / as DateTime?,rangeEnd: freezed == rangeEnd ? _self.rangeEnd : rangeEnd // ignore: cast_nullable_to_non_nullable as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable -as bool,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable -as ActivityMeterErrorEvent?, +as bool, )); } -/// Create a copy of ActivityMeterViewState +/// Create a copy of ActivityMeterState /// with the given fields replaced by the non-null parameter values. @override @pragma('vm:prefer-inline') diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.dart new file mode 100644 index 00000000..d794a9ef --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.dart @@ -0,0 +1,38 @@ +import 'dart:async'; + +import 'package:legacy_device_state/legacy_device_state.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:sf_shared/sf_shared.dart'; +import 'package:sf_tracking/sf_tracking.dart'; + +part 'pedometer_controller.g.dart'; + +@riverpod +class PedometerController extends _$PedometerController { + bool _lastValue = false; + + bool get lastValue => _lastValue; + + @override + FutureOr build() {} + + Future toggle({ + required DeviceEntity device, + required bool enabled, + }) async { + _lastValue = enabled; + state = const AsyncLoading(); + state = await AsyncValue.guard(() async { + final updated = device.settings.copyWith(pedometer: enabled); + await ref + .read(deviceSettingsUpdateProvider) + .updateDeviceSettings(device: device, updatedSettings: updated); + ref.syncDeviceSettings(device, updated); + unawaited( + ref.read(sfTrackingProvider).legacyDeviceActivityPedometerToggled( + enabled, + ), + ); + }); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.g.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.g.dart new file mode 100644 index 00000000..ee026f47 --- /dev/null +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/providers/pedometer_controller.g.dart @@ -0,0 +1,56 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'pedometer_controller.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(PedometerController) +const pedometerControllerProvider = PedometerControllerProvider._(); + +final class PedometerControllerProvider + extends $AsyncNotifierProvider { + const PedometerControllerProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'pedometerControllerProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$pedometerControllerHash(); + + @$internal + @override + PedometerController create() => PedometerController(); +} + +String _$pedometerControllerHash() => + r'd6df6753b2713d7feee4164ba8b2d0f595c67290'; + +abstract class _$PedometerController extends $AsyncNotifier { + FutureOr build(); + @$mustCallSuper + @override + void runBuild() { + build(); + final ref = this.ref as $Ref, void>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, void>, + AsyncValue, + Object?, + Object? + >; + element.handleValue(ref, null); + } +} diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/activity_footers.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/activity_footers.dart index 7a127a83..520b0af6 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/activity_footers.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/activity_footers.dart @@ -5,7 +5,7 @@ import 'package:utils/utils.dart'; import '../../../../core/presentation/format_date.dart'; import '../format_steps.dart'; -import '../state/activity_meter_view_state.dart'; +import '../providers/activity_meter_state.dart'; import 'period_stats_cards.dart'; class TodayActivityFooter extends ConsumerWidget { diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/hourly_bar_chart.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/hourly_bar_chart.dart index 83b14e6b..44a32030 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/hourly_bar_chart.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/hourly_bar_chart.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:utils/utils.dart'; -import '../state/activity_meter_view_state.dart'; +import '../providers/activity_meter_state.dart'; import 'activity_bar_chart_base.dart'; class HourlyBarChart extends ConsumerWidget { diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/pedometer_toggle.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/pedometer_toggle.dart index 839262f7..fea74bb8 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/pedometer_toggle.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/pedometer_toggle.dart @@ -1,14 +1,12 @@ -import 'package:design_system/design_system.dart'; -import 'package:legacy_theme/legacy_theme.dart'; +import 'package:device_management/src/features/activity_meter/presentation/providers/pedometer_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:legacy_device_state/legacy_device_state.dart'; -import 'package:sf_shared/sf_shared.dart'; +import 'package:legacy_theme/legacy_theme.dart'; import 'package:sf_localizations/sf_localizations.dart'; +import 'package:sf_shared/sf_shared.dart'; import 'package:utils/utils.dart'; -import '../state/activity_meter_view_model.dart'; - class PedometerToggle extends ConsumerWidget { const PedometerToggle({super.key}); @@ -20,6 +18,22 @@ class PedometerToggle extends ConsumerWidget { ), ); + ref.listen(pedometerControllerProvider, (prev, next) async { + if (prev == null || !prev.isLoading || next.isLoading) return; + if (next.hasError) { + await showErrorDialog(context, I18n.errorPedometer); + return; + } + final lastValue = + ref.read(pedometerControllerProvider.notifier).lastValue; + await showSuccessDialog( + context, + lastValue + ? I18n.activityMeterPedometerEnabled + : I18n.activityMeterPedometerDisabled, + ); + }); + return Padding( padding: EdgeInsets.symmetric( horizontal: SizeUtils.getByScreen(small: 16, big: 14), @@ -40,21 +54,11 @@ class PedometerToggle extends ConsumerWidget { activeTrackColor: context.sfColors.legacyPrimary, onChanged: (value) async { if (!await guardDeviceCommand(context, ref)) return; - final success = await ref - .read(activityMeterViewModelProvider.notifier) - .togglePedometer(enabled: value); - if (!context.mounted) return; - if (success) { - showTopSnackbar( - context, - message: context.translate( - value - ? I18n.activityMeterPedometerEnabled - : I18n.activityMeterPedometerDisabled, - ), - type: MessageType.success, - ); - } + final device = ref.read(selectedDeviceProvider).value; + if (device == null) return; + ref + .read(pedometerControllerProvider.notifier) + .toggle(device: device, enabled: value); }, ), ], diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/period_stats_cards.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/period_stats_cards.dart index c03cf022..e775413b 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/period_stats_cards.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/period_stats_cards.dart @@ -4,7 +4,7 @@ import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; import '../format_steps.dart'; -import '../state/activity_meter_view_state.dart'; +import '../providers/activity_meter_state.dart'; class PeriodStatsCards extends StatelessWidget { final StepsStats stats; diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart index 7e0a3edf..07b0b57f 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_bar_chart.dart @@ -5,7 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:utils/utils.dart'; -import '../state/activity_meter_view_state.dart'; +import '../providers/activity_meter_state.dart'; import 'activity_bar_chart_base.dart'; class StepsBarChart extends ConsumerWidget { diff --git a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart index d424b2c1..eec0c0af 100644 --- a/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart +++ b/modules/legacy/modules/device_management/lib/src/features/activity_meter/presentation/widgets/steps_history_section.dart @@ -5,7 +5,7 @@ import 'package:utils/utils.dart'; import '../../../../core/presentation/format_date.dart'; import '../format_steps.dart'; -import '../state/activity_meter_view_state.dart'; +import '../providers/activity_meter_state.dart'; class StepsHistorySection extends StatelessWidget { final List items; diff --git a/modules/legacy/modules/device_management/test/features/activity_meter/pedometer_controller_test.dart b/modules/legacy/modules/device_management/test/features/activity_meter/pedometer_controller_test.dart new file mode 100644 index 00000000..a6fd87b5 --- /dev/null +++ b/modules/legacy/modules/device_management/test/features/activity_meter/pedometer_controller_test.dart @@ -0,0 +1,90 @@ +import 'package:device_management/src/features/activity_meter/presentation/providers/pedometer_controller.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:legacy_device_state/legacy_device_state.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; +import 'package:sf_shared/sf_shared.dart'; +import 'package:sf_shared/testing.dart'; +import 'package:sf_tracking/sf_tracking.dart'; + +class MockDeviceSettingsUpdateDatasource extends Mock + implements DeviceSettingsUpdateDatasource {} + +const _device = DeviceEntity( + id: 'device-1', + identificator: 'imei-1', + carrierName: 'Watch', + settings: DeviceSettingsEntity(pedometer: false), +); + +void main() { + setUpAll(() { + registerFallbackValue(_device); + registerFallbackValue(const DeviceSettingsEntity()); + }); + + ProviderContainer buildContainer(DeviceSettingsUpdateDatasource ds) { + return makeContainer( + overrides: [ + deviceSettingsUpdateProvider.overrideWithValue(ds), + sfTrackingProvider.overrideWithValue( + SfTrackingRepository(clients: const []), + ), + ], + ); + } + + group('PedometerController.toggle', () { + test('persists pedometer=true and transitions to AsyncData', () async { + final ds = MockDeviceSettingsUpdateDatasource(); + when( + () => ds.updateDeviceSettings( + device: any(named: 'device'), + updatedSettings: any(named: 'updatedSettings'), + ), + ).thenAnswer((_) async {}); + + final container = buildContainer(ds); + addTearDown(container.dispose); + + await container + .read(pedometerControllerProvider.notifier) + .toggle(device: _device, enabled: true); + + expect( + container.read(pedometerControllerProvider), + isA>(), + ); + final captured = verify( + () => ds.updateDeviceSettings( + device: _device, + updatedSettings: captureAny(named: 'updatedSettings'), + ), + ).captured.single as DeviceSettingsEntity; + expect(captured.pedometer, isTrue); + }); + + test('exposes AsyncError when datasource fails', () async { + final ds = MockDeviceSettingsUpdateDatasource(); + when( + () => ds.updateDeviceSettings( + device: any(named: 'device'), + updatedSettings: any(named: 'updatedSettings'), + ), + ).thenThrow(const ApiException(message: 'boom', isNetworkError: true)); + + final container = buildContainer(ds); + addTearDown(container.dispose); + + await container + .read(pedometerControllerProvider.notifier) + .toggle(device: _device, enabled: true); + + expect( + container.read(pedometerControllerProvider), + isA>(), + ); + }); + }); +}