showNewsMarkerDetailsSheet function
- BuildContext context,
- NewsMarker newsMarker
Shows detailed information about a news marker in a bottom sheet.
Implementation
void showNewsMarkerDetailsSheet(BuildContext context, NewsMarker newsMarker) {
showModalBottomSheet(
context: context,
isScrollControlled: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (sheetContext) => Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header with news icon.
Row(
children: [
Icon(
Icons.article_outlined,
color: Colors.blue.shade700,
size: 28,
),
const SizedBox(width: 12),
Expanded(
child: Text(
'News Article',
style: Theme.of(
context,
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
),
),
],
),
const Divider(height: 24),
// News title.
Text(
newsMarker.title,
style: Theme.of(
context,
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),
),
const SizedBox(height: 12),
// Source and date.
if (newsMarker.source != null || newsMarker.publishedAt != null)
Row(
children: [
if (newsMarker.source != null) ...[
Icon(Icons.public, size: 16, color: Colors.grey.shade600),
const SizedBox(width: 4),
Text(
newsMarker.source!,
style: TextStyle(color: Colors.grey.shade600, fontSize: 14),
),
],
if (newsMarker.source != null && newsMarker.publishedAt != null)
Text(' • ', style: TextStyle(color: Colors.grey.shade600)),
if (newsMarker.publishedAt != null) ...[
Icon(
Icons.access_time,
size: 16,
color: Colors.grey.shade600,
),
const SizedBox(width: 4),
Text(
_formatDateTime(newsMarker.publishedAt!),
style: TextStyle(color: Colors.grey.shade600, fontSize: 14),
),
],
],
),
// Tone indicator.
if (newsMarker.tone != null) ...[
const SizedBox(height: 8),
Row(
children: [
Icon(
newsMarker.tone! > 0
? Icons.sentiment_satisfied
: newsMarker.tone! < 0
? Icons.sentiment_dissatisfied
: Icons.sentiment_neutral,
size: 16,
color: newsMarker.tone! > 0
? Colors.green
: newsMarker.tone! < 0
? Colors.red
: Colors.grey,
),
const SizedBox(width: 4),
Text(
'Tone: ${newsMarker.tone!.toStringAsFixed(1)}',
style: TextStyle(color: Colors.grey.shade600, fontSize: 14),
),
],
),
],
const SizedBox(height: 16),
// Location info.
Row(
children: [
Icon(Icons.location_on, size: 16, color: Colors.grey.shade600),
const SizedBox(width: 4),
Expanded(
child: Text(
'${newsMarker.location.latitude.toStringAsFixed(4)}, ${newsMarker.location.longitude.toStringAsFixed(4)}',
style: TextStyle(color: Colors.grey.shade600, fontSize: 12),
),
),
],
),
const SizedBox(height: 20),
// Action buttons.
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Navigator.of(sheetContext).pop(),
child: const Text('Close'),
),
if (newsMarker.url != null) ...[
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: () {
Navigator.of(sheetContext).pop();
_launchUrl(context, newsMarker.url!);
},
icon: const Icon(Icons.open_in_new, size: 18),
label: const Text('Read Article'),
),
],
],
),
const SizedBox(height: 20),
],
),
),
);
}