From 3371c12be97914a58ace42257dcd07922564e594 Mon Sep 17 00:00:00 2001 From: Benjamin Canape Date: Mon, 12 Feb 2024 13:40:41 +0100 Subject: [PATCH] fix infinite scroll list console errors (#46) * fix infinite scroll list console errors * fix other errors and clean some code * improve activity style when username is displayed * improve widget trees * fix some consle errors * fix not entirely the location provider * try to fix location * fix imports * fix --- .../view_model/activity_item_view_model.dart | 5 +- .../activity/widgets/activity_comments.dart | 2 +- .../activity/widgets/activity_item.dart | 4 +- .../widgets/activity_item_details.dart | 4 +- .../activity/widgets/activity_list.dart | 67 ++++--- .../common/core/utils/activity_utils.dart | 36 ++-- .../core/widgets/infinite_scroll_list.dart | 35 ++-- .../common/core/widgets/share_map_button.dart | 1 + .../view_model/location_view_model.dart | 27 ++- .../widgets/current_location_map.dart | 33 +++- .../common/location/widgets/location_map.dart | 67 +++---- .../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 ++++++------ .../screens/pending_requests_screen.dart | 5 +- .../widgets/pending_request_list.dart | 32 +--- .../home/screens/home_screen.dart | 8 +- .../screens/activity_details_screen.dart | 163 +++++++++--------- .../screens/activity_list_screen.dart | 2 +- .../widgets/back_to_home_button.dart | 1 + .../my_activities/widgets/details_tab.dart | 27 +-- .../screens/new_activity_screen.dart | 8 +- .../new_activity/screens/sum_up_screen.dart | 8 +- .../new_activity/widgets/save_button.dart | 1 + .../screens/edit_password_screen.dart | 1 + 26 files changed, 327 insertions(+), 323 deletions(-) diff --git a/lib/presentation/common/activity/view_model/activity_item_view_model.dart b/lib/presentation/common/activity/view_model/activity_item_view_model.dart index b1a9b6b7..479f1303 100644 --- a/lib/presentation/common/activity/view_model/activity_item_view_model.dart +++ b/lib/presentation/common/activity/view_model/activity_item_view_model.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import '../../user/view_model/profile_picture_view_model.dart'; -import '../../../my_activities/view_model/activity_list_view_model.dart'; + import '../../../../data/repositories/activity_repository_impl.dart'; import '../../../../domain/entities/activity.dart'; import '../../../../main.dart'; import '../../../my_activities/screens/activity_details_screen.dart'; +import '../../../my_activities/view_model/activity_list_view_model.dart'; +import '../../user/view_model/profile_picture_view_model.dart'; import 'state/activity_item_state.dart'; /// Provider for the activity item view model. diff --git a/lib/presentation/common/activity/widgets/activity_comments.dart b/lib/presentation/common/activity/widgets/activity_comments.dart index 3d8c9a64..2db70994 100644 --- a/lib/presentation/common/activity/widgets/activity_comments.dart +++ b/lib/presentation/common/activity/widgets/activity_comments.dart @@ -4,7 +4,6 @@ import 'package:comment_box/comment/comment.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import '../../user/view_model/profile_picture_view_model.dart'; import '../../../../core/utils/storage_utils.dart'; import '../../../../domain/entities/activity.dart'; @@ -12,6 +11,7 @@ import '../../../../domain/entities/activity_comment.dart'; import '../../../../domain/entities/user.dart'; import '../../core/utils/color_utils.dart'; import '../../core/utils/user_utils.dart'; +import '../../user/view_model/profile_picture_view_model.dart'; import '../view_model/activity_item_comments_view_model.dart'; import '../view_model/activity_item_view_model.dart'; 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/activity/widgets/activity_item_details.dart b/lib/presentation/common/activity/widgets/activity_item_details.dart index 4ad34d47..c37307eb 100644 --- a/lib/presentation/common/activity/widgets/activity_item_details.dart +++ b/lib/presentation/common/activity/widgets/activity_item_details.dart @@ -80,9 +80,7 @@ class ActivityItemDetails extends StatelessWidget { ], ), Padding( - padding: EdgeInsets.only( - left: displayUserName ? 30 : 0, - bottom: displayUserName ? 30 : 0), + padding: EdgeInsets.only(left: 0, bottom: displayUserName ? 30 : 0), child: buildActivityDetails( context, appLocalizations, formattedDate, formattedTime), ), diff --git a/lib/presentation/common/activity/widgets/activity_list.dart b/lib/presentation/common/activity/widgets/activity_list.dart index 41f229f9..1d4235f7 100644 --- a/lib/presentation/common/activity/widgets/activity_list.dart +++ b/lib/presentation/common/activity/widgets/activity_list.dart @@ -67,8 +67,7 @@ class ActivityList extends HookConsumerWidget { ? state.groupedActivities : groupActivitiesByMonth(activities); - return Expanded( - child: InfiniteScrollList( + return InfiniteScrollList( listId: id, initialData: groupedActivities, total: total, @@ -109,41 +108,39 @@ class ActivityList extends HookConsumerWidget { previousMonthsTotal += groupedActivities[i].length as int; } - return Expanded( - child: Theme( - data: ThemeData( - expansionTileTheme: ExpansionTileThemeData( - tilePadding: EdgeInsets.zero, - iconColor: ColorUtils.black, - textColor: ColorUtils.black, - childrenPadding: EdgeInsets.zero, - shape: const RoundedRectangleBorder( - side: BorderSide.none, - borderRadius: BorderRadius.zero, - ), + return Theme( + data: ThemeData( + expansionTileTheme: ExpansionTileThemeData( + tilePadding: EdgeInsets.zero, + iconColor: ColorUtils.black, + textColor: ColorUtils.black, + childrenPadding: EdgeInsets.zero, + shape: const RoundedRectangleBorder( + side: BorderSide.none, + borderRadius: BorderRadius.zero, + ), + ), + ), + child: ExpansionTile( + tilePadding: const EdgeInsets.fromLTRB(15, 0, 15, 0), + title: Text( + '${_getMonthName(monthActivities.first.startDatetime, AppLocalizations.of(context)!.localeName)} ${monthActivities.first.startDatetime.year}', + style: const TextStyle( + fontWeight: FontWeight.bold, ), ), - child: ExpansionTile( - tilePadding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - title: Text( - '${_getMonthName(monthActivities.first.startDatetime, AppLocalizations.of(context)!.localeName)} ${monthActivities.first.startDatetime.year}', - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - initiallyExpanded: true, - children: - monthActivities.asMap().entries.map((entry) { - final index = previousMonthsTotal + entry.key; - final activity = entry.value; - return ActivityItem( - index: index as int, - activity: activity, - displayUserName: displayUserName, - canOpenActivity: canOpenActivity, - ); - }).toList()))); + initiallyExpanded: true, + children: monthActivities.asMap().entries.map((entry) { + final index = previousMonthsTotal + entry.key; + final activity = entry.value; + return ActivityItem( + index: index as int, + activity: activity, + displayUserName: displayUserName, + canOpenActivity: canOpenActivity, + ); + }).toList())); }, - )); + ); } } diff --git a/lib/presentation/common/core/utils/activity_utils.dart b/lib/presentation/common/core/utils/activity_utils.dart index e7d703a5..cb6bbb59 100644 --- a/lib/presentation/common/core/utils/activity_utils.dart +++ b/lib/presentation/common/core/utils/activity_utils.dart @@ -142,23 +142,25 @@ class ActivityUtils { static Future _updateActivityList(Ref ref, String listType, Activity updatedActivity, ActivityUpdateActionEnum action) async { - var data = ref.read(infiniteScrollListViewModelProvider(listType)).data; - - List> newData = []; - - if (action == ActivityUpdateActionEnum.edit) { - newData = ActivityUtils.replaceActivity( - data as List>, updatedActivity); - } else if (action == ActivityUpdateActionEnum.remove) { - newData = ActivityUtils.deleteActivity( - data as List>, updatedActivity); - } else if (action == ActivityUpdateActionEnum.add) { - newData = ActivityUtils.prependActivity( - data as List>, updatedActivity); + var data = ref + .read(infiniteScrollListViewModelProvider(listType)) + .data + .cast>(); + + if (data.isNotEmpty) { + List> newData = []; + + if (action == ActivityUpdateActionEnum.edit) { + newData = ActivityUtils.replaceActivity(data, updatedActivity); + } else if (action == ActivityUpdateActionEnum.remove) { + newData = ActivityUtils.deleteActivity(data, updatedActivity); + } else if (action == ActivityUpdateActionEnum.add) { + newData = ActivityUtils.prependActivity(data, updatedActivity); + } + + ref + .read(infiniteScrollListViewModelProvider(listType).notifier) + .replaceData(newData); } - - ref - .read(infiniteScrollListViewModelProvider(listType).notifier) - .replaceData(newData); } } diff --git a/lib/presentation/common/core/widgets/infinite_scroll_list.dart b/lib/presentation/common/core/widgets/infinite_scroll_list.dart index 228bd7c8..220b0311 100644 --- a/lib/presentation/common/core/widgets/infinite_scroll_list.dart +++ b/lib/presentation/common/core/widgets/infinite_scroll_list.dart @@ -102,22 +102,23 @@ class InfiniteScrollList extends HookConsumerWidget { state.data.isNotEmpty ? '' : provider.setData(initialData); }); - return state.isLoading - ? buildLoadingIndicator() - : ListView.builder( - key: _listKey, - controller: scrollController, - itemCount: - state.data.length + (hasMoreData(state.data, total) ? 1 : 0), - itemBuilder: (context, index) { - if (index < state.data.length) { - return itemBuildFunction(context, state.data, index); - } else { - return state.isLoading - ? buildLoadingIndicator() - : buildLoadMoreButton(context, state, provider); - } - }, - ); + return Expanded( + child: state.isLoading + ? buildLoadingIndicator() + : ListView.builder( + key: _listKey, + controller: scrollController, + itemCount: state.data.length + + (hasMoreData(state.data, total) ? 1 : 0), + itemBuilder: (context, index) { + if (index < state.data.length) { + return itemBuildFunction(context, state.data, index); + } else { + return state.isLoading + ? buildLoadingIndicator() + : buildLoadMoreButton(context, state, provider); + } + }, + )); } } 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..38d35fba 100644 --- a/lib/presentation/common/location/view_model/location_view_model.dart +++ b/lib/presentation/common/location/view_model/location_view_model.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:geolocator/geolocator.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -11,16 +10,15 @@ import '../../metrics/view_model/metrics_view_model.dart'; import '../../timer/viewmodel/timer_view_model.dart'; import 'state/location_state.dart'; -/// Provider for the [LocationViewModel]. final locationViewModelProvider = - StateNotifierProvider.autoDispose( + StateNotifierProvider( (ref) => LocationViewModel(ref), ); /// View model for managing location-related functionality. class LocationViewModel extends StateNotifier { final Ref ref; - final MapController mapController = MapController(); + MapController? mapController = MapController(); StreamSubscription? _positionStream; /// Creates a [LocationViewModel] instance. @@ -29,9 +27,9 @@ class LocationViewModel extends StateNotifier { LocationViewModel(this.ref) : super(LocationState.initial()); @override - void dispose() { + Future dispose() async { + await cancelLocationStream(); super.dispose(); - cancelLocationStream(); } /// Starts getting the user's location updates. @@ -48,13 +46,13 @@ class LocationViewModel extends StateNotifier { } _positionStream ??= Geolocator.getPositionStream().listen((Position position) { - if (mounted) { - WidgetsBinding.instance.addPostFrameCallback((_) { - mapController.move( + if (mounted && _positionStream != null && mapController != null) { + if (mounted && _positionStream != null && mapController != null) { + mapController?.move( LatLng(position.latitude, position.longitude), 17, ); - }); + } final timerProvider = ref.read(timerViewModelProvider.notifier); if (timerProvider.isTimerRunning() && timerProvider.hasTimerStarted()) { @@ -102,11 +100,10 @@ class LocationViewModel extends StateNotifier { } /// Cancels the location stream and cleans up resources. - void cancelLocationStream() async { - await _positionStream?.cancel().whenComplete(() { - _positionStream = null; - state = state.copyWith(currentPosition: null); - }); + Future cancelLocationStream() async { + await _positionStream?.cancel(); + _positionStream = null; + state = state.copyWith(currentPosition: null); } /// Checks if the location stream is currently paused. diff --git a/lib/presentation/common/location/widgets/current_location_map.dart b/lib/presentation/common/location/widgets/current_location_map.dart index 497f534e..a3f5ed19 100644 --- a/lib/presentation/common/location/widgets/current_location_map.dart +++ b/lib/presentation/common/location/widgets/current_location_map.dart @@ -1,20 +1,29 @@ import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:latlong2/latlong.dart'; import '../../core/utils/color_utils.dart'; +import '../../core/utils/ui_utils.dart'; import '../view_model/location_view_model.dart'; import 'location_map.dart'; /// Widget that displays the current location on a map. class CurrentLocationMap extends HookConsumerWidget { - const CurrentLocationMap({super.key}); + CurrentLocationMap({super.key}); + + final dataFutureProvider = FutureProvider((ref) async { + final provider = ref.read(locationViewModelProvider.notifier); + return await provider.startGettingLocation(); + }); @override Widget build(BuildContext context, WidgetRef ref) { - final state = ref.watch(locationViewModelProvider); final provider = ref.read(locationViewModelProvider.notifier); + final state = ref.watch(locationViewModelProvider); + + var futureProvider = ref.watch(dataFutureProvider); final points = provider.savedPositionsLatLng(); @@ -58,6 +67,24 @@ class CurrentLocationMap extends HookConsumerWidget { ); } - return LocationMap(points: points, markers: markers); + useEffect(() { + return () async { + await provider.cancelLocationStream(); + }; + }, []); + + return futureProvider.when(data: (total) { + return Expanded( + child: LocationMap( + points: points, + markers: markers, + currentPosition: LatLng(currentLatitude, currentLongitude), + mapController: provider.mapController ?? MapController(), + )); + }, loading: () { + return Expanded(child: Center(child: UIUtils.loader)); + }, error: (error, stackTrace) { + return Text('$error'); + }); } } diff --git a/lib/presentation/common/location/widgets/location_map.dart b/lib/presentation/common/location/widgets/location_map.dart index 3c8f8afc..f71a31fc 100644 --- a/lib/presentation/common/location/widgets/location_map.dart +++ b/lib/presentation/common/location/widgets/location_map.dart @@ -5,50 +5,55 @@ import 'package:latlong2/latlong.dart'; import '../../core/utils/color_utils.dart'; import '../../core/utils/map_utils.dart'; -import '../view_model/location_view_model.dart'; +import '../../core/utils/ui_utils.dart'; /// Widget that displays a map with markers and polylines representing locations. class LocationMap extends HookConsumerWidget { final List points; final List markers; + final MapController? mapController; + final LatLng? currentPosition; - const LocationMap({super.key, required this.points, required this.markers}); + const LocationMap( + {super.key, + required this.points, + required this.markers, + required this.mapController, + this.currentPosition}); @override Widget build(BuildContext context, WidgetRef ref) { - final provider = ref.read(locationViewModelProvider.notifier); - final state = ref.watch(locationViewModelProvider); - final center = MapUtils.getCenterOfMap(points); final zoomLevel = MapUtils.getZoomLevel(points, center); - return Expanded( - child: SizedBox( - height: 500, - child: FlutterMap( - mapController: provider.mapController, - options: MapOptions( - center: points.isNotEmpty - ? center - : LatLng(state.currentPosition?.latitude ?? 0, - state.currentPosition?.longitude ?? 0), - zoom: zoomLevel, - ), - nonRotatedChildren: const [], - children: [ - TileLayer( - urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', - ), - PolylineLayer( - polylines: [ - Polyline( - points: points, strokeWidth: 4, color: ColorUtils.blueGrey), + return points.isNotEmpty || currentPosition != null + ? SizedBox( + height: 500, + child: FlutterMap( + key: ValueKey(MediaQuery.of(context).orientation), + mapController: mapController, + options: MapOptions( + initialCenter: points.isNotEmpty + ? center + : currentPosition ?? const LatLng(0, 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), ], ), - MarkerLayer(markers: markers), - ], - ), - ), - ); + ) + : Center(child: UIUtils.loader); } } diff --git a/lib/presentation/common/timer/viewmodel/timer_view_model.dart b/lib/presentation/common/timer/viewmodel/timer_view_model.dart index 3794136c..8eaffc45 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; + //await 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/community/screens/pending_requests_screen.dart b/lib/presentation/community/screens/pending_requests_screen.dart index 8db0ea3e..5ca2e281 100644 --- a/lib/presentation/community/screens/pending_requests_screen.dart +++ b/lib/presentation/community/screens/pending_requests_screen.dart @@ -34,8 +34,7 @@ class PendingRequestsScreen extends HookConsumerWidget { UIUtils.createHeader( AppLocalizations.of(context)!.pending_requests_title), const SizedBox(height: 40), - Expanded( - child: pendingRequestsStateProvider.when( + pendingRequestsStateProvider.when( data: (initialData) { return PendingRequestsListWidget( users: initialData.list, @@ -51,7 +50,7 @@ class PendingRequestsScreen extends HookConsumerWidget { error: (error, stackTrace) { return Text('$error'); }, - )) + ) ])), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, diff --git a/lib/presentation/community/widgets/pending_request_list.dart b/lib/presentation/community/widgets/pending_request_list.dart index ff4fa72f..9e273ff6 100644 --- a/lib/presentation/community/widgets/pending_request_list.dart +++ b/lib/presentation/community/widgets/pending_request_list.dart @@ -14,9 +14,7 @@ class PendingRequestsListWidget extends HookConsumerWidget { final Function(String) onReject; final Future> Function({int pageNumber}) bottomListScrollFct; - final ScrollController _scrollController = ScrollController(); - - PendingRequestsListWidget( + const PendingRequestsListWidget( {super.key, required this.users, required this.total, @@ -24,33 +22,9 @@ class PendingRequestsListWidget extends HookConsumerWidget { required this.onReject, required this.bottomListScrollFct}); - void onScroll() { - if (_scrollController.position.pixels == - _scrollController.position.maxScrollExtent) {} - } - @override Widget build(BuildContext context, WidgetRef ref) { - _scrollController.addListener(onScroll); - /*return ListView.builder( - controller: _scrollController, - itemCount: users.length, - itemBuilder: (context, index) { - final user = users[index]; - return ListTile( - title: Text( - UserUtils.getNameOrUsername(user), - ), - trailing: AcceptRefuseWidget( - userId: user.id, - onAccept: onAccept, - onReject: onReject, - ), - ); - }, - );*/ - return Expanded( - child: InfiniteScrollList( + return InfiniteScrollList( listId: 'PENDING_REQUESTS', initialData: users, total: total, @@ -72,6 +46,6 @@ class PendingRequestsListWidget extends HookConsumerWidget { ), ); }, - )); + ); } } diff --git a/lib/presentation/home/screens/home_screen.dart b/lib/presentation/home/screens/home_screen.dart index 938995d2..188c3b17 100644 --- a/lib/presentation/home/screens/home_screen.dart +++ b/lib/presentation/home/screens/home_screen.dart @@ -4,7 +4,6 @@ import 'package:google_nav_bar/google_nav_bar.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../common/core/utils/color_utils.dart'; -import '../../common/location/view_model/location_view_model.dart'; import '../../community/screens/community_screen.dart'; import '../../my_activities/screens/activity_list_screen.dart'; import '../../new_activity/screens/new_activity_screen.dart'; @@ -22,13 +21,8 @@ class HomeScreen extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(homeViewModelProvider); final homeViewModel = ref.watch(homeViewModelProvider.notifier); - final locationViewModel = ref.read(locationViewModelProvider.notifier); final currentIndex = state.currentIndex; - if (currentIndex == 0) { - locationViewModel.startGettingLocation(); - } - final tabs = [ const NewActivityScreen(), ActivityListScreen(), @@ -50,7 +44,7 @@ class HomeScreen extends HookConsumerWidget { padding: const EdgeInsets.all(16), selectedIndex: currentIndex, onTabChange: (value) { - locationViewModel.cancelLocationStream(); + //locationViewModel.cancelLocationStream(); homeViewModel.setCurrentIndex(value); }, gap: 8, diff --git a/lib/presentation/my_activities/screens/activity_details_screen.dart b/lib/presentation/my_activities/screens/activity_details_screen.dart index 55b154cf..49775122 100644 --- a/lib/presentation/my_activities/screens/activity_details_screen.dart +++ b/lib/presentation/my_activities/screens/activity_details_screen.dart @@ -29,92 +29,87 @@ class ActivityDetailsScreen extends HookConsumerWidget { final displayedActivity = state.activity ?? activity; return Scaffold( - body: state.isLoading - ? Center(child: UIUtils.loader) - : SafeArea( - child: Column( - children: [ - Container( - padding: const EdgeInsets.only(left: 25, top: 12), - child: Row(children: [ - Text( - ActivityUtils.translateActivityTypeValue( - AppLocalizations.of(context)!, - displayedActivity.type, + body: SafeArea( + child: state.isLoading + ? Center(child: UIUtils.loader) + : Column(children: [ + Container( + padding: const EdgeInsets.only(left: 25, top: 12), + child: Row(children: [ + Text( + ActivityUtils.translateActivityTypeValue( + AppLocalizations.of(context)!, + displayedActivity.type, + ), + style: TextStyle( + color: ColorUtils.blueGrey, + fontSize: 28, + fontWeight: FontWeight.bold), ), - style: TextStyle( + const Spacer(), + IconButton( + color: ColorUtils.black, + tooltip: 'Edit', + onPressed: () { + tabController.animateTo(0); + provider.editType(); + }, + icon: Icon( + Icons.edit, color: ColorUtils.blueGrey, - fontSize: 28, - fontWeight: FontWeight.bold), - ), - const Spacer(), - IconButton( - color: ColorUtils.black, - tooltip: 'Edit', - onPressed: () { - tabController.animateTo(0); - provider.editType(); - }, - icon: Icon( - Icons.edit, - color: ColorUtils.blueGrey, + ), ), - ), - IconButton( - color: ColorUtils.black, - tooltip: 'Remove', - onPressed: () { - QuickAlert.show( - context: context, - type: QuickAlertType.confirm, - title: AppLocalizations.of(context)! - .ask_activity_removal, - confirmBtnText: - AppLocalizations.of(context)!.delete, - cancelBtnText: - AppLocalizations.of(context)!.cancel, - confirmBtnColor: ColorUtils.red, - onCancelBtnTap: () => Navigator.of(context).pop(), - onConfirmBtnTap: () { - Navigator.of(context).pop(); - provider.removeActivity(displayedActivity); - }); - }, - icon: Icon( - Icons.delete, - color: ColorUtils.red, - ), - ) - ]), - ), - Expanded( - child: DefaultTabController( - length: 2, - child: Scaffold( - appBar: TabBar( - controller: tabController, - labelColor: ColorUtils.blueGrey, - dividerColor: ColorUtils.blueGrey, - indicatorColor: ColorUtils.blueGrey, - tabs: const [ - Tab( - icon: Icon(Icons.short_text), - ), - Tab( - icon: Icon(Icons.graphic_eq_outlined), - ), - ]), - body: TabBarView( - controller: tabController, - children: [ - Expanded( - child: DetailsTab(activity: activity)), - Expanded( - child: GraphTab(activity: activity)) - ])))) - ], - ), - ), - ); + IconButton( + color: ColorUtils.black, + tooltip: 'Remove', + onPressed: () { + QuickAlert.show( + context: context, + type: QuickAlertType.confirm, + title: AppLocalizations.of(context)! + .ask_activity_removal, + confirmBtnText: + AppLocalizations.of(context)!.delete, + cancelBtnText: + AppLocalizations.of(context)!.cancel, + confirmBtnColor: ColorUtils.red, + onCancelBtnTap: () => + Navigator.of(context).pop(), + onConfirmBtnTap: () { + Navigator.of(context).pop(); + provider.removeActivity(displayedActivity); + }); + }, + icon: Icon( + Icons.delete, + color: ColorUtils.red, + ), + ) + ]), + ), + Expanded( + child: DefaultTabController( + length: 2, + child: Scaffold( + appBar: TabBar( + controller: tabController, + labelColor: ColorUtils.blueGrey, + dividerColor: ColorUtils.blueGrey, + indicatorColor: ColorUtils.blueGrey, + tabs: const [ + Tab( + icon: Icon(Icons.short_text), + ), + Tab( + icon: Icon(Icons.graphic_eq_outlined), + ), + ]), + body: TabBarView( + controller: tabController, + children: [ + DetailsTab(activity: activity), + GraphTab(activity: activity) + ])))) + ]))); } } diff --git a/lib/presentation/my_activities/screens/activity_list_screen.dart b/lib/presentation/my_activities/screens/activity_list_screen.dart index 8fb9eed8..2832ff32 100644 --- a/lib/presentation/my_activities/screens/activity_list_screen.dart +++ b/lib/presentation/my_activities/screens/activity_list_screen.dart @@ -27,7 +27,7 @@ class ActivityListScreen extends HookConsumerWidget { return Scaffold( body: isLoading - ? Expanded(child: Center(child: UIUtils.loader)) + ? Center(child: UIUtils.loader) : SafeArea( child: Column( children: [ 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..cfc9ee4d 100644 --- a/lib/presentation/my_activities/widgets/details_tab.dart +++ b/lib/presentation/my_activities/widgets/details_tab.dart @@ -92,29 +92,30 @@ class DetailsTab extends HookConsumerWidget { ]) : 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, - ), - ], + 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), + child: LocationMap( + points: points, + markers: markers, + mapController: MapController(), + ), ), ) ], ), 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/screens/new_activity_screen.dart b/lib/presentation/new_activity/screens/new_activity_screen.dart index 5e781d82..8e8aec8c 100644 --- a/lib/presentation/new_activity/screens/new_activity_screen.dart +++ b/lib/presentation/new_activity/screens/new_activity_screen.dart @@ -20,12 +20,12 @@ class NewActivityScreen extends HookConsumerWidget { ref.watch(timerViewModelProvider.select((value) => value.isRunning)); return Scaffold( - body: const SafeArea( + body: SafeArea( child: Column( children: [ - TimerTextSized(), - Metrics(), - SizedBox(height: 10), + const TimerTextSized(), + const Metrics(), + const SizedBox(height: 10), CurrentLocationMap(), ], ), diff --git a/lib/presentation/new_activity/screens/sum_up_screen.dart b/lib/presentation/new_activity/screens/sum_up_screen.dart index c3c6e557..b7424405 100644 --- a/lib/presentation/new_activity/screens/sum_up_screen.dart +++ b/lib/presentation/new_activity/screens/sum_up_screen.dart @@ -22,7 +22,7 @@ class SumUpScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(sumUpViewModelProvider); - final provider = ref.watch(sumUpViewModelProvider.notifier); + final provider = ref.read(sumUpViewModelProvider.notifier); ActivityType selectedType = state.type; final locations = ref.read(locationViewModelProvider).savedPositions; @@ -96,7 +96,11 @@ class SumUpScreen extends HookConsumerWidget { Expanded( child: RepaintBoundary( key: state.boundaryKey, - child: LocationMap(points: points, markers: markers), + child: LocationMap( + points: points, + markers: markers, + mapController: MapController(), + ), ), ), ], 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(