Skip to content

Commit 07317d3

Browse files
Add infinite scroll pagination and refactor activity widgets (#38)
* Add ininite scroll pagination and refactor activity widgets * fix community state when like, dislinke and comment activity * fix psoition when scrolling * add loader when loading more data * fix reset state * flutter pub update * fix add, edit and remove activity on infinite list * improve code * fix imports
1 parent 66a94ae commit 07317d3

71 files changed

Lines changed: 1423 additions & 482 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ios/Flutter/AppFrameworkInfo.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
<key>CFBundleVersion</key>
2222
<string>1.0</string>
2323
<key>MinimumOSVersion</key>
24-
<string>11.0</string>
24+
<string>12.0</string>
2525
</dict>
2626
</plist>

ios/Podfile.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,16 @@ EXTERNAL SOURCES:
6161
:path: ".symlinks/plugins/wakelock/ios"
6262

6363
SPEC CHECKSUMS:
64-
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
64+
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
6565
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
6666
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
6767
flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d
68-
geolocator_apple: cc556e6844d508c95df1e87e3ea6fa4e58c50401
68+
geolocator_apple: 9157311f654584b9bb72686c55fc02a97b73f461
6969
image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb
70-
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
71-
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
70+
image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425
71+
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
7272
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
73-
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
73+
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
7474
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
7575

7676
PODFILE CHECKSUM: 2442f0b84dc733c75ff32e76bcf04626a168288b

ios/Runner.xcodeproj/project.pbxproj

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
97C146EC1CF9000F007C117D /* Resources */,
140140
9705A1C41CF9048500538489 /* Embed Frameworks */,
141141
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142+
1A0A2642D378A6DD44FFFBF6 /* [CP] Copy Pods Resources */,
142143
);
143144
buildRules = (
144145
);
@@ -197,6 +198,23 @@
197198
/* End PBXResourcesBuildPhase section */
198199

199200
/* Begin PBXShellScriptBuildPhase section */
201+
1A0A2642D378A6DD44FFFBF6 /* [CP] Copy Pods Resources */ = {
202+
isa = PBXShellScriptBuildPhase;
203+
buildActionMask = 2147483647;
204+
files = (
205+
);
206+
inputFileListPaths = (
207+
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
208+
);
209+
name = "[CP] Copy Pods Resources";
210+
outputFileListPaths = (
211+
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
212+
);
213+
runOnlyForDeploymentPostprocessing = 0;
214+
shellPath = /bin/sh;
215+
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
216+
showEnvVarsInLog = 0;
217+
};
200218
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
201219
isa = PBXShellScriptBuildPhase;
202220
alwaysOutOfDate = 1;
@@ -325,7 +343,7 @@
325343
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
326344
GCC_WARN_UNUSED_FUNCTION = YES;
327345
GCC_WARN_UNUSED_VARIABLE = YES;
328-
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
346+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
329347
MTL_ENABLE_DEBUG_INFO = NO;
330348
SDKROOT = iphoneos;
331349
SUPPORTED_PLATFORMS = iphoneos;
@@ -402,7 +420,7 @@
402420
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
403421
GCC_WARN_UNUSED_FUNCTION = YES;
404422
GCC_WARN_UNUSED_VARIABLE = YES;
405-
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
423+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
406424
MTL_ENABLE_DEBUG_INFO = YES;
407425
ONLY_ACTIVE_ARCH = YES;
408426
SDKROOT = iphoneos;
@@ -451,7 +469,7 @@
451469
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
452470
GCC_WARN_UNUSED_FUNCTION = YES;
453471
GCC_WARN_UNUSED_VARIABLE = YES;
454-
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
472+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
455473
MTL_ENABLE_DEBUG_INFO = NO;
456474
SDKROOT = iphoneos;
457475
SUPPORTED_PLATFORMS = iphoneos;

lib/core/debouncer.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import 'dart:async';
2+
import 'dart:ui';
3+
4+
class Debouncer {
5+
final int milliseconds;
6+
VoidCallback? action;
7+
Timer? _timer;
8+
9+
Debouncer({required this.milliseconds});
10+
11+
run(VoidCallback action) {
12+
if (_timer != null) {
13+
_timer!.cancel();
14+
}
15+
_timer = Timer(Duration(milliseconds: milliseconds), action);
16+
}
17+
}

lib/data/api/activity_api.dart

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:dio/dio.dart';
33
import '../model/request/activity_request.dart';
44
import '../model/response/activity_comment_response.dart';
55
import '../model/response/activity_response.dart';
6+
import '../model/response/page_response.dart';
67
import 'helpers/api_helper.dart';
78

