Skip to content

Commit

Permalink
Add pagination in team matches
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-mayank committed Dec 11, 2024
1 parent 249ef9e commit b71e9df
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 46 deletions.
20 changes: 14 additions & 6 deletions data/lib/service/match/match_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,23 @@ class MatchService {
}).handleError((error, stack) => throw AppError.fromError(error, stack));
}

Stream<List<MatchModel>> streamMatchesByTeamId(String teamId) {
return _matchCollection
Stream<List<MatchModel>> streamMatchesByTeamId({
required String teamId,
String? lastMatchId,
int limit = 10,
}) {
var query = _matchCollection
.where(FireStoreConst.teamIds, arrayContains: teamId)
.snapshots()
.asyncMap((snapshot) async {
.orderBy(FieldPath.documentId);

if (lastMatchId != null) {
query = query.startAfter([lastMatchId]);
}

return query.limit(limit).snapshots().asyncMap((snapshot) async {
return await Future.wait(
snapshot.docs.map((mainDoc) async {
final match = mainDoc.data();

final List<MatchTeamModel> teams = await getTeamsList(match.teams);
return match.copyWith(teams: teams);
}).toList(),
Expand Down Expand Up @@ -635,7 +643,7 @@ class MatchService {

Stream<List<MatchModel>> streamMatchesByIds(List<String> matchIds) {
try {
if (matchIds.isEmpty) return Stream.empty();
if (matchIds.isEmpty) return Stream.value([]);
return _matchCollection
.where(FieldPath.documentId, whereIn: matchIds)
.snapshots()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import 'package:khelo/components/match_detail_cell.dart';
import 'package:khelo/domain/extensions/context_extensions.dart';
import 'package:khelo/ui/app_route.dart';
import 'package:khelo/ui/flow/team/detail/team_detail_view_model.dart';
import 'package:style/callback/on_visible_callback.dart';
import 'package:style/indicator/progress_indicator.dart';

import '../../../../../domain/extensions/widget_extension.dart';

class TeamDetailMatchContent extends ConsumerWidget {
const TeamDetailMatchContent({super.key});
Expand All @@ -17,29 +21,38 @@ class TeamDetailMatchContent extends ConsumerWidget {
final isAdminOrOwner =
state.team?.isAdminOrOwner(state.currentUserId) ?? false;

if (state.matches != null && state.matches!.isNotEmpty) {
if (state.matches.isNotEmpty) {
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: state.matches?.length ?? 0,
itemCount: state.matches.length + 1,
itemBuilder: (context, index) {
final match = state.matches![index];
return MatchDetailCell(
match: match,
showActionButtons: isAdminOrOwner,
onTap: () =>
AppRoute.matchDetailTab(matchId: match.id).push(context),
onActionTap: () {
if (match.match_status == MatchStatus.yetToStart) {
AppRoute.addMatch(matchId: match.id).push(context);
} else {
if (match.toss_decision == null ||
match.toss_winner_id == null) {
AppRoute.addTossDetail(matchId: match.id).push(context);
if (index < state.matches.length) {
final match = state.matches[index];
return MatchDetailCell(
match: match,
showActionButtons: isAdminOrOwner,
onTap: () =>
AppRoute.matchDetailTab(matchId: match.id).push(context),
onActionTap: () {
if (match.match_status == MatchStatus.yetToStart) {
AppRoute.addMatch(matchId: match.id).push(context);
} else {
AppRoute.scoreBoard(matchId: match.id).push(context);
if (match.toss_decision == null ||
match.toss_winner_id == null) {
AppRoute.addTossDetail(matchId: match.id).push(context);
} else {
AppRoute.scoreBoard(matchId: match.id).push(context);
}
}
}
},
},
);
}
return OnVisibleCallback(
onVisible: () => runPostFrame(
ref.read(teamDetailStateProvider.notifier).loadData),
child: (state.loading && state.matches.isNotEmpty)
? const Center(child: AppProgressIndicator())
: const SizedBox(),
);
},
separatorBuilder: (context, index) => const SizedBox(height: 16),
Expand Down
22 changes: 17 additions & 5 deletions khelo/lib/ui/flow/team/detail/team_detail_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,34 @@ class TeamDetailViewNotifier extends StateNotifier<TeamDetailState> {
TeamDetailViewNotifier(this._teamService, this._matchService, String? userId)
: super(TeamDetailState(currentUserId: userId));

bool _maxLoaded = false;
String? _lastMatchId;

void setData(String teamId) {
_teamId = teamId;
loadData();
}

void loadData() {
if (_teamId == null) return;
if (_maxLoaded || state.loading) return;
_teamStreamSubscription?.cancel();
state =
state.copyWith(loading: state.team == null || state.matches == null);
final teamCombiner = combineLatest2(_teamService.streamTeamById(_teamId!),
_matchService.streamMatchesByTeamId(_teamId!));
state.copyWith(loading: state.team == null || state.matches.isEmpty);
final teamCombiner = combineLatest2(
_teamService.streamTeamById(_teamId!),
_matchService.streamMatchesByTeamId(
teamId: _teamId!, lastMatchId: _lastMatchId, limit: 10),
);
_teamStreamSubscription = teamCombiner.listen((data) {
_maxLoaded = data.$2.length < 10;

if (data.$2.isNotEmpty) {
_lastMatchId = data.$2.last.id;
}
state = state.copyWith(
team: data.$1,
matches: data.$2,
matches: {...state.matches, ...data.$2}.toList(),
loading: false,
);
}, onError: (e) {
Expand Down Expand Up @@ -73,7 +85,7 @@ class TeamDetailState with _$TeamDetailState {
Object? error,
TeamModel? team,
String? currentUserId,
List<MatchModel>? matches,
@Default([]) List<MatchModel> matches,
@Default(0) int selectedTab,
@Default(false) bool loading,
}) = _TeamDetailState;
Expand Down
33 changes: 16 additions & 17 deletions khelo/lib/ui/flow/team/detail/team_detail_view_model.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mixin _$TeamDetailState {
Object? get error => throw _privateConstructorUsedError;
TeamModel? get team => throw _privateConstructorUsedError;
String? get currentUserId => throw _privateConstructorUsedError;
List<MatchModel>? get matches => throw _privateConstructorUsedError;
List<MatchModel> get matches => throw _privateConstructorUsedError;
int get selectedTab => throw _privateConstructorUsedError;
bool get loading => throw _privateConstructorUsedError;

Expand All @@ -40,7 +40,7 @@ abstract class $TeamDetailStateCopyWith<$Res> {
{Object? error,
TeamModel? team,
String? currentUserId,
List<MatchModel>? matches,
List<MatchModel> matches,
int selectedTab,
bool loading});

Expand All @@ -65,7 +65,7 @@ class _$TeamDetailStateCopyWithImpl<$Res, $Val extends TeamDetailState>
Object? error = freezed,
Object? team = freezed,
Object? currentUserId = freezed,
Object? matches = freezed,
Object? matches = null,
Object? selectedTab = null,
Object? loading = null,
}) {
Expand All @@ -79,10 +79,10 @@ class _$TeamDetailStateCopyWithImpl<$Res, $Val extends TeamDetailState>
? _value.currentUserId
: currentUserId // ignore: cast_nullable_to_non_nullable
as String?,
matches: freezed == matches
matches: null == matches
? _value.matches
: matches // ignore: cast_nullable_to_non_nullable
as List<MatchModel>?,
as List<MatchModel>,
selectedTab: null == selectedTab
? _value.selectedTab
: selectedTab // ignore: cast_nullable_to_non_nullable
Expand Down Expand Up @@ -121,7 +121,7 @@ abstract class _$$TeamDetailStateImplCopyWith<$Res>
{Object? error,
TeamModel? team,
String? currentUserId,
List<MatchModel>? matches,
List<MatchModel> matches,
int selectedTab,
bool loading});

Expand All @@ -145,7 +145,7 @@ class __$$TeamDetailStateImplCopyWithImpl<$Res>
Object? error = freezed,
Object? team = freezed,
Object? currentUserId = freezed,
Object? matches = freezed,
Object? matches = null,
Object? selectedTab = null,
Object? loading = null,
}) {
Expand All @@ -159,10 +159,10 @@ class __$$TeamDetailStateImplCopyWithImpl<$Res>
? _value.currentUserId
: currentUserId // ignore: cast_nullable_to_non_nullable
as String?,
matches: freezed == matches
matches: null == matches
? _value._matches
: matches // ignore: cast_nullable_to_non_nullable
as List<MatchModel>?,
as List<MatchModel>,
selectedTab: null == selectedTab
? _value.selectedTab
: selectedTab // ignore: cast_nullable_to_non_nullable
Expand All @@ -182,7 +182,7 @@ class _$TeamDetailStateImpl implements _TeamDetailState {
{this.error,
this.team,
this.currentUserId,
final List<MatchModel>? matches,
final List<MatchModel> matches = const [],
this.selectedTab = 0,
this.loading = false})
: _matches = matches;
Expand All @@ -193,14 +193,13 @@ class _$TeamDetailStateImpl implements _TeamDetailState {
final TeamModel? team;
@override
final String? currentUserId;
final List<MatchModel>? _matches;
final List<MatchModel> _matches;
@override
List<MatchModel>? get matches {
final value = _matches;
if (value == null) return null;
@JsonKey()
List<MatchModel> get matches {
if (_matches is EqualUnmodifiableListView) return _matches;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
return EqualUnmodifiableListView(_matches);
}

@override
Expand Down Expand Up @@ -255,7 +254,7 @@ abstract class _TeamDetailState implements TeamDetailState {
{final Object? error,
final TeamModel? team,
final String? currentUserId,
final List<MatchModel>? matches,
final List<MatchModel> matches,
final int selectedTab,
final bool loading}) = _$TeamDetailStateImpl;

Expand All @@ -266,7 +265,7 @@ abstract class _TeamDetailState implements TeamDetailState {
@override
String? get currentUserId;
@override
List<MatchModel>? get matches;
List<MatchModel> get matches;
@override
int get selectedTab;
@override
Expand Down

0 comments on commit b71e9df

Please sign in to comment.