From 99d94f3612bdcc3605e51de24e51faa2f0135cc1 Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Mon, 30 Jan 2023 01:04:50 -0500 Subject: [PATCH] Add menu dialog on link opening button for external, copy url, and on posts "go to post" --- .../timeline/interactions_bar_control.dart | 64 +++++++++++++------ lib/globals.dart | 23 +++++++ lib/utils/clipboard_utils.dart | 15 +++++ lib/utils/url_opening_utils.dart | 16 +++-- 4 files changed, 93 insertions(+), 25 deletions(-) create mode 100644 lib/utils/clipboard_utils.dart diff --git a/lib/controls/timeline/interactions_bar_control.dart b/lib/controls/timeline/interactions_bar_control.dart index 247a73e..6363c09 100644 --- a/lib/controls/timeline/interactions_bar_control.dart +++ b/lib/controls/timeline/interactions_bar_control.dart @@ -5,6 +5,7 @@ import 'package:logging/logging.dart'; import '../../globals.dart'; import '../../models/timeline_entry.dart'; import '../../services/timeline_manager.dart'; +import '../../utils/clipboard_utils.dart'; import '../../utils/snackbar_builder.dart'; import '../../utils/url_opening_utils.dart'; @@ -122,18 +123,42 @@ class _InteractionsBarControlState extends State { } Future openAction(BuildContext context) async { - if (widget.openRemote) { - final openInBrowser = - await showYesNoDialog(context, 'Open in external browser?'); - if (openInBrowser == true && mounted) { + const goToPost = 'Go to Post'; + const copyUrl = 'Copy URL'; + const openExternal = 'Open In Browser'; + final options = [ + if (widget.showOpenControl && !widget.openRemote) goToPost, + openExternal, + copyUrl, + 'Cancel' + ]; + final result = + await showChooseOptions(context, 'Would you like to', options); + + if (!mounted) { + return; + } + + switch (result) { + case goToPost: + context.push('/post/view/${widget.entry.id}/${widget.entry.id}'); + break; + case openExternal: await openUrlStringInSystembrowser( context, widget.entry.externalLink, 'Post', ); - } - } else { - context.push('/post/view/${widget.entry.id}/${widget.entry.id}'); + break; + case copyUrl: + await copyToClipboard( + context: context, + text: widget.entry.externalLink, + message: 'Post link copied to clipboard', + ); + break; + default: + //do nothing } } @@ -176,20 +201,19 @@ class _InteractionsBarControlState extends State { onPressed: isProcessing ? null : () async => await deleteEntry(), icon: Icon(Icons.delete)), - if (widget.showOpenControl) - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - IconButton( - onPressed: () async { - await openAction(context); - }, - icon: const Icon(Icons.launch), - ), - ], - ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + onPressed: () async { + await openAction(context); + }, + icon: const Icon(Icons.launch), + ), + ], ), + ), ]), ], ); diff --git a/lib/globals.dart b/lib/globals.dart index 170c1e7..8a4dc17 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -60,3 +60,26 @@ Future showYesNoDialog(BuildContext context, String caption) { }, ); } + +Future showChooseOptions( + BuildContext context, + String caption, + List options, +) { + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: Text(caption), + actions: options + .map((o) => ElevatedButton( + child: Text(o), + onPressed: () { + Navigator.pop(context, o); // showDialog() returns true + }, + )) + .toList()); + }, + ); +} diff --git a/lib/utils/clipboard_utils.dart b/lib/utils/clipboard_utils.dart new file mode 100644 index 0000000..479ba28 --- /dev/null +++ b/lib/utils/clipboard_utils.dart @@ -0,0 +1,15 @@ +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + +import 'snackbar_builder.dart'; + +Future copyToClipboard({ + required BuildContext context, + required String text, + String message = 'Copied to clipboard', +}) async { + await Clipboard.setData(ClipboardData(text: text)); + if (context.mounted) { + buildSnackbar(context, message); + } +} diff --git a/lib/utils/url_opening_utils.dart b/lib/utils/url_opening_utils.dart index f4f9fa2..2936db3 100644 --- a/lib/utils/url_opening_utils.dart +++ b/lib/utils/url_opening_utils.dart @@ -11,13 +11,19 @@ Future openUrlStringInSystembrowser( return false; } if (await canLaunchUrl(uri)) { - buildSnackbar( - context, - 'Attempting to launch $label: $url', - ); + if (context.mounted) { + buildSnackbar( + context, + 'Attempting to launch $label: $url', + ); + } + await launchUrl(uri); } else { - buildSnackbar(context, 'Unable to launch $label: $url'); + if (context.mounted) { + buildSnackbar(context, 'Unable to launch $label: $url'); + } + return false; } return true;