89
/// API methods for managing activities.
@@ -12,32 +13,47 @@ class ActivityApi {
1213
/// Retrieves a list of activities.
1314
///
1415
/// Returns a list of [ActivityResponse] objects.
15-
static Future<List<ActivityResponse>> getActivities() async {
16-
Response? response =
17-
await ApiHelper.makeRequest('${ActivityApi.url}all', 'GET');
18-
final data = List<Map<String, dynamic>>.from(response?.data);
19-
return data.map((e) => ActivityResponse.fromMap(e)).toList();
16+
static Future<PageResponse<ActivityResponse>> getActivities(
17+
int pageNumber) async {
18+
Response? response = await ApiHelper.makeRequest(
19+
'${ActivityApi.url}all', 'GET',
20+
queryParams: {'page': pageNumber, 'size': 5});
21+
22+
PageResponse pageResponse = PageResponse.fromMap(response?.data);
23+
final data = List<Map<String, dynamic>>.from(pageResponse.list);
24+
List<ActivityResponse> activities =
25+
data.map((e) => ActivityResponse.fromMap(e)).toList();
26+
return PageResponse(list: activities, total: pageResponse.total);
2027
}
2128

2229
/// Retrieves a list of my activities and my friends.
2330
///
2431
/// Returns a list of [ActivityResponse] objects.
25-
static Future<List<ActivityResponse>> getMyAndMyFriendsActivities() async {
32+
static Future<PageResponse<ActivityResponse>> getMyAndMyFriendsActivities(
33+
int pageNumber) async {
2634
Response? response = await ApiHelper.makeRequest(
2735
'${ActivityApi.url}friends', 'GET',
28-
noCache: true);
29-
final data = List<Map<String, dynamic>>.from(response?.data);
30-
return data.map((e) => ActivityResponse.fromMap(e)).toList();
36+
queryParams: {'page': pageNumber, 'size': 3}, noCache: true);
37+
PageResponse pageResponse = PageResponse.fromMap(response?.data);
38+
final data = List<Map<String, dynamic>>.from(pageResponse.list);
39+
List<ActivityResponse> activities =
40+
data.map((e) => ActivityResponse.fromMap(e)).toList();
41+
return PageResponse(list: activities, total: pageResponse.total);
3142
}
3243

3344
/// Retrieves a list of a user activities.
3445
///
3546
/// Returns a list of [ActivityResponse] objects.
36-
static Future<List<ActivityResponse>> getUserActivities(String userId) async {
37-
Response? response =
38-
await ApiHelper.makeRequest('${ActivityApi.url}user/$userId', 'GET');
39-
final data = List<Map<String, dynamic>>.from(response?.data);
40-
return data.map((e) => ActivityResponse.fromMap(e)).toList();
47+
static Future<PageResponse<ActivityResponse>> getUserActivities(
48+
String userId, int pageNumber) async {
49+
Response? response = await ApiHelper.makeRequest(
50+
'${ActivityApi.url}user/$userId', 'GET',
51+
queryParams: {'page': pageNumber, 'size': 5});
52+
PageResponse pageResponse = PageResponse.fromMap(response?.data);
53+
final data = List<Map<String, dynamic>>.from(pageResponse.list);
54+
List<ActivityResponse> activities =
55+
data.map((e) => ActivityResponse.fromMap(e)).toList();
56+
return PageResponse(list: activities, total: pageResponse.total);
4157
}
4258

4359
/// Retrieves an activity by its ID.

lib/data/api/friend_request_api.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
21
import 'package:dio/dio.dart';
32

43
import '../../domain/entities/enum/friend_request_status.dart';
54
import '../model/response/friend_request_response.dart';
5+
import '../model/response/page_response.dart';
66
import '../model/response/user_response.dart';
77
import 'helpers/api_helper.dart';
88

@@ -13,12 +13,16 @@ class FriendRequestApi {
1313
/// Retrieves a list of users for whom I have a pending request.
1414
///
1515
/// Returns a list of [UserResponse] objects.
16-
static Future<List<UserResponse>> getPendindRequestUsers() async {
16+
static Future<PageResponse<UserResponse>> getPendindRequestUsers(
17+
int pageNumber) async {
1718
Response? response = await ApiHelper.makeRequest(
1819
'${FriendRequestApi.url}pending', 'GET',
19-
noCache: true);
20-
final data = List<Map<String, dynamic>>.from(response?.data);
21-
return data.map((e) => UserResponse.fromMap(e)).toList();
20+
queryParams: {'page': pageNumber, 'size': 20}, noCache: true);
21+
PageResponse pageResponse = PageResponse.fromMap(response?.data);
22+
final data = List<Map<String, dynamic>>.from(pageResponse.list);
23+
List<UserResponse> users =
24+
data.map((e) => UserResponse.fromMap(e)).toList();
25+
return PageResponse(list: users, total: pageResponse.total);
2226
}
2327

2428
/// Retrieves the status of the friend request I have with the user

lib/data/api/helpers/api_helper.dart

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import '../user_api.dart';
1111
/// Helper class for making API requests.
1212
class ApiHelper {
1313
// switch url when back is down
14-
//static const String apiUrl =
15-
// 'http://lxgfjcmoky.us18.qoddiapp.com/api/'; //US server
1614
static const String apiUrl =
17-
'http://tiqorhzmyb.eu11.qoddiapp.com/api/'; //EU server
15+
'http://lxgfjcmoky.us18.qoddiapp.com/api/'; //US server
16+
//static const String apiUrl =
17+
// 'http://tiqorhzmyb.eu11.qoddiapp.com/api/'; //EU server
1818

1919
/// Makes an HTTP request to the specified [url] using the given [method].
2020
///
@@ -129,11 +129,15 @@ class RemoteApi {
129129
}
130130
}
131131

132-
if (options.method == 'POST' ||
132+
if (options.method == 'POST_FORM_DATA' ||
133+
options.method == 'POST' ||
133134
options.method == 'PUT' ||
134135
options.method == 'DELETE') {
135-
prefs.remove('${url}all');
136-
prefs.remove('${url}all:timestamp');
136+
Set<String> keys = prefs.getKeys();
137+
138+
keys.where((key) => key.startsWith('${url}all')).forEach((key) {
139+
prefs.remove(key);
140+
});
137141
}
138142

139143
handler.next(options);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class PageResponse<T> {
2+
final List<T> list;
3+
final int total;
4+
5+
const PageResponse({
6+
required this.list,
7+
required this.total,
8+
});
9+
10+
factory PageResponse.fromMap(Map<String, dynamic> map) {
11+
return PageResponse(list: map['content'], total: map['totalElements']);
12+
}
13+
}

lib/data/repositories/activity_repository_impl.dart

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
22

33
import '../../domain/entities/activity.dart';
44
import '../../domain/entities/activity_comment.dart';
5+
import '../../domain/entities/page.dart';
56
import '../../domain/repositories/activity_repository.dart';
67
import '../api/activity_api.dart';
78
import '../model/request/activity_request.dart';
@@ -15,21 +16,32 @@ class ActivityRepositoryImpl extends ActivityRepository {
1516
ActivityRepositoryImpl();
1617

1718
@override
18-
Future<List<Activity>> getActivities() async {
19-
final activityResponses = await ActivityApi.getActivities();
20-
return activityResponses.map((response) => response.toEntity()).toList();
19+
Future<EntityPage<Activity>> getActivities({int pageNumber = 0}) async {
20+
final activityResponses = await ActivityApi.getActivities(pageNumber);
21+
List<Activity> activities =
22+
activityResponses.list.map((response) => response.toEntity()).toList();
23+
return EntityPage(list: activities, total: activityResponses.total);
2124
}
2225

2326
@override
24-
Future<List<Activity>> getMyAndMyFriendsActivities() async {
25-
final activityResponses = await ActivityApi.getMyAndMyFriendsActivities();
26-
return activityResponses.map((response) => response.toEntity()).toList();
27+
Future<EntityPage<Activity>> getMyAndMyFriendsActivities(
28+
{int pageNumber = 0}) async {
29+
final activityResponses =
30+
await ActivityApi.getMyAndMyFriendsActivities(pageNumber);
31+
32+
List<Activity> activities =
33+
activityResponses.list.map((response) => response.toEntity()).toList();
34+
return EntityPage(list: activities, total: activityResponses.total);
2735
}
2836

2937
@override
30-
Future<List<Activity>> getUserActivities(String userId) async {
31-
final activityResponses = await ActivityApi.getUserActivities(userId);
32-
return activityResponses.map((response) => response.toEntity()).toList();
38+
Future<EntityPage<Activity>> getUserActivities(String userId,
39+
{int pageNumber = 0}) async {
40+
final activityResponses =
41+
await ActivityApi.getUserActivities(userId, pageNumber);
42+
List<Activity> activities =
43+
activityResponses.list.map((response) => response.toEntity()).toList();
44+
return EntityPage(list: activities, total: activityResponses.total);
3345
}
3446

3547
@override

lib/data/repositories/friend_request_repository_impl.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
21
import 'package:hooks_riverpod/hooks_riverpod.dart';
2+
import '../../domain/entities/page.dart';
33
import '../api/friend_request_api.dart';
44
import '../../domain/entities/enum/friend_request_status.dart';
55
import '../../domain/repositories/friend_request_repository.dart';
@@ -16,12 +16,14 @@ class FriendRequestRepositoryImpl extends FriendRequestRepository {
1616
FriendRequestRepositoryImpl();
1717

1818
@override
19-
Future<List<User>> getPendingRequestUsers() async {
19+
Future<EntityPage<User>> getPendingRequestUsers({int pageNumber = 0}) async {
2020
final pendingUsersResponses =
21-
await FriendRequestApi.getPendindRequestUsers();
22-
return pendingUsersResponses
21+
await FriendRequestApi.getPendindRequestUsers(pageNumber);
22+
23+
List<User> users = pendingUsersResponses.list
2324
.map((response) => response.toEntity())
2425
.toList();
26+
return EntityPage(list: users, total: pendingUsersResponses.total);
2527
}
2628

2729
@override

0 commit comments

Comments
 (0)