import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:island/models/account.dart'; import 'package:island/route.dart'; import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/markdown.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:relative_time/relative_time.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:url_launcher/url_launcher_string.dart'; class NotificationTile extends StatelessWidget { final SnNotification notification; final double? avatarRadius; final EdgeInsets? contentPadding; final bool showImages; final bool compact; const NotificationTile({ super.key, required this.notification, this.avatarRadius, this.contentPadding, this.showImages = true, this.compact = false, }); IconData _getNotificationIcon(String topic) { switch (topic) { case 'post.replies': return Symbols.reply; case 'wallet.transactions': return Symbols.account_balance_wallet; case 'relationships.friends.request': return Symbols.person_add; case 'invites.chat': return Symbols.chat; case 'invites.realm': return Symbols.domain; case 'auth.login': return Symbols.login; case 'posts.new': return Symbols.post_add; case 'wallet.orders.paid': return Symbols.shopping_bag; case 'posts.reactions.new': return Symbols.add_reaction; default: return Symbols.notifications; } } @override Widget build(BuildContext context) { final pfp = notification.meta['pfp'] as String?; final images = notification.meta['images'] as List?; final imageIds = images?.cast() ?? []; return ListTile( isThreeLine: true, contentPadding: contentPadding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 8), leading: pfp != null ? ProfilePictureWidget( fileId: pfp, radius: avatarRadius ?? (compact ? 16 : 20), ) : CircleAvatar( backgroundColor: Theme.of(context).colorScheme.primaryContainer, radius: avatarRadius ?? (compact ? 16 : 20), child: Icon( _getNotificationIcon(notification.topic), color: Theme.of(context).colorScheme.onPrimaryContainer, size: compact ? 16 : 20, ), ), title: Text( notification.title, style: compact ? Theme.of(context).textTheme.bodySmall : Theme.of(context).textTheme.titleMedium, maxLines: compact ? 2 : null, overflow: compact ? TextOverflow.ellipsis : null, ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (notification.subtitle.isNotEmpty && !compact) Text(notification.subtitle).bold(), Row( spacing: 6, children: [ Text( DateFormat().format(notification.createdAt.toLocal()), style: Theme.of( context, ).textTheme.bodySmall?.copyWith(fontSize: compact ? 10 : 11), ), Text( 'ยท', style: Theme.of(context).textTheme.bodySmall?.copyWith( fontSize: compact ? 10 : 11, fontWeight: FontWeight.bold, ), ), Text( RelativeTime(context).format(notification.createdAt.toLocal()), style: Theme.of( context, ).textTheme.bodySmall?.copyWith(fontSize: compact ? 10 : 11), ), ], ).opacity(0.75).padding(bottom: compact ? 2 : 4), MarkdownTextContent( content: notification.content, textStyle: (compact ? Theme.of(context).textTheme.bodySmall : Theme.of(context).textTheme.bodyMedium) ?.copyWith( color: Theme.of( context, ).colorScheme.onSurface.withOpacity(0.8), fontSize: compact ? 11 : null, ), ), if (showImages && imageIds.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 8), child: Wrap( spacing: 8, runSpacing: 8, children: imageIds.map((imageId) { return SizedBox( width: 80, height: 80, child: ClipRRect( borderRadius: BorderRadius.circular(8), child: CloudImageWidget( fileId: imageId, aspectRatio: 1, fit: BoxFit.cover, ), ), ); }).toList(), ), ), ], ), trailing: notification.viewedAt != null ? null : Container( width: compact ? 8 : 12, height: compact ? 8 : 12, decoration: const BoxDecoration( color: Colors.blue, shape: BoxShape.circle, ), ), onTap: () { if (notification.meta['action_uri'] != null) { var uri = notification.meta['action_uri'] as String; if (uri.startsWith('/')) { // In-app routes rootNavigatorKey.currentContext?.push( notification.meta['action_uri'], ); } else { // External URLs launchUrlString(uri); } } }, ); } }