Skip to content

Commit 070313c

Browse files
authored
Fix/activities screen (#146)
# 🚀 Pull Request ## Brief Description This pull request resolves two bugs: 1. A workout in utc time would be grouped to the wrong day if the MESZ time would be within 0.00 and 2.00 because the utc time is then on the previous day. 2. The refresh indicator would not work if the list view in the activities screen does not cover the whole screen size. ## GitHub Copilot Text <!-- GitHub Copilot can suggest a PR description here --> This pull request introduces several changes to improve the user interface and data handling in the activities screen and view model. The most significant updates include refactoring the layout of the grouped activities list for better scrolling behavior and ensuring workout start dates are converted to local time for accurate grouping. ### UI Improvements: * Refactored `_buildGroupedActivities` in `activities_screen.dart` to wrap the `ListView.builder` in a `LayoutBuilder`, `SingleChildScrollView`, and `ConstrainedBox` for better handling of scrolling and layout constraints. This ensures the list always fills the available space and supports pull-to-refresh behavior. [[1]](diffhunk://#diff-88f7691689bff6b9ae5559a39398280e2b845d3fe6c13d6a14e5387fb374e83cL144-R156) [[2]](diffhunk://#diff-88f7691689bff6b9ae5559a39398280e2b845d3fe6c13d6a14e5387fb374e83cR204-R207) ### Code Formatting: * Adjusted formatting in `_buildGroupedActivities` to improve code readability, particularly around `Padding` and `Text` widget properties. ### Data Handling: * Updated `ActivitiesViewModel` in `activities_view_model.dart` to convert workout start dates to local time before grouping them by day. This ensures accurate grouping of activities based on the user's local timezone. ### Minor Changes: * Added a blank line in the loop processing workouts in `ActivitiesViewModel` for better code organization. * Added a blank line after an import statement in `activities_screen.dart` for consistency.
2 parents dc7d941 + f836097 commit 070313c

2 files changed

Lines changed: 64 additions & 44 deletions

File tree

lib/presentation/activities/list/screen/activities_screen.dart

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:io' show Platform;
2+
23
import 'package:flutter/material.dart';
34
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
45
import 'package:flutter_hooks/flutter_hooks.dart';
@@ -141,51 +142,67 @@ Widget _buildGroupedActivities(
141142
return seconds ~/ 60;
142143
}
143144

144-
return ListView.builder(
145-
controller: scrollController,
146-
physics: const ScrollPhysics(),
147-
itemCount: activities?.length ?? 0,
148-
itemBuilder: (context, index) {
149-
final date = activities?.keys.elementAt(index);
150-
final activityList = activities?[date]! ?? [];
151-
return Column(
152-
crossAxisAlignment: CrossAxisAlignment.start,
153-
children: [
154-
if (date != null && activityList.isNotEmpty)
155-
Padding(
156-
padding:
157-
const EdgeInsets.only(top: 16.0, left: 16.0, right: 16.0),
158-
child: Row(
159-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
160-
children: [
161-
Text(
162-
DateFormat("dd. MMMM yyyy").format(date),
163-
style: const TextStyle(fontWeight: FontWeight.bold),
164-
),
165-
Text(
166-
getDuration(getActivityMinutes(activityList), context),
167-
style: const TextStyle(fontWeight: FontWeight.bold),
145+
return LayoutBuilder(
146+
builder: (context, constraints) {
147+
return SingleChildScrollView(
148+
physics: const AlwaysScrollableScrollPhysics(),
149+
controller: scrollController,
150+
child: ConstrainedBox(
151+
constraints: BoxConstraints(
152+
minHeight: constraints.maxHeight,
153+
),
154+
child: ListView.builder(
155+
shrinkWrap: true,
156+
physics: const NeverScrollableScrollPhysics(),
157+
itemCount: activities?.length ?? 0,
158+
itemBuilder: (context, index) {
159+
final date = activities?.keys.elementAt(index);
160+
final activityList = activities?[date]! ?? [];
161+
return Column(
162+
crossAxisAlignment: CrossAxisAlignment.start,
163+
children: [
164+
if (date != null && activityList.isNotEmpty)
165+
Padding(
166+
padding: const EdgeInsets.only(
167+
top: 16.0, left: 16.0, right: 16.0),
168+
child: Row(
169+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
170+
children: [
171+
Text(
172+
DateFormat("dd. MMMM yyyy").format(date),
173+
style:
174+
const TextStyle(fontWeight: FontWeight.bold),
175+
),
176+
Text(
177+
getDuration(
178+
getActivityMinutes(activityList), context),
179+
style:
180+
const TextStyle(fontWeight: FontWeight.bold),
181+
),
182+
]),
168183
),
169-
]),
170-
),
171-
const Divider(),
172-
...activityList.map(
173-
(activity) => _buildActivityItem(context, activity),
184+
const Divider(),
185+
...activityList.map(
186+
(activity) => _buildActivityItem(context, activity),
187+
),
188+
// Add a loading indicator at the end of the list,
189+
if (index == activities!.length - 1 && isLoading)
190+
const Padding(
191+
padding: EdgeInsets.symmetric(vertical: 8.0),
192+
child: Center(child: CircularProgressIndicator()),
193+
) // Show loading
194+
// Show no more entries text if end is reached
195+
else if (index == activities.length - 1 && !isLoading)
196+
const Padding(
197+
padding: EdgeInsets.all(16.0),
198+
child: Center(
199+
child: Text("No more entries"),
200+
)),
201+
],
202+
);
203+
},
174204
),
175-
// Add a loading indicator at the end of the list,
176-
if (index == activities!.length - 1 && isLoading)
177-
const Padding(
178-
padding: EdgeInsets.symmetric(vertical: 8.0),
179-
child: Center(child: CircularProgressIndicator()),
180-
) // Show loading
181-
// Show no more entries text if end is reached
182-
else if (index == activities.length - 1 && !isLoading)
183-
const Padding(
184-
padding: EdgeInsets.all(16.0),
185-
child: Center(
186-
child: Text("No more entries"),
187-
)),
188-
],
205+
),
189206
);
190207
},
191208
);

lib/presentation/activities/list/view_model/activities_view_model.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ActivitiesViewModel extends StateNotifier<ActivitiesState> {
5353

5454
for (int i = 0; i < workouts.length; i++) {
5555
ActivityPreview workout = workouts[i];
56+
5657
state.icons ??= {};
5758
if (state.icons!.containsKey(workout.sourceId)) {
5859
workouts[i].icon = state.icons?[workout.sourceId];
@@ -63,8 +64,10 @@ class ActivitiesViewModel extends StateNotifier<ActivitiesState> {
6364
state.icons![workout.sourceId] = workouts[i].icon;
6465
state = state.copyWith(newIcons: state.icons);
6566
}
67+
// Convert the start date to local time
68+
final startDateLocal = toLocal(workout.start);
6669
DateTime day = DateTime(
67-
workout.start.year, workout.start.month, workout.start.day);
70+
startDateLocal.year, startDateLocal.month, startDateLocal.day);
6871
if (workoutsByDay[day] == null) {
6972
workoutsByDay[day] = [];
7073
}

0 commit comments

Comments
 (0)