Skip to content

Commit 3ad8f6e

Browse files
committed
feat(feed): implement feed pagination
- Added cursor based pagination - Implemented scroll listener - Handled initial refresh
1 parent d1f74bb commit 3ad8f6e

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

lib/headlines-feed/bloc/headlines_feed_event.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,16 @@ sealed class HeadlinesFeedEvent extends Equatable {
1414
/// {@template headlines_feed_fetch_requested}
1515
/// Event triggered when the headlines feed needs to be fetched.
1616
/// {@endtemplate}
17-
final class HeadlinesFeedFetchRequested extends HeadlinesFeedEvent {}
17+
final class HeadlinesFeedFetchRequested extends HeadlinesFeedEvent {
18+
/// {@macro headlines_feed_fetch_requested}
19+
const HeadlinesFeedFetchRequested({this.cursor});
20+
21+
/// The cursor for pagination.
22+
final String? cursor;
23+
24+
@override
25+
List<Object> get props => [cursor ?? ''];
26+
}
1827

1928
/// {@template headlines_feed_refresh_requested}
2029
/// Event triggered when the headlines feed needs to be refreshed.

lib/headlines-feed/view/headlines_feed_page.dart

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,41 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
3+
import 'package:ht_headlines_repository/ht_headlines_repository.dart';
34
import 'package:ht_main/headlines-feed/bloc/headlines_feed_bloc.dart';
45
import 'package:ht_main/headlines-feed/widgets/headline_item_widget.dart';
56
import 'package:ht_main/shared/widgets/failure_state_widget.dart';
67
import 'package:ht_main/shared/widgets/initial_state_widget.dart';
78
import 'package:ht_main/shared/widgets/loading_state_widget.dart';
89

9-
class HeadlinesFeedPage extends StatefulWidget {
10+
class HeadlinesFeedPage extends StatelessWidget {
1011
const HeadlinesFeedPage({super.key});
1112

1213
@override
13-
State<HeadlinesFeedPage> createState() => _HeadlinesFeedPageState();
14+
Widget build(BuildContext context) {
15+
return BlocProvider(
16+
create: (context) => HeadlinesFeedBloc(
17+
headlinesRepository: context.read<HtHeadlinesRepository>(),
18+
)..add(const HeadlinesFeedFetchRequested()),
19+
child: const _HeadlinesFeedView(),
20+
);
21+
}
22+
}
23+
24+
class _HeadlinesFeedView extends StatefulWidget {
25+
const _HeadlinesFeedView();
26+
27+
@override
28+
State<_HeadlinesFeedView> createState() => _HeadlinesFeedViewState();
1429
}
1530

16-
class _HeadlinesFeedPageState extends State<HeadlinesFeedPage> {
31+
class _HeadlinesFeedViewState extends State<_HeadlinesFeedView> {
1732
final _scrollController = ScrollController();
1833

1934
@override
2035
void initState() {
2136
super.initState();
2237
_scrollController.addListener(_onScroll);
38+
context.read<HeadlinesFeedBloc>().add(HeadlinesFeedRefreshRequested());
2339
}
2440

2541
@override
@@ -32,7 +48,12 @@ class _HeadlinesFeedPageState extends State<HeadlinesFeedPage> {
3248

3349
void _onScroll() {
3450
if (_isBottom) {
35-
context.read<HeadlinesFeedBloc>().add(HeadlinesFeedFetchRequested());
51+
final state = context.read<HeadlinesFeedBloc>().state;
52+
if (state is HeadlinesFeedLoaded) {
53+
context
54+
.read<HeadlinesFeedBloc>()
55+
.add(HeadlinesFeedFetchRequested(cursor: state.cursor));
56+
}
3657
}
3758
}
3859

lib/headlines-feed/widgets/headline_item_widget.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class HeadlineItemWidget extends StatelessWidget {
1818
crossAxisAlignment: CrossAxisAlignment.start,
1919
children: [
2020
Text(
21-
headline.title ?? 'No Title',
21+
headline.title,
2222
style: Theme.of(context).textTheme.titleMedium,
2323
),
2424
if (headline.description != null)

lib/shared/widgets/failure_state_widget.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ class FailureStateWidget extends StatelessWidget {
55
/// Creates a [FailureStateWidget].
66
///
77
/// The [message] is the error message to display.
8-
/// The [onRetry] is an optional callback to be called when the retry button is pressed.
8+
///
9+
/// The [onRetry] is an optional callback to be called
10+
/// when the retry button is pressed.
911
const FailureStateWidget({
10-
required this.message, super.key,
12+
required this.message,
13+
super.key,
1114
this.onRetry,
1215
});
1316

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: ht_main
22
description: main headlines toolkit mobile app.
3-
version: 0.7.5
3+
version: 0.8.5
44
publish_to: none
55
repository: https://github.com/headlines-toolkit/ht-main
66
environment:

0 commit comments

Comments
 (0)