@@ -121,97 +121,97 @@ class _HeadlinesFeedPageState extends State<HeadlinesFeedPage> {
121121 ),
122122 ),
123123 ),
124- body: Column (
125- children: [
126- const Padding (
127- padding: EdgeInsets .symmetric (horizontal: AppSpacing .md),
128- child: SavedFiltersBar (),
129- ),
130- Expanded (
131- child: BlocBuilder <HeadlinesFeedBloc , HeadlinesFeedState >(
132- builder: (context, state) {
133- // Access the AppBloc to check for remoteConfig availability.
134- final appBlocState = context.watch <AppBloc >().state;
124+ body: BlocBuilder <HeadlinesFeedBloc , HeadlinesFeedState >(
125+ builder: (context, state) {
126+ // Access the AppBloc to check for remoteConfig availability.
127+ final appBlocState = context.watch <AppBloc >().state;
128+
129+ // If remoteConfig is not yet loaded, show a loading indicator.
130+ // This handles the brief period after authentication but before
131+ // the remote config is fetched, preventing null access errors.
132+ if (appBlocState.remoteConfig == null ) {
133+ return LoadingStateWidget (
134+ icon: Icons .settings_applications_outlined,
135+ headline: l10n.headlinesFeedLoadingHeadline,
136+ subheadline: l10n.pleaseWait,
137+ );
138+ }
135139
136- // If remoteConfig is not yet loaded, show a loading indicator.
137- // This handles the brief period after authentication but before
138- // the remote config is fetched, preventing null access errors.
139- if (appBlocState.remoteConfig == null ) {
140- return LoadingStateWidget (
141- icon: Icons .settings_applications_outlined,
142- headline: l10n.headlinesFeedLoadingHeadline,
143- subheadline: l10n.pleaseWait,
144- );
145- }
140+ if (state.status == HeadlinesFeedStatus .initial ||
141+ (state.status == HeadlinesFeedStatus .loading &&
142+ state.feedItems.isEmpty)) {
143+ return LoadingStateWidget (
144+ icon: Icons .newspaper,
145+ headline: l10n.headlinesFeedLoadingHeadline,
146+ subheadline: l10n.headlinesFeedLoadingSubheadline,
147+ );
148+ }
146149
147- if (state.status == HeadlinesFeedStatus .initial ||
148- (state.status == HeadlinesFeedStatus .loading &&
149- state.feedItems.isEmpty)) {
150- return LoadingStateWidget (
151- icon: Icons .newspaper,
152- headline: l10n.headlinesFeedLoadingHeadline,
153- subheadline: l10n.headlinesFeedLoadingSubheadline,
154- );
155- }
150+ if (state.status == HeadlinesFeedStatus .failure &&
151+ state.feedItems.isEmpty) {
152+ return FailureStateWidget (
153+ //TODO(fulleni): l10n.
154+ exception:
155+ state.error ??
156+ const UnknownException ('Failed to load headlines feed.' ),
157+ onRetry: () => context.read <HeadlinesFeedBloc >().add (
158+ HeadlinesFeedRefreshRequested (
159+ adThemeStyle: AdThemeStyle .fromTheme (theme),
160+ ),
161+ ),
162+ );
163+ }
156164
157- if (state.status == HeadlinesFeedStatus .failure &&
158- state.feedItems.isEmpty) {
159- return FailureStateWidget (
160- //TODO(fulleni): l10n.
161- exception:
162- state.error ??
163- const UnknownException (
164- 'Failed to load headlines feed.' ,
165- ),
166- onRetry: () => context.read <HeadlinesFeedBloc >().add (
167- HeadlinesFeedRefreshRequested (
165+ if (state.status == HeadlinesFeedStatus .success &&
166+ state.feedItems.isEmpty) {
167+ return Center (
168+ child: Column (
169+ mainAxisAlignment: MainAxisAlignment .center,
170+ children: [
171+ InitialStateWidget (
172+ icon: Icons .search_off,
173+ headline: l10n.headlinesFeedEmptyFilteredHeadline,
174+ subheadline: l10n.headlinesFeedEmptyFilteredSubheadline,
175+ ),
176+ const SizedBox (height: AppSpacing .lg),
177+ ElevatedButton (
178+ onPressed: () => context.read <HeadlinesFeedBloc >().add (
179+ HeadlinesFeedFiltersCleared (
168180 adThemeStyle: AdThemeStyle .fromTheme (theme),
169181 ),
170182 ),
171- );
172- }
173-
174- if (state.status == HeadlinesFeedStatus .success &&
175- state.feedItems.isEmpty) {
176- return Center (
177- child: Column (
178- mainAxisAlignment: MainAxisAlignment .center,
179- children: [
180- InitialStateWidget (
181- icon: Icons .search_off,
182- headline: l10n.headlinesFeedEmptyFilteredHeadline,
183- subheadline:
184- l10n.headlinesFeedEmptyFilteredSubheadline,
185- ),
186- const SizedBox (height: AppSpacing .lg),
187- ElevatedButton (
188- onPressed: () =>
189- context.read <HeadlinesFeedBloc >().add (
190- HeadlinesFeedFiltersCleared (
191- adThemeStyle: AdThemeStyle .fromTheme (theme),
192- ),
193- ),
194- child: Text (l10n.headlinesFeedClearFiltersButton),
195- ),
196- ],
197- ),
198- );
199- }
183+ child: Text (l10n.headlinesFeedClearFiltersButton),
184+ ),
185+ ],
186+ ),
187+ );
188+ }
200189
201- return RefreshIndicator (
202- onRefresh: () async {
203- context.read <HeadlinesFeedBloc >().add (
204- HeadlinesFeedRefreshRequested (
205- adThemeStyle: AdThemeStyle .fromTheme (theme),
206- ),
207- );
208- },
209- child: ListView .separated (
210- controller: _scrollController,
211- padding: const EdgeInsets .only (
212- top: AppSpacing .md,
213- bottom: AppSpacing .xxl,
190+ return RefreshIndicator (
191+ onRefresh: () async {
192+ context.read <HeadlinesFeedBloc >().add (
193+ HeadlinesFeedRefreshRequested (
194+ adThemeStyle: AdThemeStyle .fromTheme (theme),
195+ ),
196+ );
197+ },
198+ child: CustomScrollView (
199+ controller: _scrollController,
200+ slivers: [
201+ const SliverToBoxAdapter (
202+ child: Padding (
203+ padding: EdgeInsets .symmetric (
204+ horizontal: AppSpacing .md,
214205 ),
206+ child: SavedFiltersBar (),
207+ ),
208+ ),
209+ SliverPadding (
210+ padding: const EdgeInsets .only (
211+ top: AppSpacing .md,
212+ bottom: AppSpacing .xxl,
213+ ),
214+ sliver: SliverList .separated (
215215 itemCount: state.hasMore
216216 ? state.feedItems.length + 1
217217 : state.feedItems.length,
@@ -401,11 +401,11 @@ class _HeadlinesFeedPageState extends State<HeadlinesFeedPage> {
401401 return const SizedBox .shrink ();
402402 },
403403 ),
404- );
405- } ,
404+ ),
405+ ] ,
406406 ),
407- ),
408- ] ,
407+ );
408+ } ,
409409 ),
410410 ),
411411 );
0 commit comments