From 78f995a8e570d7a55cd3db59c1e2ccc40dd11992 Mon Sep 17 00:00:00 2001 From: poppingmoon <63451158+poppingmoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:02:06 +0900 Subject: [PATCH 1/2] feat: confirm before exit Play --- lib/i18n/aria/aria.i18n.yaml | 1 + lib/i18n/strings.g.dart | 2 +- lib/i18n/strings_en_US.g.dart | 1 + lib/view/widget/play_widget.dart | 222 +++++++++++++++++-------------- 4 files changed, 125 insertions(+), 101 deletions(-) diff --git a/lib/i18n/aria/aria.i18n.yaml b/lib/i18n/aria/aria.i18n.yaml index fa5b25b8c..dfa04a8df 100644 --- a/lib/i18n/aria/aria.i18n.yaml +++ b/lib/i18n/aria/aria.i18n.yaml @@ -47,6 +47,7 @@ enableFederation: "Enable federation" enablePredictiveBack: "Enable predictive back animations" enableSpellCheck: "Enable spell check" endpoint: "Endpoint" +exitPlayConfirm: "Are you sure you want to exit the Play?" expandNote: "Expand note" extraMentionsWarning: "This note includes mentions that are not included in the target note of reply" fileNotFound: "File not found" diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 3f79771ba..9d938cf91 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,7 +4,7 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 31 -/// Strings: 57344 (1849 per locale) +/// Strings: 57345 (1849 per locale) // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_en_US.g.dart b/lib/i18n/strings_en_US.g.dart index a175a403d..6f51ab3b9 100644 --- a/lib/i18n/strings_en_US.g.dart +++ b/lib/i18n/strings_en_US.g.dart @@ -101,6 +101,7 @@ class TranslationsAriaEnUs { String get enablePredictiveBack => 'Enable predictive back animations'; String get enableSpellCheck => 'Enable spell check'; String get endpoint => 'Endpoint'; + String get exitPlayConfirm => 'Are you sure you want to exit the Play?'; String get expandNote => 'Expand note'; String get extraMentionsWarning => 'This note includes mentions that are not included in the target note of reply'; String get fileNotFound => 'File not found'; diff --git a/lib/view/widget/play_widget.dart b/lib/view/widget/play_widget.dart index 28e62e1bb..62f578ae3 100644 --- a/lib/view/widget/play_widget.dart +++ b/lib/view/widget/play_widget.dart @@ -27,6 +27,7 @@ import '../../util/copy_text.dart'; import '../../util/future_with_dialog.dart'; import '../../util/launch_url.dart'; import '../../util/nyaize.dart'; +import '../dialog/confirmation_dialog.dart'; import '../dialog/error_message_dialog.dart'; import '../dialog/text_field_dialog.dart'; import 'account_preview.dart'; @@ -66,111 +67,130 @@ class PlayWidget extends HookConsumerWidget { duration: Durations.medium1, child: started.value - ? Column( - children: [ - Card( - margin: const EdgeInsets.symmetric(vertical: 8.0), - elevation: 0.0, - color: colors.panel, - child: Container( - width: double.infinity, - padding: const EdgeInsets.all(32.0), - child: AsUiWidget( - account: account, - host: host, - componentId: '___root___', - components: components.value, + ? PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, _) async { + if (!didPop) { + final shouldPop = await confirm( + context, + message: t.aria.exitPlayConfirm, + ); + if (!context.mounted) return; + if (shouldPop) { + try { + await aiscript.value?.abort(); + } catch (_) {} + if (!context.mounted) return; + context.pop(); + } + } + }, + child: Column( + children: [ + Card( + margin: const EdgeInsets.symmetric(vertical: 8.0), + elevation: 0.0, + color: colors.panel, + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(32.0), + child: AsUiWidget( + account: account, + host: host, + componentId: '___root___', + components: components.value, + ), ), ), - ), - Card( - margin: const EdgeInsets.symmetric(vertical: 8.0), - elevation: 0.0, - color: colors.panel, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - IconButton( - tooltip: t.misskey.reload, - onPressed: () async { - await aiscript.value?.abort(); - started.value = false; - }, - icon: const Icon(Icons.refresh), - ), - Row( - children: [ - LikeButton( - isLiked: play.isLiked, - likedCount: play.likedCount ?? 0, - onTap: - !account.isGuest && account.host == host - ? () => futureWithDialog( - context, - play.isLiked - ? ref - .read( - playNotifierProvider( - account, - play.id, - ).notifier, - ) - .unlike() - : ref - .read( - playNotifierProvider( - account, - play.id, - ).notifier, - ) - .like(), - ) - : null, - ), - const Spacer(), - if (!account.isGuest) + Card( + margin: const EdgeInsets.symmetric(vertical: 8.0), + elevation: 0.0, + color: colors.panel, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + IconButton( + tooltip: t.misskey.reload, + onPressed: () async { + await aiscript.value?.abort(); + started.value = false; + }, + icon: const Icon(Icons.refresh), + ), + Row( + children: [ + LikeButton( + isLiked: play.isLiked, + likedCount: play.likedCount ?? 0, + onTap: + !account.isGuest && account.host == host + ? () => futureWithDialog( + context, + play.isLiked + ? ref + .read( + playNotifierProvider( + account, + play.id, + ).notifier, + ) + .unlike() + : ref + .read( + playNotifierProvider( + account, + play.id, + ).notifier, + ) + .like(), + ) + : null, + ), + const Spacer(), + if (!account.isGuest) + IconButton( + tooltip: t.misskey.shareWithNote, + onPressed: () { + ref + .read( + postNotifierProvider( + account, + ).notifier, + ) + .setText('${play.title} $url'); + context.push('/$account/post'); + }, + icon: const Icon(Icons.repeat_rounded), + ), IconButton( - tooltip: t.misskey.shareWithNote, - onPressed: () { - ref - .read( - postNotifierProvider( - account, - ).notifier, - ) - .setText('${play.title} $url'); - context.push('/$account/post'); - }, - icon: const Icon(Icons.repeat_rounded), + tooltip: t.misskey.copyLink, + onPressed: + () => copyToClipboard( + context, + url.toString(), + ), + icon: const Icon(Icons.link), ), - IconButton( - tooltip: t.misskey.copyLink, - onPressed: - () => copyToClipboard( - context, - url.toString(), - ), - icon: const Icon(Icons.link), - ), - IconButton( - tooltip: t.aria.openInBrowser, - onPressed: () => launchUrl(ref, url), - icon: const Icon(Icons.open_in_browser), - ), - IconButton( - tooltip: t.misskey.share, - onPressed: - () => Share.share('${play.title} $url'), - icon: const Icon(Icons.share), - ), - ], - ), - ], + IconButton( + tooltip: t.aria.openInBrowser, + onPressed: () => launchUrl(ref, url), + icon: const Icon(Icons.open_in_browser), + ), + IconButton( + tooltip: t.misskey.share, + onPressed: + () => Share.share('${play.title} $url'), + icon: const Icon(Icons.share), + ), + ], + ), + ], + ), ), ), - ), - ], + ], + ), ) : Card( margin: const EdgeInsets.symmetric(vertical: 8.0), @@ -416,7 +436,9 @@ class PlayWidget extends HookConsumerWidget { started.value = true; await aiscript.value?.exec(input: play.script); } catch (e, st) { - await aiscript.value?.abort(); + try { + await aiscript.value?.abort(); + } catch (_) {} if (!context.mounted) return; await showErrorMessageDialog( context, From 31829c12e7b17efb728b7675d9bc251862b1b67e Mon Sep 17 00:00:00 2001 From: poppingmoon <63451158+poppingmoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 15:04:00 +0900 Subject: [PATCH 2/2] fix: do not show confirmation if did pop --- lib/view/page/drive_page.dart | 18 ++++++++++-------- lib/view/page/image_page.dart | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/view/page/drive_page.dart b/lib/view/page/drive_page.dart index 7fcb81b42..0f44d65ca 100644 --- a/lib/view/page/drive_page.dart +++ b/lib/view/page/drive_page.dart @@ -95,14 +95,16 @@ class DrivePage extends HookConsumerWidget { return PopScope( canPop: currentFolder == null && (selectFolder || selectedFiles.isEmpty), - onPopInvokedWithResult: (_, _) { - if (!selectFolder && selectedFiles.isNotEmpty) { - ref.read(selectedDriveFilesNotifierProvider.notifier).removeAll(); - } else if (currentFolder != null) { - hierarchyFolders.value = hierarchyFolders.value.sublist( - 0, - hierarchyFolders.value.length - 1, - ); + onPopInvokedWithResult: (didPop, _) { + if (!didPop) { + if (!selectFolder && selectedFiles.isNotEmpty) { + ref.read(selectedDriveFilesNotifierProvider.notifier).removeAll(); + } else if (currentFolder != null) { + hierarchyFolders.value = hierarchyFolders.value.sublist( + 0, + hierarchyFolders.value.length - 1, + ); + } } }, child: Scaffold( diff --git a/lib/view/page/image_page.dart b/lib/view/page/image_page.dart index c4f8496b1..fbc57bc29 100644 --- a/lib/view/page/image_page.dart +++ b/lib/view/page/image_page.dart @@ -79,14 +79,16 @@ class ImagePage extends HookConsumerWidget { return PopScope( canPop: image == backgroundLayer.value.data && overlayLayers.isEmpty, - onPopInvokedWithResult: (_, _) async { - final confirmed = await confirm( - context, - message: t.aria.discardChangesConfirm, - ); - if (!context.mounted) return; - if (confirmed) { - context.pop(); + onPopInvokedWithResult: (didPop, _) async { + if (!didPop) { + final confirmed = await confirm( + context, + message: t.aria.discardChangesConfirm, + ); + if (!context.mounted) return; + if (confirmed) { + context.pop(); + } } }, child: Scaffold(