From beec48c8b41316d0b47458699f973a66e945dc06 Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Mon, 13 Nov 2023 17:55:47 +0330 Subject: [PATCH] Add subscription qr code share --- assets/translations/strings_en.i18n.json | 1 + assets/translations/strings_fa.i18n.json | 3 +- assets/translations/strings_ru.i18n.json | 3 +- assets/translations/strings_zh.i18n.json | 3 +- lib/features/common/profile_tile.dart | 16 ++++++- lib/features/common/qr_code_dialog.dart | 61 ++++++++++++++++++++++++ pubspec.lock | 16 +++++++ pubspec.yaml | 1 + 8 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 lib/features/common/qr_code_dialog.dart diff --git a/assets/translations/strings_en.i18n.json b/assets/translations/strings_en.i18n.json index b8f9a14f..403d6d36 100644 --- a/assets/translations/strings_en.i18n.json +++ b/assets/translations/strings_en.i18n.json @@ -77,6 +77,7 @@ "buttonText": "Share", "exportToClipboardSuccess": "Exported to clipboard", "exportSubLinkToClipboard": "Export subscription link to clipboard", + "subLinkQrCode": "Subscription link QR code", "exportConfigToClipboard": "Export configuration to clipboard", "exportConfigToClipboardSuccess": "Configuration copied to clipboard" }, diff --git a/assets/translations/strings_fa.i18n.json b/assets/translations/strings_fa.i18n.json index 1a612e0d..58236996 100644 --- a/assets/translations/strings_fa.i18n.json +++ b/assets/translations/strings_fa.i18n.json @@ -78,7 +78,8 @@ "exportToClipboardSuccess": "به کلیپ بورد اضافه شد", "exportSubLinkToClipboard": "افزودن لینک اشتراک به کلیپ بورد", "exportConfigToClipboard": "افزودن پیکربندی به کلیپ بورد", - "exportConfigToClipboardSuccess": "پیکربندی در کلیپ بورد کپی شد" + "exportConfigToClipboardSuccess": "پیکربندی در کلیپ بورد کپی شد", + "subLinkQrCode": "کد QR لینک اشتراک" }, "edit": { "buttonTxt": "ویرایش", diff --git a/assets/translations/strings_ru.i18n.json b/assets/translations/strings_ru.i18n.json index b022bd41..069ddabe 100644 --- a/assets/translations/strings_ru.i18n.json +++ b/assets/translations/strings_ru.i18n.json @@ -78,7 +78,8 @@ "exportToClipboardSuccess": "Скопировано в буфер обмена", "exportSubLinkToClipboard": "Скопировать ссылку на подписку в буфер обмена", "exportConfigToClipboard": "Скопировать конфигурацию в буфер обмена", - "exportConfigToClipboardSuccess": "Конфигурация скопирована в буфер обмена" + "exportConfigToClipboardSuccess": "Конфигурация скопирована в буфер обмена", + "subLinkQrCode": "QR-код ссылки на подписку" }, "edit": { "buttonTxt": "Изменить", diff --git a/assets/translations/strings_zh.i18n.json b/assets/translations/strings_zh.i18n.json index a468b31c..590142f6 100644 --- a/assets/translations/strings_zh.i18n.json +++ b/assets/translations/strings_zh.i18n.json @@ -78,7 +78,8 @@ "exportToClipboardSuccess": "导出到剪贴板", "exportSubLinkToClipboard": "将订阅链接导出到剪贴板", "exportConfigToClipboard": "将配置导出到剪贴板", - "exportConfigToClipboardSuccess": "配置已复制到剪贴板" + "exportConfigToClipboardSuccess": "配置已复制到剪贴板", + "subLinkQrCode": "订阅链接二维码" }, "edit": { "buttonTxt": "编辑", diff --git a/lib/features/common/profile_tile.dart b/lib/features/common/profile_tile.dart index a56374ed..c0c7781f 100644 --- a/lib/features/common/profile_tile.dart +++ b/lib/features/common/profile_tile.dart @@ -9,6 +9,7 @@ import 'package:hiddify/core/router/router.dart'; import 'package:hiddify/domain/failures.dart'; import 'package:hiddify/domain/profiles/profiles.dart'; import 'package:hiddify/features/common/confirmation_dialogs.dart'; +import 'package:hiddify/features/common/qr_code_dialog.dart'; import 'package:hiddify/features/profiles/notifier/notifier.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -289,7 +290,7 @@ class ProfileActionsMenu extends HookConsumerWidget { ), SubmenuButton( menuChildren: [ - if (profile case RemoteProfile(:final url, :final name)) + if (profile case RemoteProfile(:final url, :final name)) ...[ MenuItemButton( child: Text(t.profile.share.exportSubLinkToClipboard), onPressed: () async { @@ -303,6 +304,19 @@ class ProfileActionsMenu extends HookConsumerWidget { } }, ), + MenuItemButton( + child: Text(t.profile.share.subLinkQrCode), + onPressed: () async { + final link = LinkParser.generateSubShareLink(url, name); + if (link.isNotEmpty) { + await QrCodeDialog( + link, + message: name, + ).show(context); + } + }, + ), + ], MenuItemButton( child: Text(t.profile.share.exportConfigToClipboard), onPressed: () async { diff --git a/lib/features/common/qr_code_dialog.dart b/lib/features/common/qr_code_dialog.dart new file mode 100644 index 00000000..cc6da442 --- /dev/null +++ b/lib/features/common/qr_code_dialog.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:qr_flutter/qr_flutter.dart'; + +class QrCodeDialog extends StatelessWidget { + const QrCodeDialog( + this.data, { + super.key, + this.message, + this.width = 268, + this.backgroundColor = Colors.white, + }); + + final String data; + final String? message; + final double width; + final Color backgroundColor; + + Future show(BuildContext context) async { + await showDialog(context: context, builder: (context) => this); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: width, + child: QrImageView( + data: data, + backgroundColor: backgroundColor, + ), + ), + if (message != null) + SizedBox( + width: width, + child: Material( + color: theme.colorScheme.background, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + message!, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: theme.colorScheme.onBackground), + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 2df07782..c9b8b06a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1013,6 +1013,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + qr: + dependency: transitive + description: + name: qr + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" quiver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index aa4a95b7..0480cab6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,6 +70,7 @@ dependencies: version: ^3.0.2 posix: ^5.0.0 win32: ^5.0.9 + qr_flutter: ^4.1.0 dev_dependencies: flutter_test: