diff --git a/lib/widgets/notification_item.dart b/lib/widgets/notification_item.dart index f152da36..bd6511a9 100644 --- a/lib/widgets/notification_item.dart +++ b/lib/widgets/notification_item.dart @@ -12,12 +12,14 @@ class NotificationItemWidget extends HookConsumerWidget { final NotificationItem item; final VoidCallback onDismiss; final bool isDesktop; + final Animation progress; const NotificationItemWidget({ super.key, required this.item, required this.onDismiss, required this.isDesktop, + required this.progress, }); @override @@ -52,54 +54,66 @@ class NotificationItemWidget extends HookConsumerWidget { shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(8)), ), - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: isDesktop ? 400 : double.infinity, - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - if (item.notification.meta['pfp'] != null) - ProfilePictureWidget( - fileId: item.notification.meta['pfp'], - radius: 12, - ).padding(right: 12, top: 2) - else - Icon( - Symbols.info, - color: Theme.of(context).colorScheme.primary, - size: 24, - ).padding(right: 12), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - item.notification.title, - style: Theme.of(context).textTheme.titleMedium - ?.copyWith(fontWeight: FontWeight.bold), - ), - if (item.notification.content.isNotEmpty) + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (item.notification.meta['pfp'] != null) + ProfilePictureWidget( + fileId: item.notification.meta['pfp'], + radius: 12, + ).padding(right: 12, top: 2) + else + Icon( + Symbols.info, + color: Theme.of(context).colorScheme.primary, + size: 24, + ).padding(right: 12), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ Text( - item.notification.content, - style: Theme.of(context).textTheme.bodyMedium, + item.notification.title, + style: Theme.of(context).textTheme.titleMedium + ?.copyWith(fontWeight: FontWeight.bold), ), - if (item.notification.subtitle.isNotEmpty) - Text( - item.notification.subtitle, - style: Theme.of(context).textTheme.bodySmall, - ), - ], + if (item.notification.content.isNotEmpty) + Text( + item.notification.content, + style: Theme.of(context).textTheme.bodyMedium, + ), + if (item.notification.subtitle.isNotEmpty) + Text( + item.notification.subtitle, + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ), ), - ), - ], + ], + ), ), - ), - ), + AnimatedBuilder( + animation: progress, + builder: (context, child) => LinearProgressIndicator( + value: progress.value, + minHeight: 2, + backgroundColor: Colors.transparent, + valueColor: AlwaysStoppedAnimation( + Theme.of(context).colorScheme.primary.withOpacity(0.5), + ), + ), + ), + ], + ).clipRRect(all: 8), ), ); } diff --git a/lib/widgets/notification_overlay.dart b/lib/widgets/notification_overlay.dart index 0bcad8e1..2ba471d1 100644 --- a/lib/widgets/notification_overlay.dart +++ b/lib/widgets/notification_overlay.dart @@ -76,6 +76,9 @@ class AnimatedNotificationItem extends HookConsumerWidget { duration: const Duration(milliseconds: 300), reverseDuration: const Duration(milliseconds: 250), ); + final progressController = useAnimationController( + duration: item.duration, + ); final isDismissed = useState(false); final slideTween = Tween( @@ -83,8 +86,14 @@ class AnimatedNotificationItem extends HookConsumerWidget { end: Offset.zero, ).chain(CurveTween(curve: Curves.easeOutCubic)); + final progressAnimation = Tween( + begin: 1.0, + end: 0.0, + ).animate(progressController); + useEffect(() { animationController.forward(); + progressController.forward(); return null; }, []); @@ -100,6 +109,8 @@ class AnimatedNotificationItem extends HookConsumerWidget { return () => timer.cancel(); }, [item.duration, isDismissed.value]); + final itemWidth = isDesktop ? 420.0 : MediaQuery.sizeOf(context).width - 40; + return SlideTransition( position: slideTween.animate(animationController), child: Padding( @@ -110,8 +121,9 @@ class AnimatedNotificationItem extends HookConsumerWidget { item: item, isDesktop: isDesktop, onDismiss: () {}, - ).width(isDesktop ? 420 : MediaQuery.sizeOf(context).width - 40), + progress: progressAnimation, + ).width(itemWidth), ), ); } -} +} \ No newline at end of file