From e1a6bcff1d383fe9deb4fa8ad2ea1e46427683d3 Mon Sep 17 00:00:00 2001 From: KISHORE KUMAR S <77736919+KISHORE-KUMAR-S@users.noreply.github.com> Date: Wed, 9 Oct 2024 01:38:00 +0530 Subject: [PATCH] Select Multiple APK at once (Issue: #1439) (#1875) --- app/lib/gen/strings_en.g.dart | 1381 +++++++++-------- app/lib/pages/apk_picker_page.dart | 128 +- app/lib/pages/home_page.dart | 32 +- app/lib/pages/tabs/send_tab.dart | 135 +- app/lib/provider/apk_provider.dart | 13 +- .../provider/param/apk_provider_param.dart | 4 +- .../param/apk_provider_param.mapper.dart | 80 +- .../param/cached_apk_provider_param.dart | 4 +- app/pubspec.lock | 80 +- cli/pubspec.lock | 115 +- 10 files changed, 1149 insertions(+), 823 deletions(-) diff --git a/app/lib/gen/strings_en.g.dart b/app/lib/gen/strings_en.g.dart index 46f657ff..65975f1c 100644 --- a/app/lib/gen/strings_en.g.dart +++ b/app/lib/gen/strings_en.g.dart @@ -8,1037 +8,1130 @@ part of 'strings.g.dart'; // Path: class Translations implements BaseTranslations { - /// Returns the current translations of the given [context]. - /// - /// Usage: - /// final t = Translations.of(context); - static Translations of(BuildContext context) => InheritedLocaleData.of(context).translations; + /// Returns the current translations of the given [context]. + /// + /// Usage: + /// final t = Translations.of(context); + static Translations of(BuildContext context) => + InheritedLocaleData.of(context).translations; - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - Translations.build({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = TranslationMetadata( - locale: AppLocale.en, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); + /// You can call this constructor and build your own translation instance of this locale. + /// Constructing via the enum [AppLocale.build] is preferred. + Translations.build( + {Map? overrides, + PluralResolver? cardinalResolver, + PluralResolver? ordinalResolver}) + : assert(overrides == null, + 'Set "translation_overrides: true" in order to enable this feature.'), + $meta = TranslationMetadata( + locale: AppLocale.en, + overrides: overrides ?? {}, + cardinalResolver: cardinalResolver, + ordinalResolver: ordinalResolver, + ); - /// Metadata for the translations of . - @override final TranslationMetadata $meta; + /// Metadata for the translations of . + @override + final TranslationMetadata $meta; - late final Translations _root = this; // ignore: unused_field + late final Translations _root = this; // ignore: unused_field - // Translations - String get locale => 'English'; - String get appName => 'LocalSend'; - late final _StringsGeneralEn general = _StringsGeneralEn._(_root); - late final _StringsReceiveTabEn receiveTab = _StringsReceiveTabEn._(_root); - late final _StringsSendTabEn sendTab = _StringsSendTabEn._(_root); - late final _StringsSettingsTabEn settingsTab = _StringsSettingsTabEn._(_root); - late final _StringsTroubleshootPageEn troubleshootPage = _StringsTroubleshootPageEn._(_root); - late final _StringsReceiveHistoryPageEn receiveHistoryPage = _StringsReceiveHistoryPageEn._(_root); - late final _StringsApkPickerPageEn apkPickerPage = _StringsApkPickerPageEn._(_root); - late final _StringsSelectedFilesPageEn selectedFilesPage = _StringsSelectedFilesPageEn._(_root); - late final _StringsReceivePageEn receivePage = _StringsReceivePageEn._(_root); - late final _StringsReceiveOptionsPageEn receiveOptionsPage = _StringsReceiveOptionsPageEn._(_root); - late final _StringsSendPageEn sendPage = _StringsSendPageEn._(_root); - late final _StringsProgressPageEn progressPage = _StringsProgressPageEn._(_root); - late final _StringsWebSharePageEn webSharePage = _StringsWebSharePageEn._(_root); - late final _StringsAboutPageEn aboutPage = _StringsAboutPageEn._(_root); - late final _StringsDonationPageEn donationPage = _StringsDonationPageEn._(_root); - late final _StringsChangelogPageEn changelogPage = _StringsChangelogPageEn._(_root); - late final _StringsAliasGeneratorEn aliasGenerator = _StringsAliasGeneratorEn._(_root); - late final _StringsDialogsEn dialogs = _StringsDialogsEn._(_root); - late final _StringsSanitizationEn sanitization = _StringsSanitizationEn._(_root); - late final _StringsTrayEn tray = _StringsTrayEn._(_root); - late final _StringsWebEn web = _StringsWebEn._(_root); - late final _StringsAssetPickerEn assetPicker = _StringsAssetPickerEn._(_root); + // Translations + String get locale => 'English'; + String get appName => 'LocalSend'; + late final _StringsGeneralEn general = _StringsGeneralEn._(_root); + late final _StringsReceiveTabEn receiveTab = _StringsReceiveTabEn._(_root); + late final _StringsSendTabEn sendTab = _StringsSendTabEn._(_root); + late final _StringsSettingsTabEn settingsTab = _StringsSettingsTabEn._(_root); + late final _StringsTroubleshootPageEn troubleshootPage = + _StringsTroubleshootPageEn._(_root); + late final _StringsReceiveHistoryPageEn receiveHistoryPage = + _StringsReceiveHistoryPageEn._(_root); + late final _StringsApkPickerPageEn apkPickerPage = + _StringsApkPickerPageEn._(_root); + late final _StringsSelectedFilesPageEn selectedFilesPage = + _StringsSelectedFilesPageEn._(_root); + late final _StringsReceivePageEn receivePage = _StringsReceivePageEn._(_root); + late final _StringsReceiveOptionsPageEn receiveOptionsPage = + _StringsReceiveOptionsPageEn._(_root); + late final _StringsSendPageEn sendPage = _StringsSendPageEn._(_root); + late final _StringsProgressPageEn progressPage = + _StringsProgressPageEn._(_root); + late final _StringsWebSharePageEn webSharePage = + _StringsWebSharePageEn._(_root); + late final _StringsAboutPageEn aboutPage = _StringsAboutPageEn._(_root); + late final _StringsDonationPageEn donationPage = + _StringsDonationPageEn._(_root); + late final _StringsChangelogPageEn changelogPage = + _StringsChangelogPageEn._(_root); + late final _StringsAliasGeneratorEn aliasGenerator = + _StringsAliasGeneratorEn._(_root); + late final _StringsDialogsEn dialogs = _StringsDialogsEn._(_root); + late final _StringsSanitizationEn sanitization = + _StringsSanitizationEn._(_root); + late final _StringsTrayEn tray = _StringsTrayEn._(_root); + late final _StringsWebEn web = _StringsWebEn._(_root); + late final _StringsAssetPickerEn assetPicker = _StringsAssetPickerEn._(_root); } // Path: general class _StringsGeneralEn { - _StringsGeneralEn._(this._root); + _StringsGeneralEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get accept => 'Accept'; - String get accepted => 'Accepted'; - String get add => 'Add'; - String get advanced => 'Advanced'; - String get cancel => 'Cancel'; - String get close => 'Close'; - String get confirm => 'Confirm'; - String get continueStr => 'Continue'; - String get copy => 'Copy'; - String get copiedToClipboard => 'Copied to Clipboard'; - String get decline => 'Decline'; - String get done => 'Done'; - String get delete => 'Delete'; - String get edit => 'Edit'; - String get error => 'Error'; - String get example => 'Example'; - String get files => 'Files'; - String get finished => 'Finished'; - String get hide => 'Hide'; - String get off => 'Off'; - String get offline => 'Offline'; - String get on => 'On'; - String get online => 'Online'; - String get open => 'Open'; - String get queue => 'Queue'; - String get quickSave => 'Quick Save'; - String get quickSaveFromFavorites => 'Quick Save for "Favorites"'; - String get renamed => 'Renamed'; - String get reset => 'Undo changes'; - String get restart => 'Restart'; - String get settings => 'Settings'; - String get skipped => 'Skipped'; - String get start => 'Start'; - String get stop => 'Stop'; - String get save => 'Save'; - String get unchanged => 'Unchanged'; - String get unknown => 'Unknown'; - String get noItemInClipboard => 'No items in Clipboard.'; + // Translations + String get accept => 'Accept'; + String get accepted => 'Accepted'; + String get add => 'Add'; + String get advanced => 'Advanced'; + String get cancel => 'Cancel'; + String get close => 'Close'; + String get confirm => 'Confirm'; + String get continueStr => 'Continue'; + String get copy => 'Copy'; + String get copiedToClipboard => 'Copied to Clipboard'; + String get decline => 'Decline'; + String get done => 'Done'; + String get delete => 'Delete'; + String get edit => 'Edit'; + String get error => 'Error'; + String get example => 'Example'; + String get files => 'Files'; + String get finished => 'Finished'; + String get hide => 'Hide'; + String get off => 'Off'; + String get offline => 'Offline'; + String get on => 'On'; + String get online => 'Online'; + String get open => 'Open'; + String get queue => 'Queue'; + String get quickSave => 'Quick Save'; + String get quickSaveFromFavorites => 'Quick Save for "Favorites"'; + String get renamed => 'Renamed'; + String get reset => 'Undo changes'; + String get restart => 'Restart'; + String get settings => 'Settings'; + String get skipped => 'Skipped'; + String get start => 'Start'; + String get stop => 'Stop'; + String get save => 'Save'; + String get unchanged => 'Unchanged'; + String get unknown => 'Unknown'; + String get noItemInClipboard => 'No items in Clipboard.'; } // Path: receiveTab class _StringsReceiveTabEn { - _StringsReceiveTabEn._(this._root); + _StringsReceiveTabEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Receive'; - late final _StringsReceiveTabInfoBoxEn infoBox = _StringsReceiveTabInfoBoxEn._(_root); + // Translations + String get title => 'Receive'; + late final _StringsReceiveTabInfoBoxEn infoBox = + _StringsReceiveTabInfoBoxEn._(_root); } // Path: sendTab class _StringsSendTabEn { - _StringsSendTabEn._(this._root); + _StringsSendTabEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Send'; - late final _StringsSendTabSelectionEn selection = _StringsSendTabSelectionEn._(_root); - late final _StringsSendTabPickerEn picker = _StringsSendTabPickerEn._(_root); - String get shareIntentInfo => 'You can also use the "Share" feature of your mobile device to select files more easily.'; - String get nearbyDevices => 'Nearby devices'; - String get thisDevice => 'This Device'; - String get scan => 'Search devices'; - String get manualSending => 'Manual sending'; - String get sendMode => 'Send mode'; - late final _StringsSendTabSendModesEn sendModes = _StringsSendTabSendModesEn._(_root); - String get sendModeHelp => 'Explanation'; - String get help => 'Please ensure that the desired target is also on the same Wi-Fi network.'; - String get placeItems => 'Place items to share.'; + // Translations + String get title => 'Send'; + late final _StringsSendTabSelectionEn selection = + _StringsSendTabSelectionEn._(_root); + late final _StringsSendTabPickerEn picker = _StringsSendTabPickerEn._(_root); + String get shareIntentInfo => + 'You can also use the "Share" feature of your mobile device to select files more easily.'; + String get nearbyDevices => 'Nearby devices'; + String get thisDevice => 'This Device'; + String get scan => 'Search devices'; + String get manualSending => 'Manual sending'; + String get sendMode => 'Send mode'; + late final _StringsSendTabSendModesEn sendModes = + _StringsSendTabSendModesEn._(_root); + String get sendModeHelp => 'Explanation'; + String get help => + 'Please ensure that the desired target is also on the same Wi-Fi network.'; + String get placeItems => 'Place items to share.'; } // Path: settingsTab class _StringsSettingsTabEn { - _StringsSettingsTabEn._(this._root); + _StringsSettingsTabEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Settings'; - late final _StringsSettingsTabGeneralEn general = _StringsSettingsTabGeneralEn._(_root); - late final _StringsSettingsTabReceiveEn receive = _StringsSettingsTabReceiveEn._(_root); - late final _StringsSettingsTabSendEn send = _StringsSettingsTabSendEn._(_root); - late final _StringsSettingsTabNetworkEn network = _StringsSettingsTabNetworkEn._(_root); - late final _StringsSettingsTabOtherEn other = _StringsSettingsTabOtherEn._(_root); - String get advancedSettings => 'Advanced settings'; + // Translations + String get title => 'Settings'; + late final _StringsSettingsTabGeneralEn general = + _StringsSettingsTabGeneralEn._(_root); + late final _StringsSettingsTabReceiveEn receive = + _StringsSettingsTabReceiveEn._(_root); + late final _StringsSettingsTabSendEn send = + _StringsSettingsTabSendEn._(_root); + late final _StringsSettingsTabNetworkEn network = + _StringsSettingsTabNetworkEn._(_root); + late final _StringsSettingsTabOtherEn other = + _StringsSettingsTabOtherEn._(_root); + String get advancedSettings => 'Advanced settings'; } // Path: troubleshootPage class _StringsTroubleshootPageEn { - _StringsTroubleshootPageEn._(this._root); + _StringsTroubleshootPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Troubleshoot'; - String get subTitle => 'Does the app not work as expected? Here you can find some common solutions to problems.'; - String get solution => 'Solution:'; - String get fixButton => 'Fix automatically'; - late final _StringsTroubleshootPageFirewallEn firewall = _StringsTroubleshootPageFirewallEn._(_root); - late final _StringsTroubleshootPageNoDiscoveryEn noDiscovery = _StringsTroubleshootPageNoDiscoveryEn._(_root); - late final _StringsTroubleshootPageNoConnectionEn noConnection = _StringsTroubleshootPageNoConnectionEn._(_root); + // Translations + String get title => 'Troubleshoot'; + String get subTitle => + 'Does the app not work as expected? Here you can find some common solutions to problems.'; + String get solution => 'Solution:'; + String get fixButton => 'Fix automatically'; + late final _StringsTroubleshootPageFirewallEn firewall = + _StringsTroubleshootPageFirewallEn._(_root); + late final _StringsTroubleshootPageNoDiscoveryEn noDiscovery = + _StringsTroubleshootPageNoDiscoveryEn._(_root); + late final _StringsTroubleshootPageNoConnectionEn noConnection = + _StringsTroubleshootPageNoConnectionEn._(_root); } // Path: receiveHistoryPage class _StringsReceiveHistoryPageEn { - _StringsReceiveHistoryPageEn._(this._root); + _StringsReceiveHistoryPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'History'; - String get openFolder => 'Open folder'; - String get deleteHistory => 'Delete history'; - String get empty => 'The history is empty.'; - late final _StringsReceiveHistoryPageEntryActionsEn entryActions = _StringsReceiveHistoryPageEntryActionsEn._(_root); + // Translations + String get title => 'History'; + String get openFolder => 'Open folder'; + String get deleteHistory => 'Delete history'; + String get empty => 'The history is empty.'; + late final _StringsReceiveHistoryPageEntryActionsEn entryActions = + _StringsReceiveHistoryPageEntryActionsEn._(_root); } // Path: apkPickerPage class _StringsApkPickerPageEn { - _StringsApkPickerPageEn._(this._root); + _StringsApkPickerPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Apps (APK)'; - String get excludeSystemApps => 'Exclude system apps'; - String get excludeAppsWithoutLaunchIntent => 'Exclude non-launchable apps'; - String apps({required Object n}) => '${n} Apps'; + // Translations + String get title => 'Apps (APK)'; + String get excludeSystemApps => 'Exclude system apps'; + String get excludeAppsWithoutLaunchIntent => 'Exclude non-launchable apps'; + String apps({required Object n}) => '${n} Apps'; } // Path: selectedFilesPage class _StringsSelectedFilesPageEn { - _StringsSelectedFilesPageEn._(this._root); + _StringsSelectedFilesPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get deleteAll => 'Delete all'; + // Translations + String get deleteAll => 'Delete all'; } // Path: receivePage class _StringsReceivePageEn { - _StringsReceivePageEn._(this._root); + _StringsReceivePageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String subTitle({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - one: 'wants to send you a file', - other: 'wants to send you ${n} files', - ); - String get subTitleMessage => 'sent you a message:'; - String get subTitleLink => 'sent you a link:'; - String get canceled => 'The sender has canceled the request.'; + // Translations + String subTitle({required num n}) => + (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))( + n, + one: 'wants to send you a file', + other: 'wants to send you ${n} files', + ); + String get subTitleMessage => 'sent you a message:'; + String get subTitleLink => 'sent you a link:'; + String get canceled => 'The sender has canceled the request.'; } // Path: receiveOptionsPage class _StringsReceiveOptionsPageEn { - _StringsReceiveOptionsPageEn._(this._root); + _StringsReceiveOptionsPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Options'; - String get destination => _root.settingsTab.receive.destination; - String get appDirectory => '(LocalSend folder)'; - String get saveToGallery => _root.settingsTab.receive.saveToGallery; - String get saveToGalleryOff => 'Turned off automatically because there are folders.'; + // Translations + String get title => 'Options'; + String get destination => _root.settingsTab.receive.destination; + String get appDirectory => '(LocalSend folder)'; + String get saveToGallery => _root.settingsTab.receive.saveToGallery; + String get saveToGalleryOff => + 'Turned off automatically because there are folders.'; } // Path: sendPage class _StringsSendPageEn { - _StringsSendPageEn._(this._root); + _StringsSendPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get waiting => 'Waiting for response...'; - String get rejected => 'The recipient has rejected the request.'; - String get tooManyAttempts => _root.web.tooManyAttempts; - String get busy => 'The recipient is busy with another request.'; + // Translations + String get waiting => 'Waiting for response...'; + String get rejected => 'The recipient has rejected the request.'; + String get tooManyAttempts => _root.web.tooManyAttempts; + String get busy => 'The recipient is busy with another request.'; } // Path: progressPage class _StringsProgressPageEn { - _StringsProgressPageEn._(this._root); + _StringsProgressPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get titleSending => 'Sending files'; - String get titleReceiving => 'Receiving files'; - String get savedToGallery => 'Saved in Photos'; - late final _StringsProgressPageTotalEn total = _StringsProgressPageTotalEn._(_root); + // Translations + String get titleSending => 'Sending files'; + String get titleReceiving => 'Receiving files'; + String get savedToGallery => 'Saved in Photos'; + late final _StringsProgressPageTotalEn total = + _StringsProgressPageTotalEn._(_root); } // Path: webSharePage class _StringsWebSharePageEn { - _StringsWebSharePageEn._(this._root); + _StringsWebSharePageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Share via link'; - String get loading => 'Starting server...'; - String get stopping => 'Stopping server...'; - String get error => 'An error occurred while starting the server.'; - String openLink({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, - one: 'Open this link in your browser:', - other: 'Open one of these links in your browser:', - ); - String get requests => 'Requests'; - String get noRequests => 'No requests yet.'; - String get encryption => _root.settingsTab.network.encryption; - String get autoAccept => 'Automatically accept requests'; - String get requirePin => 'Require PIN'; - String pinHint({required Object pin}) => 'The PIN is "${pin}"'; - String get encryptionHint => 'LocalSend uses a self-signed certificate. You need to accept it in your browser.'; - String pendingRequests({required Object n}) => 'Pending requests: ${n}'; + // Translations + String get title => 'Share via link'; + String get loading => 'Starting server...'; + String get stopping => 'Stopping server...'; + String get error => 'An error occurred while starting the server.'; + String openLink({required num n}) => + (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))( + n, + one: 'Open this link in your browser:', + other: 'Open one of these links in your browser:', + ); + String get requests => 'Requests'; + String get noRequests => 'No requests yet.'; + String get encryption => _root.settingsTab.network.encryption; + String get autoAccept => 'Automatically accept requests'; + String get requirePin => 'Require PIN'; + String pinHint({required Object pin}) => 'The PIN is "${pin}"'; + String get encryptionHint => + 'LocalSend uses a self-signed certificate. You need to accept it in your browser.'; + String pendingRequests({required Object n}) => 'Pending requests: ${n}'; } // Path: aboutPage class _StringsAboutPageEn { - _StringsAboutPageEn._(this._root); + _StringsAboutPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'About LocalSend'; - List get description => [ - 'LocalSend is a free, open-source app that allows you to securely share files and messages with nearby devices over your local network without needing an internet connection.', - 'This app is available on Android, iOS, macOS, Windows and Linux. You can find all download options on the official homepage.', - ]; - String get author => 'Author'; - String get contributors => 'Contributors'; - String get packagers => 'Packagers'; - String get translators => 'Translators'; + // Translations + String get title => 'About LocalSend'; + List get description => [ + 'LocalSend is a free, open-source app that allows you to securely share files and messages with nearby devices over your local network without needing an internet connection.', + 'This app is available on Android, iOS, macOS, Windows and Linux. You can find all download options on the official homepage.', + ]; + String get author => 'Author'; + String get contributors => 'Contributors'; + String get packagers => 'Packagers'; + String get translators => 'Translators'; } // Path: donationPage class _StringsDonationPageEn { - _StringsDonationPageEn._(this._root); + _StringsDonationPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Donate'; - String get info => 'LocalSend is free, open-source and without any ads. If you like the app, you can support the development with a donation.'; - String donate({required Object amount}) => 'Donate ${amount}'; - String get thanks => 'Thank you very much!'; - String get restore => 'Restore purchase'; + // Translations + String get title => 'Donate'; + String get info => + 'LocalSend is free, open-source and without any ads. If you like the app, you can support the development with a donation.'; + String donate({required Object amount}) => 'Donate ${amount}'; + String get thanks => 'Thank you very much!'; + String get restore => 'Restore purchase'; } // Path: changelogPage class _StringsChangelogPageEn { - _StringsChangelogPageEn._(this._root); + _StringsChangelogPageEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Changelog'; + // Translations + String get title => 'Changelog'; } // Path: aliasGenerator class _StringsAliasGeneratorEn { - _StringsAliasGeneratorEn._(this._root); + _StringsAliasGeneratorEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - List get adjectives => [ - 'Adorable', - 'Beautiful', - 'Big', - 'Bright', - 'Clean', - 'Clever', - 'Cool', - 'Cute', - 'Cunning', - 'Determined', - 'Energetic', - 'Efficient', - 'Fantastic', - 'Fast', - 'Fine', - 'Fresh', - 'Good', - 'Gorgeous', - 'Great', - 'Handsome', - 'Hot', - 'Kind', - 'Lovely', - 'Mystic', - 'Neat', - 'Nice', - 'Patient', - 'Pretty', - 'Powerful', - 'Rich', - 'Secret', - 'Smart', - 'Solid', - 'Special', - 'Strategic', - 'Strong', - 'Tidy', - 'Wise', - ]; - List get fruits => [ - 'Apple', - 'Avocado', - 'Banana', - 'Blackberry', - 'Blueberry', - 'Broccoli', - 'Carrot', - 'Cherry', - 'Coconut', - 'Grape', - 'Lemon', - 'Lettuce', - 'Mango', - 'Melon', - 'Mushroom', - 'Onion', - 'Orange', - 'Papaya', - 'Peach', - 'Pear', - 'Pineapple', - 'Potato', - 'Pumpkin', - 'Raspberry', - 'Strawberry', - 'Tomato', - ]; + // Translations + List get adjectives => [ + 'Adorable', + 'Beautiful', + 'Big', + 'Bright', + 'Clean', + 'Clever', + 'Cool', + 'Cute', + 'Cunning', + 'Determined', + 'Energetic', + 'Efficient', + 'Fantastic', + 'Fast', + 'Fine', + 'Fresh', + 'Good', + 'Gorgeous', + 'Great', + 'Handsome', + 'Hot', + 'Kind', + 'Lovely', + 'Mystic', + 'Neat', + 'Nice', + 'Patient', + 'Pretty', + 'Powerful', + 'Rich', + 'Secret', + 'Smart', + 'Solid', + 'Special', + 'Strategic', + 'Strong', + 'Tidy', + 'Wise', + ]; + List get fruits => [ + 'Apple', + 'Avocado', + 'Banana', + 'Blackberry', + 'Blueberry', + 'Broccoli', + 'Carrot', + 'Cherry', + 'Coconut', + 'Grape', + 'Lemon', + 'Lettuce', + 'Mango', + 'Melon', + 'Mushroom', + 'Onion', + 'Orange', + 'Papaya', + 'Peach', + 'Pear', + 'Pineapple', + 'Potato', + 'Pumpkin', + 'Raspberry', + 'Strawberry', + 'Tomato', + ]; - /// In some languages, the adjective must be last. - String combination({required Object adjective, required Object fruit}) => '${adjective} ${fruit}'; + /// In some languages, the adjective must be last. + String combination({required Object adjective, required Object fruit}) => + '${adjective} ${fruit}'; } // Path: dialogs class _StringsDialogsEn { - _StringsDialogsEn._(this._root); + _StringsDialogsEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - late final _StringsDialogsAddFileEn addFile = _StringsDialogsAddFileEn._(_root); - late final _StringsDialogsAddressInputEn addressInput = _StringsDialogsAddressInputEn._(_root); - late final _StringsDialogsCancelSessionEn cancelSession = _StringsDialogsCancelSessionEn._(_root); - late final _StringsDialogsCannotOpenFileEn cannotOpenFile = _StringsDialogsCannotOpenFileEn._(_root); - late final _StringsDialogsEncryptionDisabledNoticeEn encryptionDisabledNotice = _StringsDialogsEncryptionDisabledNoticeEn._(_root); - late final _StringsDialogsErrorDialogEn errorDialog = _StringsDialogsErrorDialogEn._(_root); - late final _StringsDialogsFavoriteDialogEn favoriteDialog = _StringsDialogsFavoriteDialogEn._(_root); - late final _StringsDialogsFavoriteDeleteDialogEn favoriteDeleteDialog = _StringsDialogsFavoriteDeleteDialogEn._(_root); - late final _StringsDialogsFavoriteEditDialogEn favoriteEditDialog = _StringsDialogsFavoriteEditDialogEn._(_root); - late final _StringsDialogsFileInfoEn fileInfo = _StringsDialogsFileInfoEn._(_root); - late final _StringsDialogsFileNameInputEn fileNameInput = _StringsDialogsFileNameInputEn._(_root); - late final _StringsDialogsHistoryClearDialogEn historyClearDialog = _StringsDialogsHistoryClearDialogEn._(_root); - late final _StringsDialogsLocalNetworkUnauthorizedEn localNetworkUnauthorized = _StringsDialogsLocalNetworkUnauthorizedEn._(_root); - late final _StringsDialogsMessageInputEn messageInput = _StringsDialogsMessageInputEn._(_root); - late final _StringsDialogsNoFilesEn noFiles = _StringsDialogsNoFilesEn._(_root); - late final _StringsDialogsNoPermissionEn noPermission = _StringsDialogsNoPermissionEn._(_root); - late final _StringsDialogsNotAvailableOnPlatformEn notAvailableOnPlatform = _StringsDialogsNotAvailableOnPlatformEn._(_root); - late final _StringsDialogsQrEn qr = _StringsDialogsQrEn._(_root); - late final _StringsDialogsQuickActionsEn quickActions = _StringsDialogsQuickActionsEn._(_root); - late final _StringsDialogsQuickSaveNoticeEn quickSaveNotice = _StringsDialogsQuickSaveNoticeEn._(_root); - late final _StringsDialogsQuickSaveFromFavoritesNoticeEn quickSaveFromFavoritesNotice = _StringsDialogsQuickSaveFromFavoritesNoticeEn._(_root); - late final _StringsDialogsPinEn pin = _StringsDialogsPinEn._(_root); - late final _StringsDialogsSendModeHelpEn sendModeHelp = _StringsDialogsSendModeHelpEn._(_root); - late final _StringsDialogsZoomEn zoom = _StringsDialogsZoomEn._(_root); + // Translations + late final _StringsDialogsAddFileEn addFile = + _StringsDialogsAddFileEn._(_root); + late final _StringsDialogsAddressInputEn addressInput = + _StringsDialogsAddressInputEn._(_root); + late final _StringsDialogsCancelSessionEn cancelSession = + _StringsDialogsCancelSessionEn._(_root); + late final _StringsDialogsCannotOpenFileEn cannotOpenFile = + _StringsDialogsCannotOpenFileEn._(_root); + late final _StringsDialogsEncryptionDisabledNoticeEn + encryptionDisabledNotice = + _StringsDialogsEncryptionDisabledNoticeEn._(_root); + late final _StringsDialogsErrorDialogEn errorDialog = + _StringsDialogsErrorDialogEn._(_root); + late final _StringsDialogsFavoriteDialogEn favoriteDialog = + _StringsDialogsFavoriteDialogEn._(_root); + late final _StringsDialogsFavoriteDeleteDialogEn favoriteDeleteDialog = + _StringsDialogsFavoriteDeleteDialogEn._(_root); + late final _StringsDialogsFavoriteEditDialogEn favoriteEditDialog = + _StringsDialogsFavoriteEditDialogEn._(_root); + late final _StringsDialogsFileInfoEn fileInfo = + _StringsDialogsFileInfoEn._(_root); + late final _StringsDialogsFileNameInputEn fileNameInput = + _StringsDialogsFileNameInputEn._(_root); + late final _StringsDialogsHistoryClearDialogEn historyClearDialog = + _StringsDialogsHistoryClearDialogEn._(_root); + late final _StringsDialogsLocalNetworkUnauthorizedEn + localNetworkUnauthorized = + _StringsDialogsLocalNetworkUnauthorizedEn._(_root); + late final _StringsDialogsMessageInputEn messageInput = + _StringsDialogsMessageInputEn._(_root); + late final _StringsDialogsNoFilesEn noFiles = + _StringsDialogsNoFilesEn._(_root); + late final _StringsDialogsNoPermissionEn noPermission = + _StringsDialogsNoPermissionEn._(_root); + late final _StringsDialogsNotAvailableOnPlatformEn notAvailableOnPlatform = + _StringsDialogsNotAvailableOnPlatformEn._(_root); + late final _StringsDialogsQrEn qr = _StringsDialogsQrEn._(_root); + late final _StringsDialogsQuickActionsEn quickActions = + _StringsDialogsQuickActionsEn._(_root); + late final _StringsDialogsQuickSaveNoticeEn quickSaveNotice = + _StringsDialogsQuickSaveNoticeEn._(_root); + late final _StringsDialogsQuickSaveFromFavoritesNoticeEn + quickSaveFromFavoritesNotice = + _StringsDialogsQuickSaveFromFavoritesNoticeEn._(_root); + late final _StringsDialogsPinEn pin = _StringsDialogsPinEn._(_root); + late final _StringsDialogsSendModeHelpEn sendModeHelp = + _StringsDialogsSendModeHelpEn._(_root); + late final _StringsDialogsZoomEn zoom = _StringsDialogsZoomEn._(_root); } // Path: sanitization class _StringsSanitizationEn { - _StringsSanitizationEn._(this._root); + _StringsSanitizationEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get empty => 'Filename cannot be empty'; - String get invalid => 'Filename contains invalid characters'; + // Translations + String get empty => 'Filename cannot be empty'; + String get invalid => 'Filename contains invalid characters'; } // Path: tray class _StringsTrayEn { - _StringsTrayEn._(this._root); + _StringsTrayEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get open => _root.general.open; - String get close => 'Quit LocalSend'; - String get closeWindows => 'Exit'; + // Translations + String get open => _root.general.open; + String get close => 'Quit LocalSend'; + String get closeWindows => 'Exit'; } // Path: web class _StringsWebEn { - _StringsWebEn._(this._root); + _StringsWebEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get waiting => _root.sendPage.waiting; - String get enterPin => 'Enter PIN'; - String get invalidPin => 'Invalid PIN'; - String get tooManyAttempts => 'Too many attempts'; - String get rejected => 'Rejected'; - String get files => 'Files'; - String get fileName => 'File name'; - String get size => 'Size'; + // Translations + String get waiting => _root.sendPage.waiting; + String get enterPin => 'Enter PIN'; + String get invalidPin => 'Invalid PIN'; + String get tooManyAttempts => 'Too many attempts'; + String get rejected => 'Rejected'; + String get files => 'Files'; + String get fileName => 'File name'; + String get size => 'Size'; } // Path: assetPicker class _StringsAssetPickerEn { - _StringsAssetPickerEn._(this._root); + _StringsAssetPickerEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get confirm => 'Confirm'; - String get cancel => 'Cancel'; - String get edit => 'Edit'; - String get gifIndicator => 'GIF'; - String get loadFailed => 'Load failed'; - String get original => 'Origin'; - String get preview => 'Preview'; - String get select => 'Select'; - String get emptyList => 'Empty list'; - String get unSupportedAssetType => 'Unsupported file type.'; - String get unableToAccessAll => 'Unable to access all files on the device'; - String get viewingLimitedAssetsTip => 'Only view files and albums accessible to the app.'; - String get changeAccessibleLimitedAssets => 'Click to update accessible files'; - String get accessAllTip => 'App can only access some files on the device. Go to system settings and allow the app to access all media on the device.'; - String get goToSystemSettings => 'Go to system settings'; - String get accessLimitedAssets => 'Continue with limited access'; - String get accessiblePathName => 'Accessible files'; - String get sTypeAudioLabel => 'Audio'; - String get sTypeImageLabel => 'Image'; - String get sTypeVideoLabel => 'Video'; - String get sTypeOtherLabel => 'Other media'; - String get sActionPlayHint => 'play'; - String get sActionPreviewHint => 'preview'; - String get sActionSelectHint => 'select'; - String get sActionSwitchPathLabel => 'change path'; - String get sActionUseCameraHint => 'use camera'; - String get sNameDurationLabel => 'duration'; - String get sUnitAssetCountLabel => 'count'; + // Translations + String get confirm => 'Confirm'; + String get cancel => 'Cancel'; + String get edit => 'Edit'; + String get gifIndicator => 'GIF'; + String get loadFailed => 'Load failed'; + String get original => 'Origin'; + String get preview => 'Preview'; + String get select => 'Select'; + String get emptyList => 'Empty list'; + String get unSupportedAssetType => 'Unsupported file type.'; + String get unableToAccessAll => 'Unable to access all files on the device'; + String get viewingLimitedAssetsTip => + 'Only view files and albums accessible to the app.'; + String get changeAccessibleLimitedAssets => + 'Click to update accessible files'; + String get accessAllTip => + 'App can only access some files on the device. Go to system settings and allow the app to access all media on the device.'; + String get goToSystemSettings => 'Go to system settings'; + String get accessLimitedAssets => 'Continue with limited access'; + String get accessiblePathName => 'Accessible files'; + String get sTypeAudioLabel => 'Audio'; + String get sTypeImageLabel => 'Image'; + String get sTypeVideoLabel => 'Video'; + String get sTypeOtherLabel => 'Other media'; + String get sActionPlayHint => 'play'; + String get sActionPreviewHint => 'preview'; + String get sActionSelectHint => 'select'; + String get sActionSwitchPathLabel => 'change path'; + String get sActionUseCameraHint => 'use camera'; + String get sNameDurationLabel => 'duration'; + String get sUnitAssetCountLabel => 'count'; } // Path: receiveTab.infoBox class _StringsReceiveTabInfoBoxEn { - _StringsReceiveTabInfoBoxEn._(this._root); + _StringsReceiveTabInfoBoxEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get ip => 'IP:'; - String get port => 'Port:'; - String get alias => 'Device name:'; + // Translations + String get ip => 'IP:'; + String get port => 'Port:'; + String get alias => 'Device name:'; } // Path: sendTab.selection class _StringsSendTabSelectionEn { - _StringsSendTabSelectionEn._(this._root); + _StringsSendTabSelectionEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Selection'; - String files({required Object files}) => 'Files: ${files}'; - String size({required Object size}) => 'Size: ${size}'; + // Translations + String get title => 'Selection'; + String files({required Object files}) => 'Files: ${files}'; + String size({required Object size}) => 'Size: ${size}'; } // Path: sendTab.picker class _StringsSendTabPickerEn { - _StringsSendTabPickerEn._(this._root); + _StringsSendTabPickerEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get file => 'File'; - String get folder => 'Folder'; - String get media => 'Media'; - String get text => 'Text'; - String get app => 'App'; - String get clipboard => 'Paste'; + // Translations + String get file => 'File'; + String get folder => 'Folder'; + String get media => 'Media'; + String get text => 'Text'; + String get app => 'App'; + String get clipboard => 'Paste'; } // Path: sendTab.sendModes class _StringsSendTabSendModesEn { - _StringsSendTabSendModesEn._(this._root); + _StringsSendTabSendModesEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get single => 'Single recipient'; - String get multiple => 'Multiple recipients'; - String get link => 'Share via link'; + // Translations + String get single => 'Single recipient'; + String get multiple => 'Multiple recipients'; + String get link => 'Share via link'; } // Path: settingsTab.general class _StringsSettingsTabGeneralEn { - _StringsSettingsTabGeneralEn._(this._root); + _StringsSettingsTabGeneralEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'General'; - String get brightness => 'Theme'; - late final _StringsSettingsTabGeneralBrightnessOptionsEn brightnessOptions = _StringsSettingsTabGeneralBrightnessOptionsEn._(_root); - String get color => 'Color'; - late final _StringsSettingsTabGeneralColorOptionsEn colorOptions = _StringsSettingsTabGeneralColorOptionsEn._(_root); - String get language => 'Language'; - late final _StringsSettingsTabGeneralLanguageOptionsEn languageOptions = _StringsSettingsTabGeneralLanguageOptionsEn._(_root); - String get saveWindowPlacement => 'Save window position after quit'; - String get saveWindowPlacementWindows => 'Save window position after exit'; - String get minimizeToTray => 'Minimize to the System Tray/Menu Bar when closing'; - String get launchAtStartup => 'Autostart after login'; - String get launchMinimized => 'Autostart: Start hidden'; - String get showInContextMenu => 'Show LocalSend in context menu'; - String get animations => 'Animations'; + // Translations + String get title => 'General'; + String get brightness => 'Theme'; + late final _StringsSettingsTabGeneralBrightnessOptionsEn brightnessOptions = + _StringsSettingsTabGeneralBrightnessOptionsEn._(_root); + String get color => 'Color'; + late final _StringsSettingsTabGeneralColorOptionsEn colorOptions = + _StringsSettingsTabGeneralColorOptionsEn._(_root); + String get language => 'Language'; + late final _StringsSettingsTabGeneralLanguageOptionsEn languageOptions = + _StringsSettingsTabGeneralLanguageOptionsEn._(_root); + String get saveWindowPlacement => 'Save window position after quit'; + String get saveWindowPlacementWindows => 'Save window position after exit'; + String get minimizeToTray => + 'Minimize to the System Tray/Menu Bar when closing'; + String get launchAtStartup => 'Autostart after login'; + String get launchMinimized => 'Autostart: Start hidden'; + String get showInContextMenu => 'Show LocalSend in context menu'; + String get animations => 'Animations'; } // Path: settingsTab.receive class _StringsSettingsTabReceiveEn { - _StringsSettingsTabReceiveEn._(this._root); + _StringsSettingsTabReceiveEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Receive'; - String get quickSave => _root.general.quickSave; - String get quickSaveFromFavorites => _root.general.quickSaveFromFavorites; - String get requirePin => _root.webSharePage.requirePin; - String get autoFinish => 'Auto Finish'; - String get destination => 'Save to folder'; - String get downloads => '(Downloads)'; - String get saveToGallery => 'Save media to gallery'; - String get saveToHistory => 'Save to history'; + // Translations + String get title => 'Receive'; + String get quickSave => _root.general.quickSave; + String get quickSaveFromFavorites => _root.general.quickSaveFromFavorites; + String get requirePin => _root.webSharePage.requirePin; + String get autoFinish => 'Auto Finish'; + String get destination => 'Save to folder'; + String get downloads => '(Downloads)'; + String get saveToGallery => 'Save media to gallery'; + String get saveToHistory => 'Save to history'; } // Path: settingsTab.send class _StringsSettingsTabSendEn { - _StringsSettingsTabSendEn._(this._root); + _StringsSettingsTabSendEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Send'; - String get shareViaLinkAutoAccept => 'Automatically accept requests in "Share via link" mode'; + // Translations + String get title => 'Send'; + String get shareViaLinkAutoAccept => + 'Automatically accept requests in "Share via link" mode'; } // Path: settingsTab.network class _StringsSettingsTabNetworkEn { - _StringsSettingsTabNetworkEn._(this._root); + _StringsSettingsTabNetworkEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Network'; - String get needRestart => 'Restart the server to apply the settings!'; - String get server => 'Server'; - String get alias => 'Device name'; - String get deviceType => 'Device type'; - String get deviceModel => 'Device model'; - String get port => 'Port'; - String get discoveryTimeout => 'Discovery Timeout'; - String get useSystemName => 'Use system name'; - String get generateRandomAlias => 'Generate random alias'; - String portWarning({required Object defaultPort}) => 'You might not be detected by other devices because you are using a custom port. (default: ${defaultPort})'; - String get encryption => 'Encryption'; - String get multicastGroup => 'Multicast address'; - String multicastGroupWarning({required Object defaultMulticast}) => 'You might not be detected by other devices because you are using a custom multicast address. (default: ${defaultMulticast})'; + // Translations + String get title => 'Network'; + String get needRestart => 'Restart the server to apply the settings!'; + String get server => 'Server'; + String get alias => 'Device name'; + String get deviceType => 'Device type'; + String get deviceModel => 'Device model'; + String get port => 'Port'; + String get discoveryTimeout => 'Discovery Timeout'; + String get useSystemName => 'Use system name'; + String get generateRandomAlias => 'Generate random alias'; + String portWarning({required Object defaultPort}) => + 'You might not be detected by other devices because you are using a custom port. (default: ${defaultPort})'; + String get encryption => 'Encryption'; + String get multicastGroup => 'Multicast address'; + String multicastGroupWarning({required Object defaultMulticast}) => + 'You might not be detected by other devices because you are using a custom multicast address. (default: ${defaultMulticast})'; } // Path: settingsTab.other class _StringsSettingsTabOtherEn { - _StringsSettingsTabOtherEn._(this._root); + _StringsSettingsTabOtherEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Other'; - String get support => 'Support LocalSend'; - String get donate => 'Donate'; - String get privacyPolicy => 'Privacy Policy'; - String get termsOfUse => 'Terms of Use'; + // Translations + String get title => 'Other'; + String get support => 'Support LocalSend'; + String get donate => 'Donate'; + String get privacyPolicy => 'Privacy Policy'; + String get termsOfUse => 'Terms of Use'; } // Path: troubleshootPage.firewall class _StringsTroubleshootPageFirewallEn { - _StringsTroubleshootPageFirewallEn._(this._root); + _StringsTroubleshootPageFirewallEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get symptom => 'This device can send files to other devices but other devices cannot send files to this device.'; - String solution({required Object port}) => 'This is most likely a firewall issue. You can solve this by allowing incoming connections (UDP and TCP) on port ${port}.'; - String get openFirewall => 'Open Firewall'; + // Translations + String get symptom => + 'This device can send files to other devices but other devices cannot send files to this device.'; + String solution({required Object port}) => + 'This is most likely a firewall issue. You can solve this by allowing incoming connections (UDP and TCP) on port ${port}.'; + String get openFirewall => 'Open Firewall'; } // Path: troubleshootPage.noDiscovery class _StringsTroubleshootPageNoDiscoveryEn { - _StringsTroubleshootPageNoDiscoveryEn._(this._root); + _StringsTroubleshootPageNoDiscoveryEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get symptom => 'This device cannot discover other devices.'; - String get solution => 'Please make sure that all devices are on the same Wi-Fi network and share the same configuration (port, multicast address, encryption). You can try to type the IP address of the target device manually. If this works, consider adding this device to the favorites so it can be automatically discovered in the future.'; + // Translations + String get symptom => 'This device cannot discover other devices.'; + String get solution => + 'Please make sure that all devices are on the same Wi-Fi network and share the same configuration (port, multicast address, encryption). You can try to type the IP address of the target device manually. If this works, consider adding this device to the favorites so it can be automatically discovered in the future.'; } // Path: troubleshootPage.noConnection class _StringsTroubleshootPageNoConnectionEn { - _StringsTroubleshootPageNoConnectionEn._(this._root); + _StringsTroubleshootPageNoConnectionEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get symptom => 'Both devices cannot discover each other nor can they share files.'; - String get solution => 'Does the problem exist on both sides? If so, you need to make sure that both devices are on the same Wi-Fi network and share the same configuration (port, multicast address, encryption). The Wi-Fi network may not allow communication between participants (AP isolation). In this case, this option must be enabled on the router.'; + // Translations + String get symptom => + 'Both devices cannot discover each other nor can they share files.'; + String get solution => + 'Does the problem exist on both sides? If so, you need to make sure that both devices are on the same Wi-Fi network and share the same configuration (port, multicast address, encryption). The Wi-Fi network may not allow communication between participants (AP isolation). In this case, this option must be enabled on the router.'; } // Path: receiveHistoryPage.entryActions class _StringsReceiveHistoryPageEntryActionsEn { - _StringsReceiveHistoryPageEntryActionsEn._(this._root); + _StringsReceiveHistoryPageEntryActionsEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get open => 'Open file'; - String get showInFolder => 'Show in folder'; - String get info => 'Information'; - String get deleteFromHistory => 'Delete from history'; + // Translations + String get open => 'Open file'; + String get showInFolder => 'Show in folder'; + String get info => 'Information'; + String get deleteFromHistory => 'Delete from history'; } // Path: progressPage.total class _StringsProgressPageTotalEn { - _StringsProgressPageTotalEn._(this._root); + _StringsProgressPageTotalEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - late final _StringsProgressPageTotalTitleEn title = _StringsProgressPageTotalTitleEn._(_root); - String count({required Object curr, required Object n}) => 'Files: ${curr} / ${n}'; - String size({required Object curr, required Object n}) => 'Size: ${curr} / ${n}'; - String speed({required Object speed}) => 'Speed: ${speed}/s'; + // Translations + late final _StringsProgressPageTotalTitleEn title = + _StringsProgressPageTotalTitleEn._(_root); + String count({required Object curr, required Object n}) => + 'Files: ${curr} / ${n}'; + String size({required Object curr, required Object n}) => + 'Size: ${curr} / ${n}'; + String speed({required Object speed}) => 'Speed: ${speed}/s'; } // Path: dialogs.addFile class _StringsDialogsAddFileEn { - _StringsDialogsAddFileEn._(this._root); + _StringsDialogsAddFileEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Add to selection'; - String get content => 'What do you want to add?'; + // Translations + String get title => 'Add to selection'; + String get content => 'What do you want to add?'; } // Path: dialogs.addressInput class _StringsDialogsAddressInputEn { - _StringsDialogsAddressInputEn._(this._root); + _StringsDialogsAddressInputEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Enter address'; - String get hashtag => 'Hashtag'; - String get ip => 'IP Address'; - String get recentlyUsed => 'Recently used: '; + // Translations + String get title => 'Enter address'; + String get hashtag => 'Hashtag'; + String get ip => 'IP Address'; + String get recentlyUsed => 'Recently used: '; } // Path: dialogs.cancelSession class _StringsDialogsCancelSessionEn { - _StringsDialogsCancelSessionEn._(this._root); + _StringsDialogsCancelSessionEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Cancel files transfer'; - String get content => 'Do you really want to cancel the files transfer?'; + // Translations + String get title => 'Cancel files transfer'; + String get content => 'Do you really want to cancel the files transfer?'; } // Path: dialogs.cannotOpenFile class _StringsDialogsCannotOpenFileEn { - _StringsDialogsCannotOpenFileEn._(this._root); + _StringsDialogsCannotOpenFileEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Cannot open file'; - String content({required Object file}) => 'Could not open "${file}". Has this file been moved, renamed or deleted?'; + // Translations + String get title => 'Cannot open file'; + String content({required Object file}) => + 'Could not open "${file}". Has this file been moved, renamed or deleted?'; } // Path: dialogs.encryptionDisabledNotice class _StringsDialogsEncryptionDisabledNoticeEn { - _StringsDialogsEncryptionDisabledNoticeEn._(this._root); + _StringsDialogsEncryptionDisabledNoticeEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Encryption disabled'; - String get content => 'Communication now takes place via the unencrypted HTTP protocol. To use HTTPS protocol, enable encryption again.'; + // Translations + String get title => 'Encryption disabled'; + String get content => + 'Communication now takes place via the unencrypted HTTP protocol. To use HTTPS protocol, enable encryption again.'; } // Path: dialogs.errorDialog class _StringsDialogsErrorDialogEn { - _StringsDialogsErrorDialogEn._(this._root); + _StringsDialogsErrorDialogEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => _root.general.error; + // Translations + String get title => _root.general.error; } // Path: dialogs.favoriteDialog class _StringsDialogsFavoriteDialogEn { - _StringsDialogsFavoriteDialogEn._(this._root); + _StringsDialogsFavoriteDialogEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Favorites'; - String get noFavorites => 'No favorite devices yet.'; - String get addFavorite => 'Add'; + // Translations + String get title => 'Favorites'; + String get noFavorites => 'No favorite devices yet.'; + String get addFavorite => 'Add'; } // Path: dialogs.favoriteDeleteDialog class _StringsDialogsFavoriteDeleteDialogEn { - _StringsDialogsFavoriteDeleteDialogEn._(this._root); + _StringsDialogsFavoriteDeleteDialogEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Delete from favorites'; - String content({required Object name}) => 'Do you really want to delete from favorites "${name}"?'; + // Translations + String get title => 'Delete from favorites'; + String content({required Object name}) => + 'Do you really want to delete from favorites "${name}"?'; } // Path: dialogs.favoriteEditDialog class _StringsDialogsFavoriteEditDialogEn { - _StringsDialogsFavoriteEditDialogEn._(this._root); + _StringsDialogsFavoriteEditDialogEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get titleAdd => 'Add to favorites'; - String get titleEdit => 'Settings'; - String get name => 'Device name'; - String get auto => '(auto)'; - String get ip => 'IP Address'; - String get port => 'Port'; + // Translations + String get titleAdd => 'Add to favorites'; + String get titleEdit => 'Settings'; + String get name => 'Device name'; + String get auto => '(auto)'; + String get ip => 'IP Address'; + String get port => 'Port'; } // Path: dialogs.fileInfo class _StringsDialogsFileInfoEn { - _StringsDialogsFileInfoEn._(this._root); + _StringsDialogsFileInfoEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'File information'; - String get fileName => 'File name:'; - String get path => 'Path:'; - String get size => 'Size:'; - String get sender => 'Sender:'; - String get time => 'Time:'; + // Translations + String get title => 'File information'; + String get fileName => 'File name:'; + String get path => 'Path:'; + String get size => 'Size:'; + String get sender => 'Sender:'; + String get time => 'Time:'; } // Path: dialogs.fileNameInput class _StringsDialogsFileNameInputEn { - _StringsDialogsFileNameInputEn._(this._root); + _StringsDialogsFileNameInputEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Enter file name'; - String original({required Object original}) => 'Original: ${original}'; + // Translations + String get title => 'Enter file name'; + String original({required Object original}) => 'Original: ${original}'; } // Path: dialogs.historyClearDialog class _StringsDialogsHistoryClearDialogEn { - _StringsDialogsHistoryClearDialogEn._(this._root); + _StringsDialogsHistoryClearDialogEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Clear history'; - String get content => 'Do you really want to delete the entire history?'; + // Translations + String get title => 'Clear history'; + String get content => 'Do you really want to delete the entire history?'; } // Path: dialogs.localNetworkUnauthorized class _StringsDialogsLocalNetworkUnauthorizedEn { - _StringsDialogsLocalNetworkUnauthorizedEn._(this._root); + _StringsDialogsLocalNetworkUnauthorizedEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => _root.dialogs.noPermission.title; - String get description => 'LocalSend can\'t find other devices without having the permission to scan the local network. Please grant this permission in the settings.'; - String get gotoSettings => 'Settings'; + // Translations + String get title => _root.dialogs.noPermission.title; + String get description => + 'LocalSend can\'t find other devices without having the permission to scan the local network. Please grant this permission in the settings.'; + String get gotoSettings => 'Settings'; } // Path: dialogs.messageInput class _StringsDialogsMessageInputEn { - _StringsDialogsMessageInputEn._(this._root); + _StringsDialogsMessageInputEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Type message'; - String get multiline => 'Multiline'; + // Translations + String get title => 'Type message'; + String get multiline => 'Multiline'; } // Path: dialogs.noFiles class _StringsDialogsNoFilesEn { - _StringsDialogsNoFilesEn._(this._root); + _StringsDialogsNoFilesEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'No files selected'; - String get content => 'Please select at least one file.'; + // Translations + String get title => 'No files selected'; + String get content => 'Please select at least one file.'; } // Path: dialogs.noPermission class _StringsDialogsNoPermissionEn { - _StringsDialogsNoPermissionEn._(this._root); + _StringsDialogsNoPermissionEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'No permission'; - String get content => 'You have not granted the necessary permissions. Please grant them in the settings.'; + // Translations + String get title => 'No permission'; + String get content => + 'You have not granted the necessary permissions. Please grant them in the settings.'; } // Path: dialogs.notAvailableOnPlatform class _StringsDialogsNotAvailableOnPlatformEn { - _StringsDialogsNotAvailableOnPlatformEn._(this._root); + _StringsDialogsNotAvailableOnPlatformEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Not available'; - String get content => 'This feature is only available on:'; + // Translations + String get title => 'Not available'; + String get content => 'This feature is only available on:'; } // Path: dialogs.qr class _StringsDialogsQrEn { - _StringsDialogsQrEn._(this._root); + _StringsDialogsQrEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'QR Code'; + // Translations + String get title => 'QR Code'; } // Path: dialogs.quickActions class _StringsDialogsQuickActionsEn { - _StringsDialogsQuickActionsEn._(this._root); + _StringsDialogsQuickActionsEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Quick Actions'; - String get counter => 'Counter'; - String get prefix => 'Prefix'; - String get padZero => 'Pad with zeros'; - String get sortBeforeCount => 'Sort alphabetically beforehand (A-Z)'; - String get random => 'Random'; + // Translations + String get title => 'Quick Actions'; + String get counter => 'Counter'; + String get prefix => 'Prefix'; + String get padZero => 'Pad with zeros'; + String get sortBeforeCount => 'Sort alphabetically beforehand (A-Z)'; + String get random => 'Random'; } // Path: dialogs.quickSaveNotice class _StringsDialogsQuickSaveNoticeEn { - _StringsDialogsQuickSaveNoticeEn._(this._root); + _StringsDialogsQuickSaveNoticeEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => _root.general.quickSave; - String get content => 'File requests are now accepted automatically. Be aware that everyone on the local network can send you files.'; + // Translations + String get title => _root.general.quickSave; + String get content => + 'File requests are now accepted automatically. Be aware that everyone on the local network can send you files.'; } // Path: dialogs.quickSaveFromFavoritesNotice class _StringsDialogsQuickSaveFromFavoritesNoticeEn { - _StringsDialogsQuickSaveFromFavoritesNoticeEn._(this._root); + _StringsDialogsQuickSaveFromFavoritesNoticeEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => _root.general.quickSaveFromFavorites; - String get content => 'File requests are now accepted automatically from devices in your favorites list.'; + // Translations + String get title => _root.general.quickSaveFromFavorites; + String get content => + 'File requests are now accepted automatically from devices in your favorites list.'; } // Path: dialogs.pin class _StringsDialogsPinEn { - _StringsDialogsPinEn._(this._root); + _StringsDialogsPinEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Enter PIN'; + // Translations + String get title => 'Enter PIN'; } // Path: dialogs.sendModeHelp class _StringsDialogsSendModeHelpEn { - _StringsDialogsSendModeHelpEn._(this._root); + _StringsDialogsSendModeHelpEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'Send modes'; - String get single => 'Sends files to one recipient. Selection will be cleared after finished files transfer.'; - String get multiple => 'Sends files to multiple recipients. Selection will not be cleared after finished files transfer.'; - String get link => 'Recipients who do not have LocalSend installed can download the selected files by opening the link in their browser.'; + // Translations + String get title => 'Send modes'; + String get single => + 'Sends files to one recipient. Selection will be cleared after finished files transfer.'; + String get multiple => + 'Sends files to multiple recipients. Selection will not be cleared after finished files transfer.'; + String get link => + 'Recipients who do not have LocalSend installed can download the selected files by opening the link in their browser.'; } // Path: dialogs.zoom class _StringsDialogsZoomEn { - _StringsDialogsZoomEn._(this._root); + _StringsDialogsZoomEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get title => 'URL'; + // Translations + String get title => 'URL'; } // Path: settingsTab.general.brightnessOptions class _StringsSettingsTabGeneralBrightnessOptionsEn { - _StringsSettingsTabGeneralBrightnessOptionsEn._(this._root); + _StringsSettingsTabGeneralBrightnessOptionsEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get system => 'System'; - String get dark => 'Dark'; - String get light => 'Light'; + // Translations + String get system => 'System'; + String get dark => 'Dark'; + String get light => 'Light'; } // Path: settingsTab.general.colorOptions class _StringsSettingsTabGeneralColorOptionsEn { - _StringsSettingsTabGeneralColorOptionsEn._(this._root); + _StringsSettingsTabGeneralColorOptionsEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get system => 'System'; - String get oled => 'OLED'; + // Translations + String get system => 'System'; + String get oled => 'OLED'; } // Path: settingsTab.general.languageOptions class _StringsSettingsTabGeneralLanguageOptionsEn { - _StringsSettingsTabGeneralLanguageOptionsEn._(this._root); + _StringsSettingsTabGeneralLanguageOptionsEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String get system => 'System'; + // Translations + String get system => 'System'; } // Path: progressPage.total.title class _StringsProgressPageTotalTitleEn { - _StringsProgressPageTotalTitleEn._(this._root); + _StringsProgressPageTotalTitleEn._(this._root); - final Translations _root; // ignore: unused_field + final Translations _root; // ignore: unused_field - // Translations - String sending({required Object time}) => 'Total progress (${time})'; - String get finishedError => 'Finished with error'; - String get canceledSender => 'Canceled by sender'; - String get canceledReceiver => 'Canceled by receiver'; + // Translations + String sending({required Object time}) => 'Total progress (${time})'; + String get finishedError => 'Finished with error'; + String get canceledSender => 'Canceled by sender'; + String get canceledReceiver => 'Canceled by receiver'; } diff --git a/app/lib/pages/apk_picker_page.dart b/app/lib/pages/apk_picker_page.dart index e89f2785..3fa519fd 100644 --- a/app/lib/pages/apk_picker_page.dart +++ b/app/lib/pages/apk_picker_page.dart @@ -22,11 +22,34 @@ class ApkPickerPage extends StatefulWidget { class _ApkPickerPageState extends State with Refena { final _textController = TextEditingController(); + final List _selectedApps = []; - void _pickApp(Application app) { + Future _pickApp(Application app) async { + await ref.redux(selectedSendingFilesProvider).dispatchAsync(AddFilesAction( + files: [app], + converter: CrossFileConverters.convertApplication, + )); + + if (mounted) { + context.pop(); + } + } + + Future _pickApps(List apps) async { // ignore: discarded_futures - ref.redux(selectedSendingFilesProvider).dispatchAsync(AddFilesAction(files: [app], converter: CrossFileConverters.convertApplication)); - context.pop(); + + for (Application app in apps) { + await ref + .redux(selectedSendingFilesProvider) + .dispatchAsync(AddFilesAction( + files: [app], + converter: CrossFileConverters.convertApplication, + )); + } + + if (mounted) { + context.pop(); + } } @override @@ -36,6 +59,16 @@ class _ApkPickerPageState extends State with Refena { super.dispose(); } + void _appSelection(Application app) { + setState(() { + if (_selectedApps.contains(app)) { + _selectedApps.remove(app); + } else { + _selectedApps.add(app); + } + }); + } + @override Widget build(BuildContext context) { final apkParams = ref.watch(apkSearchParamProvider); @@ -61,15 +94,32 @@ class _ApkPickerPageState extends State with Refena { }, onSelected: (value) { switch (value) { case 0: - ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(includeSystemApps: !old.includeSystemApps)); + ref.notifier(apkSearchParamProvider).setState((old) => + old.copyWith(includeSystemApps: !old.includeSystemApps)); break; case 1: - ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(onlyAppsWithLaunchIntent: !old.onlyAppsWithLaunchIntent)); + ref.notifier(apkSearchParamProvider).setState((old) => + old.copyWith( + onlyAppsWithLaunchIntent: + !old.onlyAppsWithLaunchIntent)); break; } }), ], ), + floatingActionButton: (_selectedApps.isEmpty) + ? Container() + : FloatingActionButton.extended( + onPressed: () async => await _pickApps(_selectedApps), + label: Row( + children: [ + const Icon(Icons.add), + const SizedBox(width: 5), + Text( + 'Add ${_selectedApps.length} ${(_selectedApps.length == 1) ? "App" : "Apps"}'), + ], + ), + ), body: ResponsiveListView.single( padding: const EdgeInsets.symmetric(horizontal: 15), tabletPadding: const EdgeInsets.symmetric(horizontal: 15), @@ -86,7 +136,9 @@ class _ApkPickerPageState extends State with Refena { controller: _textController, autofocus: true, onChanged: (s) { - ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(query: s)); + ref + .notifier(apkSearchParamProvider) + .setState((old) => old.copyWith(query: s)); setState(() {}); }, decoration: InputDecoration( @@ -99,7 +151,9 @@ class _ApkPickerPageState extends State with Refena { suffixIcon: apkParams.query.isNotEmpty ? IconButton( onPressed: () { - ref.notifier(apkSearchParamProvider).setState((old) => old.copyWith(query: '')); + ref + .notifier(apkSearchParamProvider) + .setState((old) => old.copyWith(query: '')); _textController.clear(); }, icon: const Icon(Icons.clear), @@ -110,7 +164,33 @@ class _ApkPickerPageState extends State with Refena { ), ), SliverToBoxAdapter( - child: Text(t.apkPickerPage.apps(n: apkAsync.data?.length ?? 0)), + child: Row( + children: [ + Text(t.apkPickerPage.apps(n: apkAsync.data?.length ?? 0)), + const Spacer(), + Row( + children: [ + const Text('Select Multiple Apps'), + const SizedBox(width: 5), + Switch( + value: apkParams.selectMultipleApps, + onChanged: (bool newValue) { + setState(() { + apkParams.selectMultipleApps = + !apkParams.selectMultipleApps; + }); + }, + activeTrackColor: Theme.of(context).colorScheme.primary, + activeColor: Theme.of(context).colorScheme.onPrimary, + inactiveThumbColor: + Theme.of(context).colorScheme.outline, + inactiveTrackColor: + Theme.of(context).colorScheme.surface, + ), + ], + ), + ], + ), ), const SliverToBoxAdapter( child: SizedBox(height: 10), @@ -127,7 +207,9 @@ class _ApkPickerPageState extends State with Refena { return Padding( padding: const EdgeInsets.only(bottom: 10), child: InkWell( - onTap: () => _pickApp(app), + onTap: () async => (apkParams.selectMultipleApps) + ? _appSelection(app) + : _pickApp(app), customBorder: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), @@ -151,21 +233,28 @@ class _ApkPickerPageState extends State with Refena { ), Consumer( builder: (context, ref) { - final appSize = ref.watch(apkSizeProvider(app.apkFilePath)); + final appSize = ref.watch( + apkSizeProvider(app.apkFilePath)); final appSizeString = appSize.maybeWhen( - data: (size) => '${size.asReadableFileSize} • ', + data: (size) => + '${size.asReadableFileSize} • ', orElse: () => '', ); return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( '$appSizeString${app.versionName != null ? 'v${app.versionName}' : ''}', - style: Theme.of(context).textTheme.bodySmall, + style: Theme.of(context) + .textTheme + .bodySmall, ), Text( app.packageName, - style: Theme.of(context).textTheme.bodySmall, + style: Theme.of(context) + .textTheme + .bodySmall, ), ], ); @@ -174,6 +263,15 @@ class _ApkPickerPageState extends State with Refena { ], ), ), + if (apkParams.selectMultipleApps) + Icon( + _selectedApps.contains(app) + ? Icons.check_circle + : Icons.radio_button_unchecked, + color: _selectedApps.contains(app) + ? Theme.of(context).iconTheme.color + : Colors.grey, + ) ], ), ), @@ -194,7 +292,7 @@ class _ApkPickerPageState extends State with Refena { }, ), SliverToBoxAdapter( - child: SizedBox(height: getNavBarPadding(context) + 30), // handle navigation bar + some additional padding + child: SizedBox(height: getNavBarPadding(context) + 50), ), ], ), diff --git a/app/lib/pages/home_page.dart b/app/lib/pages/home_page.dart index 6e8536e4..482d9ba4 100644 --- a/app/lib/pages/home_page.dart +++ b/app/lib/pages/home_page.dart @@ -60,7 +60,9 @@ class _HomePageState extends State with Refena { super.initState(); ensureRef((ref) async { - ref.redux(homePageControllerProvider).dispatch(ChangeTabAction(widget.initialTab)); + ref + .redux(homePageControllerProvider) + .dispatch(ChangeTabAction(widget.initialTab)); await postInit(context, ref, widget.appStart); }); } @@ -82,12 +84,17 @@ class _HomePageState extends State with Refena { }); }, onDragDone: (event) async { - if (event.files.length == 1 && Directory(event.files.first.path).existsSync()) { + if (event.files.length == 1 && + Directory(event.files.first.path).existsSync()) { // user dropped a directory - await ref.redux(selectedSendingFilesProvider).dispatchAsync(AddDirectoryAction(event.files.first.path)); + await ref + .redux(selectedSendingFilesProvider) + .dispatchAsync(AddDirectoryAction(event.files.first.path)); } else { // user dropped one or more files - await ref.redux(selectedSendingFilesProvider).dispatchAsync(AddFilesAction( + await ref + .redux(selectedSendingFilesProvider) + .dispatchAsync(AddFilesAction( files: event.files, converter: CrossFileConverters.convertXFile, )); @@ -102,7 +109,9 @@ class _HomePageState extends State with Refena { if (!sizingInformation.isMobile) NavigationRail( selectedIndex: vm.currentTab.index, - onDestinationSelected: (index) => vm.changeTab(HomeTab.values[index]), + groupAlignment: 0, + onDestinationSelected: (index) => + vm.changeTab(HomeTab.values[index]), extended: sizingInformation.isDesktop, backgroundColor: Theme.of(context).cardColorWithElevation, leading: sizingInformation.isDesktop @@ -111,7 +120,8 @@ class _HomePageState extends State with Refena { SizedBox(height: 20), Text( 'LocalSend', - style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 32, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), SizedBox(height: 20), @@ -150,7 +160,9 @@ class _HomePageState extends State with Refena { children: [ const Icon(Icons.file_download, size: 128), const SizedBox(height: 30), - Text(t.sendTab.placeItems, style: Theme.of(context).textTheme.titleLarge), + Text(t.sendTab.placeItems, + style: + Theme.of(context).textTheme.titleLarge), ], ), ), @@ -163,9 +175,11 @@ class _HomePageState extends State with Refena { bottomNavigationBar: sizingInformation.isMobile ? NavigationBar( selectedIndex: vm.currentTab.index, - onDestinationSelected: (index) => vm.changeTab(HomeTab.values[index]), + onDestinationSelected: (index) => + vm.changeTab(HomeTab.values[index]), destinations: HomeTab.values.map((tab) { - return NavigationDestination(icon: Icon(tab.icon), label: tab.label); + return NavigationDestination( + icon: Icon(tab.icon), label: tab.label); }).toList(), ) : null, diff --git a/app/lib/pages/tabs/send_tab.dart b/app/lib/pages/tabs/send_tab.dart index e09e490c..22b66078 100644 --- a/app/lib/pages/tabs/send_tab.dart +++ b/app/lib/pages/tabs/send_tab.dart @@ -44,10 +44,14 @@ class SendTab extends StatelessWidget { Widget build(BuildContext context) { return ViewModelBuilder( provider: sendTabVmProvider, - init: (context) => context.global.dispatchAsync(SendTabInitAction(context)), // ignore: discarded_futures + init: (context) async => context.global.dispatchAsync( + SendTabInitAction(context)), // ignore: discarded_futures builder: (context, vm) { - final sizingInformation = SizingInformation(MediaQuery.sizeOf(context).width); - final buttonWidth = sizingInformation.isDesktop ? BigButton.desktopWidth : BigButton.mobileWidth; + final sizingInformation = + SizingInformation(MediaQuery.sizeOf(context).width); + final buttonWidth = sizingInformation.isDesktop + ? BigButton.desktopWidth + : BigButton.mobileWidth; final ref = context.ref; return ResponsiveListView( padding: EdgeInsets.zero, @@ -55,7 +59,8 @@ class SendTab extends StatelessWidget { const SizedBox(height: 20), if (vm.selectedFiles.isEmpty) ...[ Padding( - padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding), + padding: + const EdgeInsets.symmetric(horizontal: _horizontalPadding), child: Text( t.sendTab.selection.title, style: Theme.of(context).textTheme.titleMedium, @@ -80,9 +85,13 @@ class SendTab extends StatelessWidget { ), ] else ...[ Card( - margin: const EdgeInsets.only(bottom: 10, left: _horizontalPadding, right: _horizontalPadding), + margin: const EdgeInsets.only( + bottom: 10, + left: _horizontalPadding, + right: _horizontalPadding), child: Padding( - padding: const EdgeInsetsDirectional.only(start: 15, top: 5, bottom: 15), + padding: const EdgeInsetsDirectional.only( + start: 15, top: 5, bottom: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -94,15 +103,22 @@ class SendTab extends StatelessWidget { ), const Spacer(), CustomIconButton( - onPressed: () => ref.redux(selectedSendingFilesProvider).dispatch(ClearSelectionAction()), - child: Icon(Icons.close, color: Theme.of(context).colorScheme.secondary), + onPressed: () => ref + .redux(selectedSendingFilesProvider) + .dispatch(ClearSelectionAction()), + child: Icon(Icons.close, + color: Theme.of(context).colorScheme.secondary), ), const SizedBox(width: 5), ], ), const SizedBox(height: 5), - Text(t.sendTab.selection.files(files: vm.selectedFiles.length)), - Text(t.sendTab.selection.size(size: vm.selectedFiles.fold(0, (prev, curr) => prev + curr.size).asReadableFileSize)), + Text(t.sendTab.selection + .files(files: vm.selectedFiles.length)), + Text(t.sendTab.selection.size( + size: vm.selectedFiles + .fold(0, (prev, curr) => prev + curr.size) + .asReadableFileSize)), const SizedBox(height: 10), SizedBox( height: defaultThumbnailSize, @@ -124,18 +140,22 @@ class SendTab extends StatelessWidget { children: [ TextButton( style: TextButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.onSurface, + foregroundColor: + Theme.of(context).colorScheme.onSurface, ), onPressed: () async { - await context.push(() => const SelectedFilesPage()); + await context + .push(() => const SelectedFilesPage()); }, child: Text(t.general.edit), ), const SizedBox(width: 15), ElevatedButton.icon( style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).colorScheme.primary, - foregroundColor: Theme.of(context).colorScheme.onPrimary, + backgroundColor: + Theme.of(context).colorScheme.primary, + foregroundColor: + Theme.of(context).colorScheme.onPrimary, ), onPressed: () async { if (_options.length == 1) { @@ -168,7 +188,8 @@ class SendTab extends StatelessWidget { Flexible( child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), - child: Text(t.sendTab.nearbyDevices, style: Theme.of(context).textTheme.titleMedium), + child: Text(t.sendTab.nearbyDevices, + style: Theme.of(context).textTheme.titleMedium), ), ), const SizedBox(width: 10), @@ -196,7 +217,10 @@ class SendTab extends StatelessWidget { ), if (vm.nearbyDevices.isEmpty) const Padding( - padding: EdgeInsets.only(bottom: 10, left: _horizontalPadding, right: _horizontalPadding), + padding: EdgeInsets.only( + bottom: 10, + left: _horizontalPadding, + right: _horizontalPadding), child: Opacity( opacity: 0.3, child: DevicePlaceholderListTile(), @@ -205,7 +229,10 @@ class SendTab extends StatelessWidget { ...vm.nearbyDevices.map((device) { final favoriteEntry = vm.favoriteDevices.findDevice(device); return Padding( - padding: const EdgeInsets.only(bottom: 10, left: _horizontalPadding, right: _horizontalPadding), + padding: const EdgeInsets.only( + bottom: 10, + left: _horizontalPadding, + right: _horizontalPadding), child: Hero( tag: 'device-${device.ip}', child: vm.sendMode == SendMode.multiple @@ -219,8 +246,10 @@ class SendTab extends StatelessWidget { device: device, isFavorite: favoriteEntry != null, nameOverride: favoriteEntry?.alias, - onFavoriteTap: () async => await vm.onToggleFavorite(context, device), - onTap: () async => await vm.onTapDevice(context, device), + onFavoriteTap: () async => + await vm.onToggleFavorite(context, device), + onTap: () async => + await vm.onTapDevice(context, device), ), ), ); @@ -236,7 +265,8 @@ class SendTab extends StatelessWidget { ), const SizedBox(height: 20), Padding( - padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding), + padding: + const EdgeInsets.symmetric(horizontal: _horizontalPadding), child: Consumer( builder: (context, ref) { final animations = ref.watch(animationProvider); @@ -244,9 +274,13 @@ class SendTab extends StatelessWidget { durationMillis: 6000, running: animations, children: [ - Text(t.sendTab.help, style: const TextStyle(color: Colors.grey), textAlign: TextAlign.center), + Text(t.sendTab.help, + style: const TextStyle(color: Colors.grey), + textAlign: TextAlign.center), if (checkPlatformCanReceiveShareIntent()) - Text(t.sendTab.shareIntentInfo, style: const TextStyle(color: Colors.grey), textAlign: TextAlign.center), + Text(t.sendTab.shareIntentInfo, + style: const TextStyle(color: Colors.grey), + textAlign: TextAlign.center), ], ); }, @@ -284,7 +318,9 @@ class _CircularPopupButton extends StatelessWidget { type: MaterialType.transparency, child: DividerTheme( data: DividerThemeData( - color: Theme.of(context).brightness == Brightness.light ? Colors.teal.shade100 : Colors.grey.shade700, + color: Theme.of(context).brightness == Brightness.light + ? Colors.teal.shade100 + : Colors.grey.shade700, ), child: PopupMenuButton( offset: const Offset(0, 40), @@ -309,11 +345,16 @@ class _ScanButton extends StatelessWidget { @override Widget build(BuildContext context) { - final (scanningFavorites, scanningIps) = context.ref.watch(nearbyDevicesProvider.select((s) => (s.runningFavoriteScan, s.runningIps))); + final (scanningFavorites, scanningIps) = context.ref.watch( + nearbyDevicesProvider + .select((s) => (s.runningFavoriteScan, s.runningIps))); final animations = context.ref.watch(animationProvider); - final spinning = (scanningFavorites || scanningIps.isNotEmpty) && animations; - final iconColor = !animations && scanningIps.isNotEmpty ? Theme.of(context).colorScheme.warning : null; + final spinning = + (scanningFavorites || scanningIps.isNotEmpty) && animations; + final iconColor = !animations && scanningIps.isNotEmpty + ? Theme.of(context).colorScheme.warning + : null; if (ips.length <= StartSmartScan.maxInterfaces) { return Tooltip( @@ -324,8 +365,11 @@ class _ScanButton extends StatelessWidget { reverse: true, child: CustomIconButton( onPressed: () async { - context.redux(nearbyDevicesProvider).dispatch(ClearFoundDevicesAction()); - await context.global.dispatchAsync(StartSmartScan(forceLegacy: true)); + context + .redux(nearbyDevicesProvider) + .dispatch(ClearFoundDevicesAction()); + await context.global + .dispatchAsync(StartSmartScan(forceLegacy: true)); }, child: Icon(Icons.sync, color: iconColor), ), @@ -336,8 +380,11 @@ class _ScanButton extends StatelessWidget { return _CircularPopupButton( tooltip: t.sendTab.scan, onSelected: (ip) async { - context.redux(nearbyDevicesProvider).dispatch(ClearFoundDevicesAction()); - await context.global.dispatchAsync(StartLegacySubnetScan(subnets: [ip])); + context + .redux(nearbyDevicesProvider) + .dispatch(ClearFoundDevicesAction()); + await context.global + .dispatchAsync(StartLegacySubnetScan(subnets: [ip])); }, itemBuilder: (_) { return [ @@ -378,7 +425,8 @@ class _RotatingSyncIcon extends StatelessWidget { @override Widget build(BuildContext context) { - final scanningIps = context.ref.watch(nearbyDevicesProvider.select((s) => s.runningIps)); + final scanningIps = + context.ref.watch(nearbyDevicesProvider.select((s) => s.runningIps)); return RotatingWidget( duration: const Duration(seconds: 2), spinning: scanningIps.contains(ip), @@ -409,7 +457,8 @@ class _SendModeButton extends StatelessWidget { onSelect(SendMode.link); break; case -1: - await showDialog(context: context, builder: (_) => const SendModeHelpDialog()); + await showDialog( + context: context, builder: (_) => const SendModeHelpDialog()); break; } }, @@ -421,7 +470,8 @@ class _SendModeButton extends StatelessWidget { children: [ Consumer( builder: (context, ref) { - final sendMode = ref.watch(settingsProvider.select((s) => s.sendMode)); + final sendMode = + ref.watch(settingsProvider.select((s) => s.sendMode)); return Visibility( visible: sendMode == SendMode.single, maintainSize: true, @@ -443,7 +493,8 @@ class _SendModeButton extends StatelessWidget { children: [ Consumer( builder: (context, ref) { - final sendMode = ref.watch(settingsProvider.select((s) => s.sendMode)); + final sendMode = + ref.watch(settingsProvider.select((s) => s.sendMode)); return Visibility( visible: sendMode == SendMode.multiple, maintainSize: true, @@ -516,14 +567,24 @@ class _MultiSendDeviceListTile extends StatelessWidget { @override Widget build(BuildContext context) { final ref = context.ref; - final session = ref.watch(sendProvider).values.firstWhereOrNull((s) => s.target.ip == device.ip); + final session = ref + .watch(sendProvider) + .values + .firstWhereOrNull((s) => s.target.ip == device.ip); final double? progress; if (session != null) { final files = session.files.values.where((f) => f.token != null); final progressNotifier = ref.watch(progressProvider); final currBytes = files.fold( - 0, (prev, curr) => prev + ((progressNotifier.getProgress(sessionId: session.sessionId, fileId: curr.file.id) * curr.file.size).round())); - final totalBytes = files.fold(0, (prev, curr) => prev + curr.file.size); + 0, + (prev, curr) => + prev + + ((progressNotifier.getProgress( + sessionId: session.sessionId, fileId: curr.file.id) * + curr.file.size) + .round())); + final totalBytes = + files.fold(0, (prev, curr) => prev + curr.file.size); progress = totalBytes == 0 ? 0 : currBytes / totalBytes; } else { progress = null; diff --git a/app/lib/provider/apk_provider.dart b/app/lib/provider/apk_provider.dart index 1269cd8b..c9dc0d12 100644 --- a/app/lib/provider/apk_provider.dart +++ b/app/lib/provider/apk_provider.dart @@ -6,10 +6,11 @@ import 'package:localsend_app/provider/param/cached_apk_provider_param.dart'; import 'package:refena_flutter/refena_flutter.dart'; final apkSearchParamProvider = StateProvider( - (ref) => const ApkProviderParam( + (ref) => ApkProviderParam( query: '', includeSystemApps: false, onlyAppsWithLaunchIntent: true, + selectMultipleApps: false, ), ); @@ -20,12 +21,17 @@ final apkProvider = ViewProvider>>((ref) { .watch(_apkProvider(CachedApkProviderParam( includeSystemApps: param.includeSystemApps, onlyAppsWithLaunchIntent: param.onlyAppsWithLaunchIntent, + selectMultipleApps: param.selectMultipleApps, ))) .maybeWhen( data: (apps) { final query = param.query.trim().toLowerCase(); if (query.isNotEmpty) { - apps = apps.where((a) => a.appName.toLowerCase().contains(query) || a.packageName.contains(query)).toList(); + apps = apps + .where((a) => + a.appName.toLowerCase().contains(query) || + a.packageName.contains(query)) + .toList(); } apps.sort((a, b) => a.appName.compareTo(b.appName)); @@ -40,7 +46,8 @@ final apkSizeProvider = FutureFamilyProvider((_, path) { }); /// Provides a list of APKs which is cached -final _apkProvider = FutureFamilyProvider, CachedApkProviderParam>((_, param) { +final _apkProvider = + FutureFamilyProvider, CachedApkProviderParam>((_, param) { return DeviceApps.getInstalledApplications( includeSystemApps: param.includeSystemApps, onlyAppsWithLaunchIntent: param.onlyAppsWithLaunchIntent, diff --git a/app/lib/provider/param/apk_provider_param.dart b/app/lib/provider/param/apk_provider_param.dart index c1b68ecb..5b7fe650 100644 --- a/app/lib/provider/param/apk_provider_param.dart +++ b/app/lib/provider/param/apk_provider_param.dart @@ -7,10 +7,12 @@ class ApkProviderParam with ApkProviderParamMappable { final String query; final bool includeSystemApps; final bool onlyAppsWithLaunchIntent; + bool selectMultipleApps; - const ApkProviderParam({ + ApkProviderParam({ required this.query, required this.includeSystemApps, required this.onlyAppsWithLaunchIntent, + this.selectMultipleApps = false, }); } diff --git a/app/lib/provider/param/apk_provider_param.mapper.dart b/app/lib/provider/param/apk_provider_param.mapper.dart index 9765a3dd..8f68af5c 100644 --- a/app/lib/provider/param/apk_provider_param.mapper.dart +++ b/app/lib/provider/param/apk_provider_param.mapper.dart @@ -21,11 +21,15 @@ class ApkProviderParamMapper extends ClassMapperBase { final String id = 'ApkProviderParam'; static String _$query(ApkProviderParam v) => v.query; - static const Field _f$query = Field('query', _$query); + static const Field _f$query = + Field('query', _$query); static bool _$includeSystemApps(ApkProviderParam v) => v.includeSystemApps; - static const Field _f$includeSystemApps = Field('includeSystemApps', _$includeSystemApps); - static bool _$onlyAppsWithLaunchIntent(ApkProviderParam v) => v.onlyAppsWithLaunchIntent; - static const Field _f$onlyAppsWithLaunchIntent = Field('onlyAppsWithLaunchIntent', _$onlyAppsWithLaunchIntent); + static const Field _f$includeSystemApps = + Field('includeSystemApps', _$includeSystemApps); + static bool _$onlyAppsWithLaunchIntent(ApkProviderParam v) => + v.onlyAppsWithLaunchIntent; + static const Field _f$onlyAppsWithLaunchIntent = + Field('onlyAppsWithLaunchIntent', _$onlyAppsWithLaunchIntent); @override final MappableFields fields = const { @@ -36,9 +40,10 @@ class ApkProviderParamMapper extends ClassMapperBase { static ApkProviderParam _instantiate(DecodingData data) { return ApkProviderParam( - query: data.dec(_f$query), - includeSystemApps: data.dec(_f$includeSystemApps), - onlyAppsWithLaunchIntent: data.dec(_f$onlyAppsWithLaunchIntent)); + query: data.dec(_f$query), + includeSystemApps: data.dec(_f$includeSystemApps), + onlyAppsWithLaunchIntent: data.dec(_f$onlyAppsWithLaunchIntent), + ); } @override @@ -55,58 +60,81 @@ class ApkProviderParamMapper extends ClassMapperBase { mixin ApkProviderParamMappable { String serialize() { - return ApkProviderParamMapper.ensureInitialized().encodeJson(this as ApkProviderParam); + return ApkProviderParamMapper.ensureInitialized() + .encodeJson(this as ApkProviderParam); } Map toJson() { - return ApkProviderParamMapper.ensureInitialized().encodeMap(this as ApkProviderParam); + return ApkProviderParamMapper.ensureInitialized() + .encodeMap(this as ApkProviderParam); } - ApkProviderParamCopyWith get copyWith => - _ApkProviderParamCopyWithImpl(this as ApkProviderParam, $identity, $identity); + ApkProviderParamCopyWith + get copyWith => _ApkProviderParamCopyWithImpl( + this as ApkProviderParam, $identity, $identity); @override String toString() { - return ApkProviderParamMapper.ensureInitialized().stringifyValue(this as ApkProviderParam); + return ApkProviderParamMapper.ensureInitialized() + .stringifyValue(this as ApkProviderParam); } @override bool operator ==(Object other) { - return ApkProviderParamMapper.ensureInitialized().equalsValue(this as ApkProviderParam, other); + return ApkProviderParamMapper.ensureInitialized() + .equalsValue(this as ApkProviderParam, other); } @override int get hashCode { - return ApkProviderParamMapper.ensureInitialized().hashValue(this as ApkProviderParam); + return ApkProviderParamMapper.ensureInitialized() + .hashValue(this as ApkProviderParam); } } -extension ApkProviderParamValueCopy<$R, $Out> on ObjectCopyWith<$R, ApkProviderParam, $Out> { - ApkProviderParamCopyWith<$R, ApkProviderParam, $Out> get $asApkProviderParam => $base.as((v, t, t2) => _ApkProviderParamCopyWithImpl(v, t, t2)); +extension ApkProviderParamValueCopy<$R, $Out> + on ObjectCopyWith<$R, ApkProviderParam, $Out> { + ApkProviderParamCopyWith<$R, ApkProviderParam, $Out> + get $asApkProviderParam => + $base.as((v, t, t2) => _ApkProviderParamCopyWithImpl(v, t, t2)); } -abstract class ApkProviderParamCopyWith<$R, $In extends ApkProviderParam, $Out> implements ClassCopyWith<$R, $In, $Out> { - $R call({String? query, bool? includeSystemApps, bool? onlyAppsWithLaunchIntent}); - ApkProviderParamCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +abstract class ApkProviderParamCopyWith<$R, $In extends ApkProviderParam, $Out> + implements ClassCopyWith<$R, $In, $Out> { + $R call( + {String? query, bool? includeSystemApps, bool? onlyAppsWithLaunchIntent}); + ApkProviderParamCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t); } -class _ApkProviderParamCopyWithImpl<$R, $Out> extends ClassCopyWithBase<$R, ApkProviderParam, $Out> +class _ApkProviderParamCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, ApkProviderParam, $Out> implements ApkProviderParamCopyWith<$R, ApkProviderParam, $Out> { _ApkProviderParamCopyWithImpl(super.value, super.then, super.then2); @override - late final ClassMapperBase $mapper = ApkProviderParamMapper.ensureInitialized(); + late final ClassMapperBase $mapper = + ApkProviderParamMapper.ensureInitialized(); @override - $R call({String? query, bool? includeSystemApps, bool? onlyAppsWithLaunchIntent}) => $apply(FieldCopyWithData({ + $R call( + {String? query, + bool? includeSystemApps, + bool? onlyAppsWithLaunchIntent}) => + $apply(FieldCopyWithData({ if (query != null) #query: query, if (includeSystemApps != null) #includeSystemApps: includeSystemApps, - if (onlyAppsWithLaunchIntent != null) #onlyAppsWithLaunchIntent: onlyAppsWithLaunchIntent + if (onlyAppsWithLaunchIntent != null) + #onlyAppsWithLaunchIntent: onlyAppsWithLaunchIntent })); @override ApkProviderParam $make(CopyWithData data) => ApkProviderParam( query: data.get(#query, or: $value.query), - includeSystemApps: data.get(#includeSystemApps, or: $value.includeSystemApps), - onlyAppsWithLaunchIntent: data.get(#onlyAppsWithLaunchIntent, or: $value.onlyAppsWithLaunchIntent)); + includeSystemApps: + data.get(#includeSystemApps, or: $value.includeSystemApps), + onlyAppsWithLaunchIntent: data.get(#onlyAppsWithLaunchIntent, + or: $value.onlyAppsWithLaunchIntent)); @override - ApkProviderParamCopyWith<$R2, ApkProviderParam, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t) => _ApkProviderParamCopyWithImpl($value, $cast, t); + ApkProviderParamCopyWith<$R2, ApkProviderParam, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t) => + _ApkProviderParamCopyWithImpl($value, $cast, t); } diff --git a/app/lib/provider/param/cached_apk_provider_param.dart b/app/lib/provider/param/cached_apk_provider_param.dart index 527c48a2..2a9bfd83 100644 --- a/app/lib/provider/param/cached_apk_provider_param.dart +++ b/app/lib/provider/param/cached_apk_provider_param.dart @@ -6,9 +6,11 @@ part 'cached_apk_provider_param.mapper.dart'; class CachedApkProviderParam with CachedApkProviderParamMappable { final bool includeSystemApps; final bool onlyAppsWithLaunchIntent; + bool selectMultipleApps; - const CachedApkProviderParam({ + CachedApkProviderParam({ required this.includeSystemApps, required this.onlyAppsWithLaunchIntent, + this.selectMultipleApps = false, }); } diff --git a/app/pubspec.lock b/app/pubspec.lock index f7abd115..7698be13 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -377,10 +377,10 @@ packages: dependency: transitive description: name: extended_image - sha256: "8ad4917eaae7271ce6d975d5c0040c7903010262908fbdb49ff2798fca754d3b" + sha256: "69d4299043334ecece679996e47d0b0891cd8c29d8da0034868443506f1d9a78" url: "https://pub.dev" source: hosted - version: "8.3.0" + version: "8.3.1" extended_image_library: dependency: transitive description: @@ -433,34 +433,34 @@ packages: dependency: transitive description: name: file_selector_android - sha256: b8c9717a0177ca6fa035554b82cd6c83b838ddc66b7704eb6df0f77f027ecc90 + sha256: "00aafa9ae05a8663d0b4f17abd2a02316911ca0f46f9b9dacb9578b324d99590" url: "https://pub.dev" source: hosted - version: "0.5.1+7" + version: "0.5.1+9" file_selector_ios: dependency: transitive description: name: file_selector_ios - sha256: "38ebf91ecbcfa89a9639a0854ccaed8ab370c75678938eebca7d34184296f0bb" + sha256: "94b98ad950b8d40d96fee8fa88640c2e4bd8afcdd4817993bd04e20310f45420" url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.3+1" file_selector_linux: dependency: transitive description: name: file_selector_linux - sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + sha256: "712ce7fab537ba532c8febdb1a8f167b32441e74acd68c3ccb2e36dcb52c4ab2" url: "https://pub.dev" source: hosted - version: "0.9.2+1" + version: "0.9.3" file_selector_macos: dependency: transitive description: name: file_selector_macos - sha256: cb284e267f8e2a45a904b5c094d2ba51d0aabfc20b1538ab786d9ef7dc2bf75c + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" url: "https://pub.dev" source: hosted - version: "0.9.4+1" + version: "0.9.4+2" file_selector_platform_interface: dependency: transitive description: @@ -481,10 +481,10 @@ packages: dependency: transitive description: name: file_selector_windows - sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" + sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4" url: "https://pub.dev" source: hosted - version: "0.9.3+2" + version: "0.9.3+3" fixnum: dependency: transitive description: @@ -547,10 +547,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" + sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.0.23" flutter_test: dependency: transitive description: flutter @@ -677,10 +677,10 @@ packages: dependency: transitive description: name: image_picker_android - sha256: c0a6763d50b354793d0192afd0a12560b823147d3ded7c6b77daf658fa05cc85 + sha256: d3e5e00fdfeca8fd4ffb3227001264d449cc8950414c2ff70b0e06b9c628e643 url: "https://pub.dev" source: hosted - version: "0.8.12+13" + version: "0.8.12+15" image_picker_for_web: dependency: transitive description: @@ -733,10 +733,10 @@ packages: dependency: transitive description: name: image_size_getter - sha256: f98c4246144e9b968899d2dfde69091e22a539bb64bc9b0bea51505fbb490e57 + sha256: "0511799498340b70993d2dfb34b55a2247b5b801d75a6cdd4543acfcafdb12b0" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.0" in_app_purchase: dependency: "direct main" description: @@ -749,10 +749,10 @@ packages: dependency: transitive description: name: in_app_purchase_android - sha256: "25eb8694819caca282a527c26d5a1775164965c554ee99b9c10f3a0e44675c75" + sha256: bee60266e443d4ae0e4809bae7f9cd4d6be75ab5ec6bb3d2ca737774a274a3bd url: "https://pub.dev" source: hosted - version: "0.3.6+8" + version: "0.3.6+9" in_app_purchase_platform_interface: dependency: transitive description: @@ -1038,10 +1038,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.12" path_provider_foundation: dependency: transitive description: @@ -1327,18 +1327,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.3" shared_preferences_linux: dependency: transitive description: @@ -1628,10 +1628,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab + sha256: "8fc3bae0b68c02c47c5c86fa8bfa74471d42687b0eded01b78de87872db745e2" url: "https://pub.dev" source: hosted - version: "6.3.10" + version: "6.3.12" url_launcher_ios: dependency: transitive description: @@ -1716,34 +1716,34 @@ packages: dependency: transitive description: name: video_player - sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d + sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17" url: "https://pub.dev" source: hosted - version: "2.9.1" + version: "2.9.2" video_player_android: dependency: transitive description: name: video_player_android - sha256: "38d8fe136c427abdce68b5e8c3c08ea29d7a794b453c7a51b12ecfad4aad9437" + sha256: ae5287ca367e206eb74d7b3dc1ce0b8912ab9a3fc0597b6a101a0a5239f229d3 url: "https://pub.dev" source: hosted - version: "2.7.3" + version: "2.7.9" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c + sha256: cd5ab8a8bc0eab65ab0cea40304097edc46da574c8c1ecdee96f28cd8ef3792f url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "2.6.2" video_player_platform_interface: dependency: transitive description: name: video_player_platform_interface - sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6" + sha256: "229d7642ccd9f3dc4aba169609dd6b5f3f443bb4cc15b82f7785fcada5af9bbb" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.2.3" video_player_web: dependency: transitive description: @@ -1836,10 +1836,10 @@ packages: dependency: transitive description: name: win32 - sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a" + sha256: "4d45dc9069dba4619dc0ebd93c7cec5e66d8482cb625a370ac806dcc8165f2ec" url: "https://pub.dev" source: hosted - version: "5.5.4" + version: "5.5.5" win32_registry: dependency: "direct main" description: @@ -1868,10 +1868,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" xml: dependency: transitive description: diff --git a/cli/pubspec.lock b/cli/pubspec.lock index b451e849..493abda4 100644 --- a/cli/pubspec.lock +++ b/cli/pubspec.lock @@ -5,18 +5,23 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77" url: "https://pub.dev" source: hosted - version: "64.0.0" + version: "73.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.2" analyzer: dependency: transitive description: name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.8.0" args: dependency: "direct main" description: @@ -45,10 +50,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" common: dependency: "direct main" description: @@ -68,18 +73,18 @@ packages: dependency: transitive description: name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + sha256: c1fb2dce3c0085f39dc72668e85f8e0210ec7de05345821ff58530567df345a5 url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.9.2" crypto: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" dart_mappable: dependency: transitive description: @@ -116,10 +121,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" glob: dependency: transitive description: @@ -140,10 +145,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.0" io: dependency: transitive description: @@ -156,10 +161,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" lints: dependency: "direct dev" description: @@ -176,30 +181,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + macros: + dependency: transitive + description: + name: macros + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + url: "https://pub.dev" + source: hosted + version: "0.1.2-main.4" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.16.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.6" node_preamble: dependency: transitive description: @@ -244,18 +257,18 @@ packages: dependency: transitive description: name: refena - sha256: "04ef88e22bee3f6735a9e11d81f41c8cf00bd264c396214945156b9858b07619" + sha256: "1446e9622451e0cffef2af5b3fd57a52f0688d7c9eb848e969c16ccc2d14e833" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" shelf: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" shelf_packages_handler: dependency: transitive description: @@ -268,26 +281,26 @@ packages: dependency: transitive description: name: shelf_static - sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.3" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.0.0" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace - sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" source_maps: dependency: transitive description: @@ -308,10 +321,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -324,10 +337,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" term_glyph: dependency: transitive description: @@ -340,26 +353,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9" + sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" url: "https://pub.dev" source: hosted - version: "1.24.6" + version: "1.25.8" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.3" test_core: dependency: transitive description: name: test_core - sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265" + sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" url: "https://pub.dev" source: hosted - version: "0.5.6" + version: "0.6.5" type_plus: dependency: transitive description: @@ -380,10 +393,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "11.10.0" + version: "14.3.0" watcher: dependency: transitive description: @@ -400,14 +413,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "3.0.1" webkit_inspection_protocol: dependency: transitive description: @@ -425,4 +446,4 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.1 <4.0.0" + dart: ">=3.4.0 <4.0.0"