11import 'package:flutter/material.dart' ;
2- import 'package:go_router/go_router.dart' ; // Added
3- import 'package:ht_main/entity_details/models/entity_type.dart' ;
4- import 'package:ht_main/entity_details/view/entity_details_page.dart' ; // Added for Page Arguments
5- import 'package:ht_main/l10n/app_localizations.dart' ;
2+ import 'package:go_router/go_router.dart' ;
3+ import 'package:ht_main/entity_details/view/entity_details_page.dart' ;
64import 'package:ht_main/l10n/l10n.dart' ;
7- import 'package:ht_main/router/routes.dart' ; // Added
8- import 'package:ht_main/shared/constants/app_spacing.dart' ;
9- import 'package:ht_main/shared/utils/utils.dart' ; // Import the new utility
10- import 'package:ht_shared/ht_shared.dart' show Headline;
11- // timeago import removed from here, handled by utility
5+ import 'package:ht_main/router/routes.dart' ;
6+ import 'package:ht_shared/ht_shared.dart' ;
7+ import 'package:ht_ui_kit/ht_ui_kit.dart' ;
128
139/// {@template headline_tile_image_top}
1410/// A shared widget to display a headline item with a large image at the top.
@@ -34,14 +30,13 @@ class HeadlineTileImageTop extends StatelessWidget {
3430 final Widget ? trailing;
3531
3632 /// The type of the entity currently being viewed in detail (e.g., on a category page).
37- final EntityType ? currentContextEntityType;
33+ final ContentType ? currentContextEntityType;
3834
3935 /// The ID of the entity currently being viewed in detail.
4036 final String ? currentContextEntityId;
4137
4238 @override
4339 Widget build (BuildContext context) {
44- final l10n = context.l10n;
4540 final theme = Theme .of (context);
4641 final textTheme = theme.textTheme;
4742 final colorScheme = theme.colorScheme;
@@ -61,44 +56,33 @@ class HeadlineTileImageTop extends StatelessWidget {
6156 topLeft: Radius .circular (AppSpacing .xs),
6257 topRight: Radius .circular (AppSpacing .xs),
6358 ),
64- child: headline.imageUrl != null
65- ? Image .network (
66- headline.imageUrl,
67- width: double .infinity,
68- height: 180 , // Standard large image height
69- fit: BoxFit .cover,
70- loadingBuilder: (context, child, loadingProgress) {
71- if (loadingProgress == null ) return child;
72- return Container (
73- width: double .infinity,
74- height: 180 ,
75- color: colorScheme.surfaceContainerHighest,
76- child: const Center (
77- child: CircularProgressIndicator (strokeWidth: 2 ),
78- ),
79- );
80- },
81- errorBuilder: (context, error, stackTrace) => Container (
82- width: double .infinity,
83- height: 180 ,
84- color: colorScheme.surfaceContainerHighest,
85- child: Icon (
86- Icons .broken_image_outlined,
87- color: colorScheme.onSurfaceVariant,
88- size: AppSpacing .xxl,
89- ),
90- ),
91- )
92- : Container (
93- width: double .infinity,
94- height: 180 ,
95- color: colorScheme.surfaceContainerHighest,
96- child: Icon (
97- Icons .image_not_supported_outlined,
98- color: colorScheme.onSurfaceVariant,
99- size: AppSpacing .xxl,
100- ),
59+ child: Image .network (
60+ headline.imageUrl,
61+ width: double .infinity,
62+ height: 180 , // Standard large image height
63+ fit: BoxFit .cover,
64+ loadingBuilder: (context, child, loadingProgress) {
65+ if (loadingProgress == null ) return child;
66+ return Container (
67+ width: double .infinity,
68+ height: 180 ,
69+ color: colorScheme.surfaceContainerHighest,
70+ child: const Center (
71+ child: CircularProgressIndicator (strokeWidth: 2 ),
10172 ),
73+ );
74+ },
75+ errorBuilder: (context, error, stackTrace) => Container (
76+ width: double .infinity,
77+ height: 180 ,
78+ color: colorScheme.surfaceContainerHighest,
79+ child: Icon (
80+ Icons .broken_image_outlined,
81+ color: colorScheme.onSurfaceVariant,
82+ size: AppSpacing .xxl,
83+ ),
84+ ),
85+ ),
10286 ),
10387 ),
10488 Padding (
@@ -131,7 +115,6 @@ class HeadlineTileImageTop extends StatelessWidget {
131115 const SizedBox (height: AppSpacing .sm),
132116 _HeadlineMetadataRow (
133117 headline: headline,
134- l10n: l10n,
135118 colorScheme: colorScheme,
136119 textTheme: textTheme,
137120 currentContextEntityType:
@@ -151,23 +134,22 @@ class HeadlineTileImageTop extends StatelessWidget {
151134class _HeadlineMetadataRow extends StatelessWidget {
152135 const _HeadlineMetadataRow ({
153136 required this .headline,
154- required this .l10n,
155137 required this .colorScheme,
156138 required this .textTheme,
157139 this .currentContextEntityType,
158140 this .currentContextEntityId,
159141 });
160142
161143 final Headline headline;
162- final AppLocalizations l10n;
163144 final ColorScheme colorScheme;
164145 final TextTheme textTheme;
165- final EntityType ? currentContextEntityType;
146+ final ContentType ? currentContextEntityType;
166147 final String ? currentContextEntityId;
167148
168149 @override
169150 Widget build (BuildContext context) {
170- final formattedDate = formatRelativeTime (context, headline.publishedAt);
151+ // TODO(anyone): Use a proper timeago library.
152+ final formattedDate = headline.createdAt.toString ();
171153
172154 // Use bodySmall for a reasonable base size, with muted accent color
173155 final metadataTextStyle = textTheme.bodySmall? .copyWith (
@@ -195,34 +177,35 @@ class _HeadlineMetadataRow extends StatelessWidget {
195177 Text (formattedDate, style: metadataTextStyle),
196178 ],
197179 ),
198- // Conditionally render Category as Text
199- if (headline.category ? .name != null &&
200- ! (currentContextEntityType == EntityType .category &&
201- headline.category ! .id == currentContextEntityId)) ...[
180+ // Conditionally render Topic as Text
181+ if (headline.topic .name.isNotEmpty &&
182+ ! (currentContextEntityType == ContentType .topic &&
183+ headline.topic .id == currentContextEntityId)) ...[
202184 if (formattedDate.isNotEmpty)
203185 Padding (
204186 padding: const EdgeInsets .symmetric (horizontal: AppSpacing .xs),
205187 child: Text ('•' , style: metadataTextStyle),
206188 ),
207189 GestureDetector (
208190 onTap: () {
209- if (headline.category != null ) {
210- context.push (
211- Routes .categoryDetails,
212- extra: EntityDetailsPageArguments (entity: headline.category),
213- );
214- }
191+ context.push (
192+ Routes .topicDetails,
193+ extra: EntityDetailsPageArguments (
194+ entity: headline.topic,
195+ contentType: ContentType .topic,
196+ ),
197+ );
215198 },
216- child: Text (headline.category ! .name, style: metadataTextStyle),
199+ child: Text (headline.topic .name, style: metadataTextStyle),
217200 ),
218201 ],
219202 // Conditionally render Source as Text
220- if (! (currentContextEntityType == EntityType .source &&
203+ if (! (currentContextEntityType == ContentType .source &&
221204 headline.source.id == currentContextEntityId)) ...[
222205 if (formattedDate.isNotEmpty ||
223- (headline.category ? .name != null &&
224- ! (currentContextEntityType == EntityType .category &&
225- headline.category ! .id == currentContextEntityId)))
206+ (headline.topic .name.isNotEmpty &&
207+ ! (currentContextEntityType == ContentType .topic &&
208+ headline.topic .id == currentContextEntityId)))
226209 Padding (
227210 padding: const EdgeInsets .symmetric (horizontal: AppSpacing .xs),
228211 child: Text ('•' , style: metadataTextStyle),
@@ -231,7 +214,10 @@ class _HeadlineMetadataRow extends StatelessWidget {
231214 onTap: () {
232215 context.push (
233216 Routes .sourceDetails,
234- extra: EntityDetailsPageArguments (entity: headline.source),
217+ extra: EntityDetailsPageArguments (
218+ entity: headline.source,
219+ contentType: ContentType .source,
220+ ),
235221 );
236222 },
237223 child: Text (headline.source.name, style: metadataTextStyle),
0 commit comments