From 0b66b3806fe7209ab295490eaeb0edfb234d27fc Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Thu, 19 Dec 2024 22:08:51 -0500 Subject: [PATCH] Eliminate multiple click through events and put up snackbar if loading before navigating to new screen --- lib/controls/notifications_control.dart | 45 ++++++++++++++----- .../flattened_tree_entry_control.dart | 37 ++++++++++++--- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/lib/controls/notifications_control.dart b/lib/controls/notifications_control.dart index 38eb997..555765d 100644 --- a/lib/controls/notifications_control.dart +++ b/lib/controls/notifications_control.dart @@ -17,18 +17,31 @@ import '../utils/snackbar_builder.dart'; import 'html_text_viewer_control.dart'; import 'image_control.dart'; -class NotificationControl extends ConsumerWidget { - static final _logger = Logger('$NotificationControl'); - final UserNotification notification; - bool _processingTap = false; +final _logger = Logger('$NotificationControl'); - NotificationControl({ +class NotificationControl extends ConsumerStatefulWidget { + final UserNotification notification; + + const NotificationControl({ super.key, required this.notification, }); + @override + ConsumerState createState() => + _NotificationControlState(); +} + +class _NotificationControlState extends ConsumerState { + bool _processingTap = false; + + UserNotification get notification => widget.notification; + Future _goToStatus( - BuildContext context, WidgetRef ref, Profile profile) async { + BuildContext context, + WidgetRef ref, + Profile profile, + ) async { final existingPostData = ref.read(postTreeEntryByIdProvider(profile, notification.iid)); if (existingPostData.isSuccess) { @@ -36,6 +49,8 @@ class NotificationControl extends ConsumerWidget { .push('/post/view/${existingPostData.value.id}/${notification.iid}'); return; } + + buildSnackbar(context, 'Fetching status to load'); final loadedPost = await ref .read(timelineUpdaterProvider(profile).notifier) .refreshStatusChain(notification.iid); @@ -52,7 +67,7 @@ class NotificationControl extends ConsumerWidget { } @override - Widget build(BuildContext context, WidgetRef ref) { + Widget build(BuildContext context) { final profile = ref.watch(activeProfileProvider); const iconSize = 50.0; @@ -114,7 +129,7 @@ class NotificationControl extends ConsumerWidget { break; } - final onTap = onTapCallFunction == null + final onTap = _processingTap || onTapCallFunction == null ? null : () async { if (_processingTap) { @@ -165,11 +180,19 @@ class NotificationControl extends ConsumerWidget { } void _tapProcessingStarted() { - _processingTap = true; - Future.delayed(const Duration(seconds: 10), () => _processingTap = false); + setState(() { + _processingTap = true; + }); + Future.delayed(const Duration(seconds: 20), () { + if (mounted) { + _tapProcessingStop(); + } + }); } void _tapProcessingStop() { - _processingTap = false; + setState(() { + _processingTap = false; + }); } } diff --git a/lib/controls/timeline/flattened_tree_entry_control.dart b/lib/controls/timeline/flattened_tree_entry_control.dart index 12813e2..e9e5c16 100644 --- a/lib/controls/timeline/flattened_tree_entry_control.dart +++ b/lib/controls/timeline/flattened_tree_entry_control.dart @@ -58,6 +58,7 @@ class _StatusControlState extends ConsumerState { var showComments = false; var isProcessing = false; var filteringInfo = FilterResult.show; + var _processingTap = false; bool get isMine => widget.originalItem.isMine; @@ -137,11 +138,18 @@ class _StatusControlState extends ConsumerState { bottom: otherPadding, ), child: GestureDetector( - onTap: () { - if (widget.showStatusOpenButton) { - _goToPostView(entry); - } - }, + onTap: _processingTap + ? null + : () { + if (widget.showStatusOpenButton) { + if (_processingTap) { + return; + } + _tapProcessingStarted(); + _goToPostView(entry); + _tapProcessingStop(); + } + }, child: bodyCard), ); } @@ -151,8 +159,6 @@ class _StatusControlState extends ConsumerState { Profile profile, TimelineEntry entry, ) { - _logger.info( - 'Show content? $showContent Show spoiler? $showSpoilerControl Has Spoiler Text? ${entry.spoilerText.isNotEmpty}'); return Padding( padding: const EdgeInsets.all(5.0), child: Column( @@ -417,6 +423,23 @@ class _StatusControlState extends ConsumerState { void _goToPostView(TimelineEntry entry) { context.push('/post/view/${entry.id}/${entry.id}'); } + + void _tapProcessingStarted() { + setState(() { + _processingTap = true; + }); + Future.delayed(const Duration(seconds: 20), () { + if (mounted) { + _tapProcessingStop(); + } + }); + } + + void _tapProcessingStop() { + setState(() { + _processingTap = false; + }); + } } extension _TimelineExtensions on TimelineEntry {