From 2576c905f100fef87fdc3206cdcd8c32bed1ab36 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Sat, 19 Jul 2025 19:46:21 +0530 Subject: [PATCH] Refactor common utils --- .../packages/utils/lib/directory_utils.dart | 32 + mobile/packages/utils/lib/email_util.dart | 244 +++++ mobile/packages/utils/lib/ente_utils.dart | 6 + mobile/packages/utils/lib/platform_util.dart | 70 ++ mobile/packages/utils/lib/share_utils.dart | 71 ++ mobile/packages/utils/pubspec.lock | 994 ++++++++++++++++++ mobile/packages/utils/pubspec.yaml | 42 + 7 files changed, 1459 insertions(+) create mode 100644 mobile/packages/utils/lib/directory_utils.dart create mode 100644 mobile/packages/utils/lib/email_util.dart create mode 100644 mobile/packages/utils/lib/ente_utils.dart create mode 100644 mobile/packages/utils/lib/platform_util.dart create mode 100644 mobile/packages/utils/lib/share_utils.dart create mode 100644 mobile/packages/utils/pubspec.lock create mode 100644 mobile/packages/utils/pubspec.yaml diff --git a/mobile/packages/utils/lib/directory_utils.dart b/mobile/packages/utils/lib/directory_utils.dart new file mode 100644 index 0000000000..7fdbc6de67 --- /dev/null +++ b/mobile/packages/utils/lib/directory_utils.dart @@ -0,0 +1,32 @@ +import 'dart:io'; + +import 'package:ente_logging/logging.dart'; +import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; + +class DirectoryUtils { + static final logger = Logger('DirectoryUtils'); + + static Future getDatabasePath(String databaseName) async { + String? directoryPath; + + directoryPath ??= (await getApplicationSupportDirectory()).path; + + return p.joinAll( + [ + directoryPath, + ".$databaseName", + ], + ); + } + + static Future getDirectoryForInit() async { + Directory directory = await getApplicationCacheDirectory(); + + return Directory(p.join(directory.path, "init")); + } + + static Future getTempsDir() async { + return await getTemporaryDirectory(); + } +} diff --git a/mobile/packages/utils/lib/email_util.dart b/mobile/packages/utils/lib/email_util.dart new file mode 100644 index 0000000000..1f98a20b72 --- /dev/null +++ b/mobile/packages/utils/lib/email_util.dart @@ -0,0 +1,244 @@ +import 'dart:io'; + +import 'package:archive/archive_io.dart'; +import 'package:email_validator/email_validator.dart'; +import 'package:ente_logging/logging.dart'; +import 'package:ente_strings/extensions.dart'; +import 'package:ente_ui/components/buttons/button_widget.dart'; +import 'package:ente_ui/components/buttons/models/button_type.dart'; +import 'package:ente_ui/components/dialog_widget.dart'; +import 'package:flutter_email_sender/flutter_email_sender.dart'; +import 'package:ente_configuration/base_configuration.dart'; +import 'package:ente_utils/directory_utils.dart'; +import 'package:ente_utils/platform_util.dart'; +import 'package:ente_utils/share_utils.dart'; +import "package:file_saver/file_saver.dart"; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import "package:intl/intl.dart"; +import 'package:logging/logging.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:url_launcher/url_launcher.dart'; + +final Logger _logger = Logger('email_util'); + +bool isValidEmail(String? email) { + if (email == null) { + return false; + } + return EmailValidator.validate(email); +} + +Future sendLogs( + BuildContext context, + String toEmail, + String? subject, + String? body, +) async { + final String zipFilePath = await getZippedLogsFile(); + final Email email = Email( + recipients: [toEmail], + subject: subject ?? '', + body: body ?? '', + attachmentPaths: [zipFilePath], + isHTML: false, + ); + try { + await FlutterEmailSender.send(email); + } catch (e, s) { + _logger.severe('email sender failed', e, s); + Navigator.of(context).pop(); + await shareLogs(context, toEmail, zipFilePath); + } +} + +Future shareLogs( + BuildContext context, + String toEmail, + String zipFilePath, +) async { + final result = await showDialogWidget( + context: context, + title: context.strings.emailYourLogs, + body: context.strings.pleaseSendTheLogsTo(toEmail), + buttons: [ + ButtonWidget( + buttonType: ButtonType.neutral, + labelText: context.strings.copyEmailAddress, + isInAlert: true, + buttonAction: ButtonAction.first, + onTap: () async { + await Clipboard.setData(ClipboardData(text: toEmail)); + }, + shouldShowSuccessConfirmation: true, + ), + ButtonWidget( + buttonType: ButtonType.neutral, + labelText: context.strings.exportLogs, + isInAlert: true, + buttonAction: ButtonAction.second, + ), + ButtonWidget( + buttonType: ButtonType.secondary, + labelText: context.strings.cancel, + isInAlert: true, + buttonAction: ButtonAction.cancel, + ), + ], + ); + if (result?.action != null && result!.action == ButtonAction.second) { + await exportLogs(context, zipFilePath); + } +} + +Future openSupportPage( + String? subject, + String? body, +) async { + const url = "https://github.com/ente-io/ente/discussions/new?category=q-a"; + if (subject != null && body != null) { + await launchUrl( + Uri.parse( + "$url&title=$subject&body=$body", + ), + ); + } else { + await launchUrl(Uri.parse(url)); + } +} + +Future getZippedLogsFile({ + String logsSubPath = "logs", +}) async { + final logsPath = (await getApplicationSupportDirectory()).path; + final logsDirectory = Directory("$logsPath/$logsSubPath"); + final tempPath = (await DirectoryUtils.getTempsDir()).path; + final zipFilePath = "$tempPath/logs.zip"; + final encoder = ZipFileEncoder(); + encoder.create(zipFilePath); + await encoder.addDirectory(logsDirectory); + await encoder.close(); + return zipFilePath; +} + +Future exportLogs( + BuildContext context, + String zipFilePath, [ + bool isSharing = false, +]) async { + if (!isSharing) { + final DateTime now = DateTime.now().toUtc(); + final String shortMonthName = DateFormat('MMM').format(now); // Short month + final String logFileName = + 'ente-logs-${now.year}-$shortMonthName-${now.day}-${now.hour}-${now.minute}'; + + final bytes = await File(zipFilePath).readAsBytes(); + await PlatformUtil.shareFile( + logFileName, + 'zip', + bytes, + MimeType.zip, + ); + } else { + await shareFiles( + [XFile(zipFilePath, mimeType: 'application/zip')], + context: context, + ); + } +} + +Future sendLogsViaEmail( + String toEmail, + String? subject, + String? body, +) async { + final String zipFilePath = await getZippedLogsFile(); + final Email email = Email( + recipients: [toEmail], + subject: subject ?? '', + body: body ?? '', + attachmentPaths: [zipFilePath], + isHTML: false, + ); + try { + await FlutterEmailSender.send(email); + } catch (e, s) { + _logger.severe('email sender failed', e, s); + rethrow; + } +} + +Future sendEmail( + BuildContext context, { + required String to, + String? subject, + String? body, + BaseConfiguration? configuration, +}) async { + try { + final String clientDebugInfo = await _clientInfo(configuration); + final String subject0 = subject ?? '[Support]'; + final String body0 = (body ?? '') + clientDebugInfo; + + if (Platform.isAndroid) { + // Special handling due to issue in proton mail android client + // https://github.com/ente-io/frame/pull/253 + final Uri params = Uri( + scheme: 'mailto', + path: to, + query: 'subject=$subject0&body=$body0', + ); + if (await canLaunchUrl(params)) { + await launchUrl(params); + } else { + // this will trigger _showNoMailAppsDialog + throw Exception('Could not launch ${params.toString()}'); + } + } else { + _showNoMailAppsDialog(context, to); + } + } catch (e) { + _logger.severe("Failed to send email to $to", e); + _showNoMailAppsDialog(context, to); + } +} + +Future _clientInfo(BaseConfiguration? configuration) async { + final packageInfo = await PackageInfo.fromPlatform(); + final String debugInfo = + '\n\n\n\n ------------------- \nFollowing information can ' + 'help us in debugging if you are facing any issue ' + '\nRegistered email: ${configuration?.getEmail() ?? 'N/A'}' + '\nClient: ${packageInfo.packageName}' + '\nVersion : ${packageInfo.version}'; + return debugInfo; +} + +void _showNoMailAppsDialog(BuildContext context, String toEmail) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + icon: const Icon(Icons.email_outlined), + title: Text('Email us at $toEmail'), + actions: [ + TextButton( + onPressed: () async { + await Clipboard.setData(ClipboardData(text: toEmail)); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Email address copied')), + ); + }, + child: const Text('Copy Email Address'), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('OK'), + ), + ], + ); + }, + ); +} diff --git a/mobile/packages/utils/lib/ente_utils.dart b/mobile/packages/utils/lib/ente_utils.dart new file mode 100644 index 0000000000..b431dc7ff9 --- /dev/null +++ b/mobile/packages/utils/lib/ente_utils.dart @@ -0,0 +1,6 @@ +library ente_utils; + +export 'directory_utils.dart'; +export 'email_util.dart'; +export 'platform_util.dart'; +export 'share_utils.dart'; diff --git a/mobile/packages/utils/lib/platform_util.dart b/mobile/packages/utils/lib/platform_util.dart new file mode 100644 index 0000000000..e84349c301 --- /dev/null +++ b/mobile/packages/utils/lib/platform_util.dart @@ -0,0 +1,70 @@ +import 'dart:io'; + +import 'package:file_saver/file_saver.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher_string.dart'; +import 'package:window_manager/window_manager.dart'; + +class PlatformUtil { + static bool isDesktop() { + return !kIsWeb && + (Platform.isWindows || Platform.isLinux || Platform.isMacOS); + } + + static bool isMobile() { + return !kIsWeb && (Platform.isAndroid || Platform.isIOS); + } + + static bool isWeb() { + return kIsWeb; + } + + static TextSelectionControls get selectionControls => Platform.isAndroid + ? materialTextSelectionControls + : Platform.isIOS + ? cupertinoTextSelectionControls + : desktopTextSelectionControls; + + static openWebView(BuildContext context, String title, String url) async { + // For desktop, always open in external browser + // For mobile, open in external browser (apps can override this if they have web view) + await launchUrlString(url); + } + + static Future shareFile( + String fileName, + String extension, + Uint8List bytes, + MimeType type, + ) async { + try { + if (Platform.isAndroid || Platform.isIOS) { + await FileSaver.instance.saveAs( + name: fileName, + ext: extension, + bytes: bytes, + mimeType: type, + ); + } else { + await FileSaver.instance.saveFile( + name: fileName, + ext: extension, + bytes: bytes, + mimeType: type, + ); + } + } catch (_) {} + } + + // Needed to fix issue with local_auth on Windows + // https://github.com/flutter/flutter/issues/122322 + static Future refocusWindows() async { + if (!Platform.isWindows) return; + await windowManager.blur(); + await windowManager.focus(); + await windowManager.setAlwaysOnTop(true); + await windowManager.setAlwaysOnTop(false); + } +} diff --git a/mobile/packages/utils/lib/share_utils.dart b/mobile/packages/utils/lib/share_utils.dart new file mode 100644 index 0000000000..c7cf0e8de5 --- /dev/null +++ b/mobile/packages/utils/lib/share_utils.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; +import 'package:share_plus/share_plus.dart'; + +Rect _sharePosOrigin(BuildContext? context, GlobalKey? key) { + late final Rect rect; + if (context != null) { + rect = shareButtonRect(context, key); + } else { + rect = const Offset(20.0, 20.0) & const Size(10, 10); + } + return rect; +} + +/// Returns the rect of button if context and key are not null +/// If key is null, returned rect will be at the center of the screen +Rect shareButtonRect(BuildContext context, GlobalKey? shareButtonKey) { + Size size = MediaQuery.sizeOf(context); + final RenderObject? renderObject = + shareButtonKey?.currentContext?.findRenderObject(); + RenderBox? renderBox; + if (renderObject != null && renderObject is RenderBox) { + renderBox = renderObject; + } + if (renderBox == null) { + return Rect.fromLTWH(0, 0, size.width, size.height / 2); + } + size = renderBox.size; + final Offset position = renderBox.localToGlobal(Offset.zero); + return Rect.fromCenter( + center: position + Offset(size.width / 2, size.height / 2), + width: size.width, + height: size.height, + ); +} + +Future shareText( + String text, { + BuildContext? context, + GlobalKey? key, +}) async { + try { + final sharePosOrigin = _sharePosOrigin(context, key); + return Share.share( + text, + sharePositionOrigin: sharePosOrigin, + ); + } catch (e, s) { + Logger("ShareUtil").severe("failed to share text", e, s); + return ShareResult.unavailable; + } +} + +Future shareFiles( + List files, { + BuildContext? context, + GlobalKey? key, + String? text, +}) async { + try { + final sharePosOrigin = _sharePosOrigin(context, key); + return Share.shareXFiles( + files, + text: text, + sharePositionOrigin: sharePosOrigin, + ); + } catch (e, s) { + Logger("ShareUtil").severe("failed to share files", e, s); + return ShareResult.unavailable; + } +} diff --git a/mobile/packages/utils/pubspec.lock b/mobile/packages/utils/pubspec.lock new file mode 100644 index 0000000000..9b33654cf8 --- /dev/null +++ b/mobile/packages/utils/pubspec.lock @@ -0,0 +1,994 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: "direct main" + description: + name: archive + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + url: "https://pub.dev" + source: hosted + version: "4.0.7" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + bip39: + dependency: transitive + description: + name: bip39 + sha256: de1ee27ebe7d96b84bb3a04a4132a0a3007dcdd5ad27dd14aa87a29d97c45edc + url: "https://pub.dev" + source: hosted + version: "1.0.6" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" + url: "https://pub.dev" + source: hosted + version: "9.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f + url: "https://pub.dev" + source: hosted + version: "7.0.3" + dio: + dependency: transitive + description: + name: dio + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + url: "https://pub.dev" + source: hosted + version: "5.8.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + email_validator: + dependency: "direct main" + description: + name: email_validator + sha256: b19aa5d92fdd76fbc65112060c94d45ba855105a28bb6e462de7ff03b12fa1fb + url: "https://pub.dev" + source: hosted + version: "3.0.0" + ente_base: + dependency: transitive + description: + path: "../base" + relative: true + source: path + version: "1.0.0" + ente_configuration: + dependency: "direct main" + description: + path: "../configuration" + relative: true + source: path + version: "1.0.0" + ente_crypto_dart: + dependency: transitive + description: + path: "." + ref: HEAD + resolved-ref: f91e1545f8263df127762240c4da54a0c42835b2 + url: "https://github.com/ente-io/ente_crypto_dart.git" + source: git + version: "1.0.0" + ente_events: + dependency: transitive + description: + path: "../events" + relative: true + source: path + version: "1.0.0" + ente_logging: + dependency: "direct main" + description: + path: "../logging" + relative: true + source: path + version: "1.0.0" + ente_strings: + dependency: "direct main" + description: + path: "../strings" + relative: true + source: path + version: "1.0.0" + ente_ui: + dependency: "direct main" + description: + path: "../ui" + relative: true + source: path + version: "1.0.0" + event_bus: + dependency: transitive + description: + name: event_bus + sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + file_saver: + dependency: "direct main" + description: + name: file_saver + sha256: "017a127de686af2d2fbbd64afea97052d95f2a0f87d19d25b87e097407bf9c1e" + url: "https://pub.dev" + source: hosted + version: "0.2.14" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_email_sender: + dependency: "direct main" + description: + name: flutter_email_sender + sha256: d39eb5e91358fc19ec4050da69accec21f9d5b2b6bcf188aa246327b6ca2352c + url: "https://pub.dev" + source: hosted + version: "7.0.0" + flutter_inappwebview: + dependency: transitive + description: + name: flutter_inappwebview + sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + flutter_inappwebview_android: + dependency: transitive + description: + name: flutter_inappwebview_android + sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba" + url: "https://pub.dev" + source: hosted + version: "1.1.3" + flutter_inappwebview_internal_annotations: + dependency: transitive + description: + name: flutter_inappwebview_internal_annotations + sha256: "787171d43f8af67864740b6f04166c13190aa74a1468a1f1f1e9ee5b90c359cd" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + flutter_inappwebview_ios: + dependency: transitive + description: + name: flutter_inappwebview_ios + sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_inappwebview_macos: + dependency: transitive + description: + name: flutter_inappwebview_macos + sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_inappwebview_platform_interface: + dependency: transitive + description: + name: flutter_inappwebview_platform_interface + sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500 + url: "https://pub.dev" + source: hosted + version: "1.3.0+1" + flutter_inappwebview_web: + dependency: transitive + description: + name: flutter_inappwebview_web + sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_inappwebview_windows: + dependency: transitive + description: + name: flutter_inappwebview_windows + sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_secure_storage: + dependency: transitive + description: + name: flutter_secure_storage + sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" + url: "https://pub.dev" + source: hosted + version: "9.2.4" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: transitive + description: + name: fluttertoast + sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1" + url: "https://pub.dev" + source: hosted + version: "8.2.12" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 + url: "https://pub.dev" + source: hosted + version: "2.4.4" + hex: + dependency: transitive + description: + name: hex + sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + url: "https://pub.dev" + source: hosted + version: "10.0.9" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + url: "https://pub.dev" + source: hosted + version: "3.0.9" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + url: "https://pub.dev" + source: hosted + version: "5.1.1" + logging: + dependency: "direct main" + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" + source: hosted + version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" + url: "https://pub.dev" + source: hosted + version: "8.3.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + path: + dependency: "direct main" + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + url: "https://pub.dev" + source: hosted + version: "2.2.17" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" + screen_retriever: + dependency: transitive + description: + name: screen_retriever + sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_linux: + dependency: transitive + description: + name: screen_retriever_linux + sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_macos: + dependency: transitive + description: + name: screen_retriever_macos + sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_platform_interface: + dependency: transitive + description: + name: screen_retriever_platform_interface + sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_windows: + dependency: transitive + description: + name: screen_retriever_windows + sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + sentry: + dependency: transitive + description: + name: sentry + sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb" + url: "https://pub.dev" + source: hosted + version: "8.14.2" + sentry_flutter: + dependency: transitive + description: + name: sentry_flutter + sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8" + url: "https://pub.dev" + source: hosted + version: "8.14.2" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da + url: "https://pub.dev" + source: hosted + version: "10.1.4" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b + url: "https://pub.dev" + source: hosted + version: "5.0.2" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + url: "https://pub.dev" + source: hosted + version: "2.4.10" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + sodium: + dependency: transitive + description: + name: sodium + sha256: d9830a388e37c82891888e64cfd4c6764fa3ac716bed80ac6eab89ee42c3cd76 + url: "https://pub.dev" + source: hosted + version: "2.3.1+1" + sodium_libs: + dependency: transitive + description: + name: sodium_libs + sha256: aa764acd6ccc6113e119c2d99471aeeb4637a9a501639549b297d3a143ff49b3 + url: "https://pub.dev" + source: hosted + version: "2.2.1+6" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" + source: hosted + version: "1.10.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + url: "https://pub.dev" + source: hosted + version: "3.4.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + url: "https://pub.dev" + source: hosted + version: "0.7.4" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" + url: "https://pub.dev" + source: hosted + version: "6.3.16" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + url: "https://pub.dev" + source: hosted + version: "6.3.3" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + url: "https://pub.dev" + source: hosted + version: "15.0.0" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + url: "https://pub.dev" + source: hosted + version: "5.14.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + window_manager: + dependency: "direct main" + description: + name: window_manager + sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" +sdks: + dart: ">=3.8.0 <4.0.0" + flutter: ">=3.29.0" diff --git a/mobile/packages/utils/pubspec.yaml b/mobile/packages/utils/pubspec.yaml new file mode 100644 index 0000000000..648b0f0ac6 --- /dev/null +++ b/mobile/packages/utils/pubspec.yaml @@ -0,0 +1,42 @@ +name: ente_utils +description: A Flutter package containing shared utility functions for Ente apps +version: 1.0.0 +publish_to: none + +environment: + sdk: ">=3.0.0 <4.0.0" + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + # Core dependencies + archive: ^4.0.7 + email_validator: ^3.0.0 + file_saver: ^0.2.14 + flutter_email_sender: ^7.0.0 + ente_logging: + path: ../../packages/logging + ente_strings: + path: ../../packages/strings + ente_ui: + path: ../../packages/ui + intl: ^0.20.1 + logging: ^1.3.0 + package_info_plus: ^8.1.1 + path: ^1.9.1 + path_provider: ^2.1.5 + share_plus: ^10.1.2 + url_launcher: ^6.3.1 + window_manager: ^0.5.0 + + # Ente packages + ente_configuration: + path: ../../packages/configuration + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +flutter: