@@ -7,9 +7,22 @@ import 'package:ht_main/shared/widgets/failure_state_widget.dart';
77import 'package:ht_main/shared/widgets/initial_state_widget.dart' ;
88import 'package:ht_main/shared/widgets/loading_state_widget.dart' ;
99
10- class HeadlinesSearchView extends StatelessWidget {
10+ class HeadlinesSearchView extends StatefulWidget {
1111 const HeadlinesSearchView ({super .key});
1212
13+ @override
14+ State <HeadlinesSearchView > createState () => _HeadlinesSearchViewState ();
15+ }
16+
17+ class _HeadlinesSearchViewState extends State <HeadlinesSearchView > {
18+ final _scrollController = ScrollController ();
19+
20+ @override
21+ void initState () {
22+ super .initState ();
23+ _scrollController.addListener (_onScroll);
24+ }
25+
1326 @override
1427 Widget build (BuildContext context) {
1528 return Scaffold (
@@ -48,8 +61,14 @@ class HeadlinesSearchView extends StatelessWidget {
4861 headline: 'Loading...' ,
4962 subheadline: 'Fetching headlines' ,
5063 ),
51- HeadlinesSearchLoaded (: final headlines) =>
52- _HeadlinesSearchLoadedView (headlines: headlines),
64+ HeadlinesSearchLoaded (
65+ : final headlines,
66+ : final hasReachedMax
67+ ) =>
68+ _HeadlinesSearchLoadedView (
69+ headlines: headlines,
70+ hasReachedMax: hasReachedMax,
71+ ),
5372 HeadlinesSearchError (: final message) => FailureStateWidget (
5473 message: message,
5574 onRetry: () {
@@ -63,18 +82,48 @@ class HeadlinesSearchView extends StatelessWidget {
6382 ),
6483 );
6584 }
85+
86+ @override
87+ void dispose () {
88+ _scrollController
89+ ..removeListener (_onScroll)
90+ ..dispose ();
91+ super .dispose ();
92+ }
93+
94+ void _onScroll () {
95+ if (_isBottom) {
96+ context.read <HeadlinesSearchBloc >().add (HeadlinesSearchLoadMore ());
97+ }
98+ }
99+
100+ bool get _isBottom {
101+ if (! _scrollController.hasClients) return false ;
102+ final maxScroll = _scrollController.position.maxScrollExtent;
103+ final currentScroll = _scrollController.offset;
104+ return currentScroll >= (maxScroll * 0.9 );
105+ }
66106}
67107
68108class _HeadlinesSearchLoadedView extends StatelessWidget {
69- const _HeadlinesSearchLoadedView ({required this .headlines});
109+ const _HeadlinesSearchLoadedView ({
110+ required this .headlines,
111+ required this .hasReachedMax,
112+ });
70113
71114 final List <Headline > headlines;
115+ final bool hasReachedMax;
72116
73117 @override
74118 Widget build (BuildContext context) {
75119 return ListView .builder (
76- itemCount: headlines.length,
120+ itemCount: hasReachedMax ? headlines.length : headlines.length + 1 ,
77121 itemBuilder: (context, index) {
122+ if (index >= headlines.length) {
123+ return const Center (
124+ child: CircularProgressIndicator (),
125+ );
126+ }
78127 return HeadlineItemWidget (headline: headlines[index]);
79128 },
80129 );
0 commit comments