@@ -19,11 +19,8 @@ import 'package:share_plus/share_plus.dart'; // Import share_plus
19
19
import 'package:url_launcher/url_launcher_string.dart' ;
20
20
21
21
class HeadlineDetailsPage extends StatefulWidget {
22
- const HeadlineDetailsPage ({
23
- super .key,
24
- this .headlineId,
25
- this .initialHeadline,
26
- }) : assert (headlineId != null || initialHeadline != null );
22
+ const HeadlineDetailsPage ({super .key, this .headlineId, this .initialHeadline})
23
+ : assert (headlineId != null || initialHeadline != null );
27
24
28
25
final String ? headlineId;
29
26
final Headline ? initialHeadline;
@@ -37,17 +34,17 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
37
34
void initState () {
38
35
super .initState ();
39
36
if (widget.initialHeadline != null ) {
40
- context
41
- . read < HeadlineDetailsBloc >()
42
- . add ( HeadlineProvided (widget.initialHeadline ! ) );
37
+ context. read < HeadlineDetailsBloc >(). add (
38
+ HeadlineProvided (widget.initialHeadline ! ),
39
+ );
43
40
// Also trigger fetching similar headlines if the main one is already provided
44
- context
45
- . read < SimilarHeadlinesBloc >()
46
- . add ( FetchSimilarHeadlines (currentHeadline : widget.initialHeadline ! ) );
41
+ context. read < SimilarHeadlinesBloc >(). add (
42
+ FetchSimilarHeadlines (currentHeadline : widget.initialHeadline ! ),
43
+ );
47
44
} else if (widget.headlineId != null ) {
48
- context
49
- . read < HeadlineDetailsBloc >()
50
- . add ( FetchHeadlineById (widget.headlineId ! ) );
45
+ context. read < HeadlineDetailsBloc >(). add (
46
+ FetchHeadlineById (widget.headlineId ! ),
47
+ );
51
48
}
52
49
}
53
50
@@ -63,8 +60,8 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
63
60
// This check ensures it's not re-triggered if already loaded via initialHeadline.
64
61
if (widget.initialHeadline == null ) {
65
62
context.read <SimilarHeadlinesBloc >().add (
66
- FetchSimilarHeadlines (currentHeadline: headlineState.headline),
67
- );
63
+ FetchSimilarHeadlines (currentHeadline: headlineState.headline),
64
+ );
68
65
}
69
66
}
70
67
},
@@ -77,21 +74,21 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
77
74
final currentHeadlineId = detailsState.headline.id;
78
75
final wasPreviouslySaved =
79
76
previous.preferences? .savedHeadlines.any (
80
- (h) => h.id == currentHeadlineId,
81
- ) ??
82
- false ;
77
+ (h) => h.id == currentHeadlineId,
78
+ ) ??
79
+ false ;
83
80
final isCurrentlySaved =
84
81
current.preferences? .savedHeadlines.any (
85
- (h) => h.id == currentHeadlineId,
86
- ) ??
87
- false ;
82
+ (h) => h.id == currentHeadlineId,
83
+ ) ??
84
+ false ;
88
85
89
86
// Condition 1: Actual change in saved status for this headline
90
87
if (wasPreviouslySaved != isCurrentlySaved) {
91
88
// Only trigger if the status is success (to show confirmation)
92
89
// or failure (to show error). Avoid triggering if status is just loading.
93
90
return current.status == AccountStatus .success ||
94
- current.status == AccountStatus .failure;
91
+ current.status == AccountStatus .failure;
95
92
}
96
93
97
94
// Condition 2: A specific save/unsave operation just failed
@@ -108,9 +105,9 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
108
105
if (detailsState is HeadlineDetailsLoaded ) {
109
106
final nowIsSaved =
110
107
accountState.preferences? .savedHeadlines.any (
111
- (h) => h.id == detailsState.headline.id,
112
- ) ??
113
- false ;
108
+ (h) => h.id == detailsState.headline.id,
109
+ ) ??
110
+ false ;
114
111
115
112
if (accountState.status == AccountStatus .failure &&
116
113
accountState.errorMessage != null ) {
@@ -145,20 +142,19 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
145
142
builder: (context, state) {
146
143
return switch (state) {
147
144
HeadlineDetailsInitial () ||
148
- HeadlineDetailsLoading () =>
149
- LoadingStateWidget (
150
- icon: Icons .downloading,
151
- headline: l10n.headlineDetailsLoadingHeadline,
152
- subheadline: l10n.headlineDetailsLoadingSubheadline,
153
- ),
145
+ HeadlineDetailsLoading () => LoadingStateWidget (
146
+ icon: Icons .downloading,
147
+ headline: l10n.headlineDetailsLoadingHeadline,
148
+ subheadline: l10n.headlineDetailsLoadingSubheadline,
149
+ ),
154
150
final HeadlineDetailsFailure failureState =>
155
151
FailureStateWidget (
156
152
message: failureState.message,
157
153
onRetry: () {
158
154
if (widget.headlineId != null ) {
159
- context
160
- . read < HeadlineDetailsBloc >()
161
- . add ( FetchHeadlineById (widget.headlineId ! ) );
155
+ context. read < HeadlineDetailsBloc >(). add (
156
+ FetchHeadlineById (widget.headlineId ! ),
157
+ );
162
158
}
163
159
},
164
160
),
@@ -187,19 +183,20 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
187
183
final accountState = context.watch <AccountBloc >().state;
188
184
final isSaved =
189
185
accountState.preferences? .savedHeadlines.any (
190
- (h) => h.id == headline.id,
191
- ) ??
192
- false ;
186
+ (h) => h.id == headline.id,
187
+ ) ??
188
+ false ;
193
189
194
190
final bookmarkButton = IconButton (
195
191
icon: Icon (isSaved ? Icons .bookmark : Icons .bookmark_border),
196
- tooltip: isSaved
197
- ? l10n.headlineDetailsRemoveFromSavedTooltip
198
- : l10n.headlineDetailsSaveTooltip,
192
+ tooltip:
193
+ isSaved
194
+ ? l10n.headlineDetailsRemoveFromSavedTooltip
195
+ : l10n.headlineDetailsSaveTooltip,
199
196
onPressed: () {
200
197
context.read <AccountBloc >().add (
201
- AccountSaveHeadlineToggled (headline: headline),
202
- );
198
+ AccountSaveHeadlineToggled (headline: headline),
199
+ );
203
200
},
204
201
);
205
202
@@ -241,9 +238,7 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
241
238
if (buttonContext.mounted) {
242
239
if (shareResult.status == ShareResultStatus .unavailable) {
243
240
ScaffoldMessenger .of (buttonContext).showSnackBar (
244
- SnackBar (
245
- content: Text (l10n.sharingUnavailableSnackbar),
246
- ),
241
+ SnackBar (content: Text (l10n.sharingUnavailableSnackbar)),
247
242
);
248
243
}
249
244
}
@@ -297,16 +292,17 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
297
292
child: const Center (child: CircularProgressIndicator ()),
298
293
);
299
294
},
300
- errorBuilder: (context, error, stackTrace) => Container (
301
- width: double .infinity,
302
- height: 200 ,
303
- color: colorScheme.surfaceContainerHighest,
304
- child: Icon (
305
- Icons .broken_image,
306
- color: colorScheme.onSurfaceVariant,
307
- size: AppSpacing .xxl,
308
- ),
309
- ),
295
+ errorBuilder:
296
+ (context, error, stackTrace) => Container (
297
+ width: double .infinity,
298
+ height: 200 ,
299
+ color: colorScheme.surfaceContainerHighest,
300
+ child: Icon (
301
+ Icons .broken_image,
302
+ color: colorScheme.onSurfaceVariant,
303
+ size: AppSpacing .xxl,
304
+ ),
305
+ ),
310
306
),
311
307
),
312
308
),
@@ -400,7 +396,9 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
400
396
}
401
397
402
398
if (headline.publishedAt != null ) {
403
- final formattedDate = DateFormat ('MMM d, yyyy' ).format (headline.publishedAt! );
399
+ final formattedDate = DateFormat (
400
+ 'MMM d, yyyy' ,
401
+ ).format (headline.publishedAt! );
404
402
chips.add (
405
403
Chip (
406
404
avatar: Icon (
@@ -459,58 +457,54 @@ class _HeadlineDetailsPageState extends State<HeadlineDetailsPage> {
459
457
builder: (context, state) {
460
458
return switch (state) {
461
459
SimilarHeadlinesInitial () ||
462
- SimilarHeadlinesLoading () =>
463
- const SliverToBoxAdapter (
464
- child: Padding (
465
- padding: EdgeInsets .all (AppSpacing .lg),
466
- child: Center (child: CircularProgressIndicator ()),
467
- ),
460
+ SimilarHeadlinesLoading () => const SliverToBoxAdapter (
461
+ child: Padding (
462
+ padding: EdgeInsets .all (AppSpacing .lg),
463
+ child: Center (child: CircularProgressIndicator ()),
468
464
),
465
+ ),
469
466
final SimilarHeadlinesError errorState => SliverToBoxAdapter (
470
- child: Padding (
471
- padding: const EdgeInsets .all (AppSpacing .lg),
472
- child: Text (
473
- errorState.message,
474
- textAlign: TextAlign .center,
475
- style: TextStyle (color: Theme .of (context).colorScheme.error),
476
- ),
467
+ child: Padding (
468
+ padding: const EdgeInsets .all (AppSpacing .lg),
469
+ child: Text (
470
+ errorState.message,
471
+ textAlign: TextAlign .center,
472
+ style: TextStyle (color: Theme .of (context).colorScheme.error),
477
473
),
478
474
),
475
+ ),
479
476
SimilarHeadlinesEmpty () => SliverToBoxAdapter (
480
- child: Padding (
481
- padding: const EdgeInsets .all (AppSpacing .lg),
482
- child: Text (
483
- l10n.similarHeadlinesEmpty,
484
- textAlign: TextAlign .center,
485
- ),
477
+ child: Padding (
478
+ padding: const EdgeInsets .all (AppSpacing .lg),
479
+ child: Text (
480
+ l10n.similarHeadlinesEmpty,
481
+ textAlign: TextAlign .center,
486
482
),
487
483
),
484
+ ),
488
485
final SimilarHeadlinesLoaded loadedState => SliverList (
489
- delegate: SliverChildBuilderDelegate (
490
- (context, index) {
491
- final similarHeadline = loadedState.similarHeadlines[index];
492
- return Padding (
493
- padding: const EdgeInsets .symmetric (
494
- horizontal: AppSpacing .paddingMedium,
495
- vertical: AppSpacing .sm,
496
- ),
497
- child: HeadlineItemWidget (
498
- headline: similarHeadline,
499
- // Use the onTap callback for navigation
500
- onTap: (tappedHeadline) {
501
- context.pushNamed (
502
- Routes .articleDetailsName,
503
- pathParameters: {'id' : tappedHeadline.id},
504
- extra: tappedHeadline,
505
- );
506
- },
507
- // targetRouteName: Routes.articleDetailsName, // No longer needed here
508
- ),
509
- );
510
- },
511
- childCount: loadedState.similarHeadlines.length,
512
- ),
513
- ),
486
+ delegate: SliverChildBuilderDelegate ((context, index) {
487
+ final similarHeadline = loadedState.similarHeadlines[index];
488
+ return Padding (
489
+ padding: const EdgeInsets .symmetric (
490
+ horizontal: AppSpacing .paddingMedium,
491
+ vertical: AppSpacing .sm,
492
+ ),
493
+ child: HeadlineItemWidget (
494
+ headline: similarHeadline,
495
+ // Use the onTap callback for navigation
496
+ onTap: (tappedHeadline) {
497
+ context.pushNamed (
498
+ Routes .articleDetailsName,
499
+ pathParameters: {'id' : tappedHeadline.id},
500
+ extra: tappedHeadline,
501
+ );
502
+ },
503
+ // targetRouteName: Routes.articleDetailsName, // No longer needed here
504
+ ),
505
+ );
506
+ }, childCount: loadedState.similarHeadlines.length),
507
+ ),
514
508
_ => const SliverToBoxAdapter (child: SizedBox .shrink ()),
515
509
};
516
510
},
0 commit comments