Skip to content

Commit c34f2f5

Browse files
committed
feat(ui_kit): add HeadlineSourceRow widget
- Create a new widget to display the source and publish date of a headline - Implement tap functionality to navigate to source details - Use timeago package to format publication date - Apply theming and styling according to existing design guidelines
1 parent 5927158 commit c34f2f5

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import 'package:core/core.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_bloc/flutter_bloc.dart';
4+
import 'package:flutter_news_app_mobile_client_full_source_code/ads/interstitial_ad_manager.dart';
5+
import 'package:flutter_news_app_mobile_client_full_source_code/router/routes.dart';
6+
import 'package:go_router/go_router.dart';
7+
import 'package:timeago/timeago.dart' as timeago;
8+
import 'package:ui_kit/ui_kit.dart';
9+
10+
/// {@template headline_source_row}
11+
/// A widget to display the source and publish date of a headline.
12+
/// {@endtemplate}
13+
class HeadlineSourceRow extends StatelessWidget {
14+
/// {@macro headline_source_row}
15+
const HeadlineSourceRow({
16+
required this.headline,
17+
super.key,
18+
});
19+
20+
/// The headline data to display.
21+
final Headline headline;
22+
23+
Future<void> _handleEntityTap(BuildContext context) async {
24+
await context.read<InterstitialAdManager>().onPotentialAdTrigger();
25+
if (!context.mounted) return;
26+
await context.pushNamed(
27+
Routes.entityDetailsName,
28+
pathParameters: {
29+
'type': ContentType.source.name,
30+
'id': headline.source.id,
31+
},
32+
);
33+
}
34+
35+
@override
36+
Widget build(BuildContext context) {
37+
final theme = Theme.of(context);
38+
final textTheme = theme.textTheme;
39+
final colorScheme = theme.colorScheme;
40+
41+
final formattedDate = timeago.format(headline.createdAt);
42+
43+
final sourceTextStyle = textTheme.bodySmall?.copyWith(
44+
color: colorScheme.onSurfaceVariant,
45+
fontWeight: FontWeight.w500,
46+
);
47+
48+
final dateTextStyle = textTheme.bodySmall?.copyWith(
49+
color: colorScheme.onSurfaceVariant.withOpacity(0.7),
50+
);
51+
52+
return Row(
53+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
54+
children: [
55+
Expanded(
56+
child: InkWell(
57+
onTap: () => _handleEntityTap(context),
58+
child: Row(
59+
mainAxisSize: MainAxisSize.min,
60+
children: [
61+
Icon(
62+
Icons.source_outlined,
63+
size: AppSpacing.md,
64+
color: colorScheme.onSurfaceVariant,
65+
),
66+
const SizedBox(width: AppSpacing.xs),
67+
Flexible(
68+
child: Text(
69+
headline.source.name,
70+
style: sourceTextStyle,
71+
overflow: TextOverflow.ellipsis,
72+
),
73+
),
74+
],
75+
),
76+
),
77+
),
78+
if (formattedDate.isNotEmpty)
79+
Text(
80+
formattedDate,
81+
style: dateTextStyle,
82+
),
83+
],
84+
);
85+
}
86+
}

0 commit comments

Comments
 (0)