From f8145fee35f2b5d12a49f73e8e5b6374671e43fb Mon Sep 17 00:00:00 2001 From: Benjamin Canape Date: Sat, 10 Feb 2024 23:56:53 +0100 Subject: [PATCH] improve widget trees --- .../activity/widgets/activity_item.dart | 4 +- .../common/core/widgets/share_map_button.dart | 1 + .../view_model/location_view_model.dart | 7 +- .../widgets/current_location_map.dart | 2 +- .../common/location/widgets/location_map.dart | 46 ++++---- .../timer/viewmodel/timer_view_model.dart | 4 +- .../common/timer/widgets/timer_pause.dart | 1 + .../common/timer/widgets/timer_start.dart | 1 + .../common/user/screens/profile_screen.dart | 107 +++++++++--------- .../widgets/back_to_home_button.dart | 1 + .../my_activities/widgets/details_tab.dart | 59 +++++----- .../new_activity/widgets/save_button.dart | 1 + .../screens/edit_password_screen.dart | 1 + 13 files changed, 123 insertions(+), 112 deletions(-) diff --git a/lib/presentation/common/activity/widgets/activity_item.dart b/lib/presentation/common/activity/widgets/activity_item.dart index a048ce22..cf83a992 100644 --- a/lib/presentation/common/activity/widgets/activity_item.dart +++ b/lib/presentation/common/activity/widgets/activity_item.dart @@ -33,6 +33,8 @@ class ActivityItem extends HookConsumerWidget { final state = ref.watch(activityItemViewModelProvider(activity.id)); final List colors = ColorUtils.generateColorTupleFromIndex(index); + final titleColor = colors.first; + final startColor = colors.first; final endColor = colors.last; const double borderRadius = 24; @@ -111,7 +113,7 @@ class ActivityItem extends HookConsumerWidget { ActivityItemDetails( displayUserName: displayUserName, activity: activity, - color: startColor), + color: titleColor), ], ), ), diff --git a/lib/presentation/common/core/widgets/share_map_button.dart b/lib/presentation/common/core/widgets/share_map_button.dart index 078b5df2..1c536fba 100644 --- a/lib/presentation/common/core/widgets/share_map_button.dart +++ b/lib/presentation/common/core/widgets/share_map_button.dart @@ -51,6 +51,7 @@ class ShareMapButton extends HookConsumerWidget { } return FloatingActionButton( + heroTag: 'share_button', onPressed: () async { try { Uint8List? image = await ImageUtils.captureWidgetToImage(boundaryKey); diff --git a/lib/presentation/common/location/view_model/location_view_model.dart b/lib/presentation/common/location/view_model/location_view_model.dart index a7e8f0bd..4e547268 100644 --- a/lib/presentation/common/location/view_model/location_view_model.dart +++ b/lib/presentation/common/location/view_model/location_view_model.dart @@ -12,9 +12,14 @@ import '../../timer/viewmodel/timer_view_model.dart'; import 'state/location_state.dart'; /// Provider for the [LocationViewModel]. -final locationViewModelProvider = +/*final locationViewModelProvider = StateNotifierProvider.autoDispose( (ref) => LocationViewModel(ref), +);*/ + +final locationViewModelProvider = + StateNotifierProvider( + (ref) => LocationViewModel(ref), ); /// View model for managing location-related functionality. diff --git a/lib/presentation/common/location/widgets/current_location_map.dart b/lib/presentation/common/location/widgets/current_location_map.dart index 497f534e..202f1077 100644 --- a/lib/presentation/common/location/widgets/current_location_map.dart +++ b/lib/presentation/common/location/widgets/current_location_map.dart @@ -58,6 +58,6 @@ class CurrentLocationMap extends HookConsumerWidget { ); } - return LocationMap(points: points, markers: markers); + return Expanded(child: LocationMap(points: points, markers: markers)); } } diff --git a/lib/presentation/common/location/widgets/location_map.dart b/lib/presentation/common/location/widgets/location_map.dart index 2b2b6993..385ea69f 100644 --- a/lib/presentation/common/location/widgets/location_map.dart +++ b/lib/presentation/common/location/widgets/location_map.dart @@ -22,31 +22,29 @@ class LocationMap extends HookConsumerWidget { final center = MapUtils.getCenterOfMap(points); final zoomLevel = MapUtils.getZoomLevel(points, center); - return Expanded( - child: SizedBox( - height: 500, - child: FlutterMap( - mapController: provider.mapController, - options: MapOptions( - initialCenter: points.isNotEmpty - ? center - : LatLng(state.currentPosition?.latitude ?? 0, - state.currentPosition?.longitude ?? 0), - initialZoom: zoomLevel, - ), - children: [ - TileLayer( - urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', - ), - PolylineLayer( - polylines: [ - Polyline( - points: points, strokeWidth: 4, color: ColorUtils.blueGrey), - ], - ), - MarkerLayer(markers: markers), - ], + return SizedBox( + height: 500, + child: FlutterMap( + mapController: provider.mapController, + options: MapOptions( + initialCenter: points.isNotEmpty + ? center + : LatLng(state.currentPosition?.latitude ?? 0, + state.currentPosition?.longitude ?? 0), + initialZoom: zoomLevel, ), + children: [ + TileLayer( + urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + ), + PolylineLayer( + polylines: [ + Polyline( + points: points, strokeWidth: 4, color: ColorUtils.blueGrey), + ], + ), + MarkerLayer(markers: markers), + ], ), ); } diff --git a/lib/presentation/common/timer/viewmodel/timer_view_model.dart b/lib/presentation/common/timer/viewmodel/timer_view_model.dart index 3794136c..2f02d264 100644 --- a/lib/presentation/common/timer/viewmodel/timer_view_model.dart +++ b/lib/presentation/common/timer/viewmodel/timer_view_model.dart @@ -69,6 +69,8 @@ class TimerViewModel extends StateNotifier { final distance = metricsProvider.distance; final globalSpeed = metricsProvider.globalSpeed; + ref.read(locationViewModelProvider.notifier).cancelLocationStream(); + var textToSay = StringBuffer(); textToSay.write('${l10nConf.congrats}.'); @@ -101,8 +103,6 @@ class TimerViewModel extends StateNotifier { "${l10nConf.speed}: $km,$meters ${l10nConf.kilometers} ${l10nConf.per} ${l10nConf.hours}"); await ref.read(textToSpeechService).say(textToSay.toString()); - - ref.read(locationViewModelProvider.notifier).cancelLocationStream(); } void resetTimerState() { diff --git a/lib/presentation/common/timer/widgets/timer_pause.dart b/lib/presentation/common/timer/widgets/timer_pause.dart index 59877638..bf75d99c 100644 --- a/lib/presentation/common/timer/widgets/timer_pause.dart +++ b/lib/presentation/common/timer/widgets/timer_pause.dart @@ -23,6 +23,7 @@ class TimerPause extends HookConsumerWidget { ); }, child: FloatingActionButton( + heroTag: 'pause_resume_button', backgroundColor: ColorUtils.main, key: ValueKey(isRunning), tooltip: timerViewModel.isTimerRunning() ? 'Pause' : 'Resume', diff --git a/lib/presentation/common/timer/widgets/timer_start.dart b/lib/presentation/common/timer/widgets/timer_start.dart index c3e17461..b09d7145 100644 --- a/lib/presentation/common/timer/widgets/timer_start.dart +++ b/lib/presentation/common/timer/widgets/timer_start.dart @@ -15,6 +15,7 @@ class TimerStart extends HookConsumerWidget { final timerViewModel = ref.watch(timerViewModelProvider.notifier); return FloatingActionButton( + heroTag: 'start_button', backgroundColor: timerViewModel.hasTimerStarted() ? ColorUtils.red : ColorUtils.main, elevation: 4.0, diff --git a/lib/presentation/common/user/screens/profile_screen.dart b/lib/presentation/common/user/screens/profile_screen.dart index 206d9bc5..d5056dd8 100644 --- a/lib/presentation/common/user/screens/profile_screen.dart +++ b/lib/presentation/common/user/screens/profile_screen.dart @@ -46,34 +46,35 @@ class ProfileScreen extends HookConsumerWidget { var activitiesStateProvider = ref.watch(activitiesDataFutureProvider(user)); - return state.isLoading - ? Expanded(child: Center(child: UIUtils.loader)) - : Scaffold( - body: SafeArea( - child: Column( + return Scaffold( + body: SafeArea( + child: state.isLoading + ? Expanded(child: Center(child: UIUtils.loader)) + : Column( children: [ Container( - padding: - const EdgeInsets.only(left: 16, top: 16, right: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(150), - child: Container( - alignment: Alignment.center, - width: 150, - height: 150, - child: profilePicture != null - ? Image.memory( - profilePicture, - fit: BoxFit.cover, - ) - : const Icon(Icons.person, size: 100), - ), + padding: + const EdgeInsets.only(left: 16, top: 16, right: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(150), + child: Container( + alignment: Alignment.center, + width: 150, + height: 150, + child: profilePicture != null + ? Image.memory( + profilePicture, + fit: BoxFit.cover, + ) + : const Icon(Icons.person, size: 100), ), - Flexible( - child: Column(children: [ + ), + Expanded( + child: Column( + children: [ Text( UserUtils.getNameOrUsername(user), style: const TextStyle( @@ -93,38 +94,37 @@ class ProfileScreen extends HookConsumerWidget { return widget; }, loading: () { - return Expanded( - child: Center(child: UIUtils.loader)); + return Center(child: UIUtils.loader); }, error: (error, stackTrace) { return Text('$error'); }, ) - ]), + ], ), - ], - )), + ), + ], + ), + ), const Divider(), - const SizedBox(height: 20), Expanded( child: RefreshIndicator( - key: _refreshIndicatorKey, - onRefresh: () async { - provider.refreshList(); - return ref - .refresh(activitiesDataFutureProvider(user)); - }, - child: Column(children: [ + key: _refreshIndicatorKey, + onRefresh: () async { + provider.refreshList(); + return ref.refresh(activitiesDataFutureProvider(user)); + }, + child: Column( + children: [ activitiesStateProvider.when( data: (initialData) { return ActivityList( - id: - '${InfiniteScrollListEnum.profile}_${user.id}', - activities: initialData.list, - total: initialData.total, - canOpenActivity: false, - bottomListScrollFct: - provider.fetchActivities); + id: '${InfiniteScrollListEnum.profile}_${user.id}', + activities: initialData.list, + total: initialData.total, + canOpenActivity: false, + bottomListScrollFct: provider.fetchActivities, + ); }, loading: () { return Expanded( @@ -133,15 +133,16 @@ class ProfileScreen extends HookConsumerWidget { error: (error, stackTrace) { return Text('$error'); }, - ) - ])), - ) + ), + ], + ), + ), + ), ], ), - ), - floatingActionButtonLocation: - FloatingActionButtonLocation.centerFloat, - floatingActionButton: UIUtils.createBackButton(context), - ); + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, + floatingActionButton: UIUtils.createBackButton(context), + ); } } diff --git a/lib/presentation/my_activities/widgets/back_to_home_button.dart b/lib/presentation/my_activities/widgets/back_to_home_button.dart index 69db8991..bcaf72d3 100644 --- a/lib/presentation/my_activities/widgets/back_to_home_button.dart +++ b/lib/presentation/my_activities/widgets/back_to_home_button.dart @@ -13,6 +13,7 @@ class BackToHomeButton extends HookConsumerWidget { final provider = ref.watch(activityListViewModelProvider.notifier); return FloatingActionButton( + heroTag: 'back_button', backgroundColor: ColorUtils.main, elevation: 4.0, child: Icon( diff --git a/lib/presentation/my_activities/widgets/details_tab.dart b/lib/presentation/my_activities/widgets/details_tab.dart index bec43b6c..a27bd6e5 100644 --- a/lib/presentation/my_activities/widgets/details_tab.dart +++ b/lib/presentation/my_activities/widgets/details_tab.dart @@ -81,40 +81,39 @@ class DetailsTab extends HookConsumerWidget { } return Scaffold( - body: Column( - children: [ - const SizedBox(height: 10), - state.isEditing - ? Column(children: [ - ActivityUtils.buildActivityTypeDropdown( - context, selectedType, provider), - const SizedBox(height: 20) - ]) - : Container(), - Date(date: displayedActivity.startDatetime), - Column( - children: [ - const SizedBox(height: 30), - Center( - child: TimerText(timeInMs: displayedActivity.time.toInt()), - ), - const SizedBox(height: 15), - Metrics( - distance: displayedActivity.distance, - speed: displayedActivity.speed, - ), - ], - ), - Expanded( - child: RepaintBoundary( - key: state.boundaryKey, - child: LocationMap(points: points, markers: markers), + body: SafeArea( + child: Column( + children: [ + const SizedBox(height: 10), + state.isEditing + ? Column(children: [ + ActivityUtils.buildActivityTypeDropdown( + context, selectedType, provider), + const SizedBox(height: 20) + ]) + : Container(), + Date(date: displayedActivity.startDatetime), + const SizedBox(height: 30), + Center( + child: TimerText(timeInMs: displayedActivity.time.toInt()), ), - ) - ], + const SizedBox(height: 15), + Metrics( + distance: displayedActivity.distance, + speed: displayedActivity.speed, + ), + Expanded( + child: RepaintBoundary( + key: state.boundaryKey, + child: LocationMap(points: points, markers: markers), + ), + ) + ], + ), ), floatingActionButton: state.isEditing || state.isLoading ? FloatingActionButton( + heroTag: 'save_button', backgroundColor: ColorUtils.main, elevation: 4.0, onPressed: state.isLoading diff --git a/lib/presentation/new_activity/widgets/save_button.dart b/lib/presentation/new_activity/widgets/save_button.dart index 9f777ea2..f556238d 100644 --- a/lib/presentation/new_activity/widgets/save_button.dart +++ b/lib/presentation/new_activity/widgets/save_button.dart @@ -20,6 +20,7 @@ class SaveButton extends HookConsumerWidget { opacity: disabled ? 0.5 : 1.0, duration: animationDuration, child: FloatingActionButton( + heroTag: 'save_button', backgroundColor: ColorUtils.main, elevation: 4.0, onPressed: disabled diff --git a/lib/presentation/settings/screens/edit_password_screen.dart b/lib/presentation/settings/screens/edit_password_screen.dart index 8dfc17b3..a32fe4b8 100644 --- a/lib/presentation/settings/screens/edit_password_screen.dart +++ b/lib/presentation/settings/screens/edit_password_screen.dart @@ -108,6 +108,7 @@ class EditPasswordScreen extends HookConsumerWidget { bottom: 16, right: 80, child: FloatingActionButton( + heroTag: 'save_button', backgroundColor: ColorUtils.main, elevation: 4.0, child: Icon(