diff --git a/lib/core/configuration.dart b/lib/core/configuration.dart index a39052e65..0717e4b46 100644 --- a/lib/core/configuration.dart +++ b/lib/core/configuration.dart @@ -45,7 +45,7 @@ class Configuration { final List onlineSecureKeys = [ keyKey, secretKeyKey, - authSecretKeyKey + authSecretKeyKey, ]; final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds; diff --git a/lib/core/logging/tunneled_transport.dart b/lib/core/logging/tunneled_transport.dart index 9706f72fd..daf8a7941 100644 --- a/lib/core/logging/tunneled_transport.dart +++ b/lib/core/logging/tunneled_transport.dart @@ -122,7 +122,7 @@ class _CredentialBuilder { return headers ..addAll( { - 'X-Sentry-Auth': '$_authHeader, sentry_timestamp=$timestamp' + 'X-Sentry-Auth': '$_authHeader, sentry_timestamp=$timestamp', }, ); } diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index e5cc9b7ab..b572856ed 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -332,5 +332,6 @@ "showLargeIcons": "Show large icons", "shouldHideCode": "Hide codes", "focusOnSearchBar": "Focus search on app start", - "confirmUpdatingkey": "Are you sure you want to update the secret key?" + "confirmUpdatingkey": "Are you sure you want to update the secret key?", + "minimizeAppOnCopy": "Minimize app on copy" } diff --git a/lib/locale.dart b/lib/locale.dart index c45f38d75..ebca9528a 100644 --- a/lib/locale.dart +++ b/lib/locale.dart @@ -24,7 +24,7 @@ Locale localResolutionCallBack(locales, supportedLocales) { Locale? languageCodeMatch; final Map languageCodeToLocale = { for (Locale supportedLocale in appSupportedLocales) - supportedLocale.languageCode: supportedLocale + supportedLocale.languageCode: supportedLocale, }; for (Locale locale in locales) { diff --git a/lib/onboarding/view/view_qr_page.dart b/lib/onboarding/view/view_qr_page.dart index 9b29b457e..71f4756a7 100644 --- a/lib/onboarding/view/view_qr_page.dart +++ b/lib/onboarding/view/view_qr_page.dart @@ -89,7 +89,7 @@ class ViewQrPage extends StatelessWidget { child: Text(l10n.back), ), ), - ) + ), ], ), ), diff --git a/lib/services/preference_service.dart b/lib/services/preference_service.dart index cad38143d..66d96c7fd 100644 --- a/lib/services/preference_service.dart +++ b/lib/services/preference_service.dart @@ -13,6 +13,7 @@ class PreferenceService { static const kShouldShowLargeIconsKey = "should_show_large_icons"; static const kShouldHideCodesKey = "should_hide_codes"; static const kShouldAutoFocusOnSearchBar = "should_auto_focus_on_search_bar"; + static const kShouldMinimizeOnCopy = "should_minimize_on_copy"; Future init() async { _prefs = await SharedPreferences.getInstance(); @@ -64,4 +65,16 @@ class PreferenceService { await _prefs.setBool(kShouldAutoFocusOnSearchBar, value); Bus.instance.fire(IconsChangedEvent()); } + + bool shouldMinimizeOnCopy() { + if (_prefs.containsKey(kShouldMinimizeOnCopy)) { + return _prefs.getBool(kShouldMinimizeOnCopy)!; + } else { + return false; + } + } + + Future setShouldMinimizeOnCopy(bool value) async { + await _prefs.setBool(kShouldMinimizeOnCopy, value); + } } diff --git a/lib/ui/account/email_entry_page.dart b/lib/ui/account/email_entry_page.dart index f84b68cfe..e1147f416 100644 --- a/lib/ui/account/email_entry_page.dart +++ b/lib/ui/account/email_entry_page.dart @@ -403,7 +403,7 @@ class _EmailEntryPageState extends State { style: const TextStyle( decoration: TextDecoration.underline, ), - ) + ), }, ), ), diff --git a/lib/ui/account/login_page.dart b/lib/ui/account/login_page.dart index a2f9414a2..b2cfce745 100644 --- a/lib/ui/account/login_page.dart +++ b/lib/ui/account/login_page.dart @@ -204,14 +204,14 @@ class _LoginPageState extends State { style: const TextStyle( decoration: TextDecoration.underline, ), - ) + ), }, ), ), Expanded( flex: 2, child: Container(), - ) + ), ], ), ), diff --git a/lib/ui/account/login_pwd_verification_page.dart b/lib/ui/account/login_pwd_verification_page.dart index 0755be1b1..a443cf249 100644 --- a/lib/ui/account/login_pwd_verification_page.dart +++ b/lib/ui/account/login_pwd_verification_page.dart @@ -221,7 +221,7 @@ State { ), ], ), - ) + ), ], ), ), diff --git a/lib/ui/account/ott_verification_page.dart b/lib/ui/account/ott_verification_page.dart index ce7b8ea35..8bcaf3e34 100644 --- a/lib/ui/account/ott_verification_page.dart +++ b/lib/ui/account/ott_verification_page.dart @@ -152,7 +152,7 @@ class _OTTVerificationPageState extends State { SizedBox( width: MediaQuery.of(context).size.width * 0.2, height: 1, - ) + ), ], ), ), @@ -203,7 +203,7 @@ class _OTTVerificationPageState extends State { decoration: TextDecoration.underline, ), ), - ) + ), ], ), ), diff --git a/lib/ui/account/password_reentry_page.dart b/lib/ui/account/password_reentry_page.dart index c8fc23a67..aab2553eb 100644 --- a/lib/ui/account/password_reentry_page.dart +++ b/lib/ui/account/password_reentry_page.dart @@ -310,7 +310,7 @@ class _PasswordReentryPageState extends State { ), ], ), - ) + ), ], ), ), diff --git a/lib/ui/account/recovery_key_page.dart b/lib/ui/account/recovery_key_page.dart index bbe08b7e5..c5ca66fdc 100644 --- a/lib/ui/account/recovery_key_page.dart +++ b/lib/ui/account/recovery_key_page.dart @@ -191,7 +191,7 @@ class _RecoveryKeyPageState extends State { children: _saveOptions(context, recoveryKey), ), ), - ) + ), ], ), // columnEnds ), diff --git a/lib/ui/account/verify_recovery_page.dart b/lib/ui/account/verify_recovery_page.dart index 3c9796d10..dad67590b 100644 --- a/lib/ui/account/verify_recovery_page.dart +++ b/lib/ui/account/verify_recovery_page.dart @@ -196,7 +196,7 @@ class _VerifyRecoveryPageState extends State { ), ), ), - const SizedBox(height: 20) + const SizedBox(height: 20), ], ), ), diff --git a/lib/ui/code_widget.dart b/lib/ui/code_widget.dart index b3f240224..a26cc20b2 100644 --- a/lib/ui/code_widget.dart +++ b/lib/ui/code_widget.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:io'; import 'package:clipboard/clipboard.dart'; import 'package:ente_auth/core/configuration.dart'; @@ -17,6 +18,7 @@ import 'package:ente_auth/utils/totp_util.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:logging/logging.dart'; +import 'package:move_to_background/move_to_background.dart'; class CodeWidget extends StatefulWidget { final Code code; @@ -141,7 +143,7 @@ class _CodeWidgetState extends State { borderRadius: BorderRadius.circular(10), ), onTap: () { - _copyToClipboard(); + _copyCurrentOTPToClipboard(); }, onDoubleTap: isMaskingEnabled ? () { @@ -153,7 +155,7 @@ class _CodeWidgetState extends State { } : null, onLongPress: () { - _copyToClipboard(); + _copyCurrentOTPToClipboard(); }, child: _getCardContents(l10n), ), @@ -328,17 +330,34 @@ class _CodeWidgetState extends State { ); } - void _copyToClipboard() { - FlutterClipboard.copy(_getCurrentOTP()) - .then((value) => showToast(context, context.l10n.copiedToClipboard)); + void _copyCurrentOTPToClipboard() async { + _copyToClipboard( + _getCurrentOTP(), + confirmationMessage: context.l10n.copiedToClipboard, + ); } void _copyNextToClipboard() { - FlutterClipboard.copy(_getNextTotp()).then( - (value) => showToast(context, context.l10n.copiedNextToClipboard), + _copyToClipboard( + _getNextTotp(), + confirmationMessage: context.l10n.copiedNextToClipboard, ); } + void _copyToClipboard( + String content, { + required String confirmationMessage, + }) async { + final shouldMinimizeOnCopy = + PreferenceService.instance.shouldMinimizeOnCopy(); + + await FlutterClipboard.copy(content); + showToast(context, confirmationMessage); + if (Platform.isAndroid && shouldMinimizeOnCopy) { + MoveToBackground.moveTaskToBack(); + } + } + void _onNextHotpTapped() { if (widget.code.type == Type.hotp) { CodeStore.instance diff --git a/lib/ui/common/dynamic_fab.dart b/lib/ui/common/dynamic_fab.dart index 0fedcff94..db612882a 100644 --- a/lib/ui/common/dynamic_fab.dart +++ b/lib/ui/common/dynamic_fab.dart @@ -30,7 +30,7 @@ class DynamicFAB extends StatelessWidget { spreadRadius: 200, blurRadius: 100, offset: const Offset(0, 230), - ) + ), ], ), width: double.infinity, diff --git a/lib/ui/common/progress_dialog.dart b/lib/ui/common/progress_dialog.dart index a05f031e6..8c9a4e1f1 100644 --- a/lib/ui/common/progress_dialog.dart +++ b/lib/ui/common/progress_dialog.dart @@ -277,7 +277,7 @@ class _BodyState extends State<_Body> { _direction == TextDirection.ltr ? loader : text, const SizedBox(width: 8.0), _direction == TextDirection.rtl ? loader : text, - const SizedBox(width: 8.0) + const SizedBox(width: 8.0), ], ), ], diff --git a/lib/ui/components/buttons/button_widget.dart b/lib/ui/components/buttons/button_widget.dart index 36f79a364..28d62f4a6 100644 --- a/lib/ui/components/buttons/button_widget.dart +++ b/lib/ui/components/buttons/button_widget.dart @@ -308,7 +308,7 @@ class _ButtonChildWidgetState extends State { overflow: TextOverflow.ellipsis, ), ), - ) + ), ], ); }, diff --git a/lib/ui/components/captioned_text_widget.dart b/lib/ui/components/captioned_text_widget.dart index 77a161bde..f03c8551f 100644 --- a/lib/ui/components/captioned_text_widget.dart +++ b/lib/ui/components/captioned_text_widget.dart @@ -48,7 +48,7 @@ class CaptionedTextWidget extends StatelessWidget { ], ), ), - ) + ), ], ), ), diff --git a/lib/ui/components/dialog_widget.dart b/lib/ui/components/dialog_widget.dart index 02311fc53..ab96a0dbe 100644 --- a/lib/ui/components/dialog_widget.dart +++ b/lib/ui/components/dialog_widget.dart @@ -280,7 +280,7 @@ class _TextInputDialogState extends State { ), ), ], - ) + ), ], ), ), diff --git a/lib/ui/components/title_bar_widget.dart b/lib/ui/components/title_bar_widget.dart index 6ee76e1a0..8e22d4f65 100644 --- a/lib/ui/components/title_bar_widget.dart +++ b/lib/ui/components/title_bar_widget.dart @@ -61,7 +61,7 @@ class TitleBarWidget extends StatelessWidget { : Text( caption!, style: textTheme.mini.copyWith(color: colorTheme.textMuted), - ) + ), ], ), ), @@ -112,7 +112,7 @@ class TitleBarWidget extends StatelessWidget { ), overflow: TextOverflow.ellipsis, maxLines: 1, - ) + ), ], ), ), diff --git a/lib/ui/home/coach_mark_widget.dart b/lib/ui/home/coach_mark_widget.dart index 9b4b8b48c..b0e15d7d2 100644 --- a/lib/ui/home/coach_mark_widget.dart +++ b/lib/ui/home/coach_mark_widget.dart @@ -56,7 +56,7 @@ class CoachMarkWidget extends StatelessWidget { }, child: Text(l10n.ok), ), - ) + ), ], ), ], diff --git a/lib/ui/scanner_gauth_page.dart b/lib/ui/scanner_gauth_page.dart index 41909ed32..785f1d3d3 100644 --- a/lib/ui/scanner_gauth_page.dart +++ b/lib/ui/scanner_gauth_page.dart @@ -46,7 +46,8 @@ class ScannerGoogleAuthPageState extends State { child: QRView( key: qrKey, overlay: QrScannerOverlayShape( - borderColor: getEnteColorScheme(context).primary700,), + borderColor: getEnteColorScheme(context).primary700, + ), onQRViewCreated: _onQRViewCreated, formatsAllowed: const [BarcodeFormat.qrcode], ), @@ -56,7 +57,7 @@ class ScannerGoogleAuthPageState extends State { child: Center( child: (totp != null) ? Text(totp!) : Text(l10n.scanACode), ), - ) + ), ], ), ); diff --git a/lib/ui/scanner_page.dart b/lib/ui/scanner_page.dart index 97ff1278a..0159f0cfa 100644 --- a/lib/ui/scanner_page.dart +++ b/lib/ui/scanner_page.dart @@ -51,7 +51,7 @@ class ScannerPageState extends State { child: Center( child: (totp != null) ? Text(totp!) : Text(l10n.scanACode), ), - ) + ), ], ), ); diff --git a/lib/ui/settings/faq.dart b/lib/ui/settings/faq.dart index 3d5c78ab8..d9aa88f1b 100644 --- a/lib/ui/settings/faq.dart +++ b/lib/ui/settings/faq.dart @@ -95,7 +95,7 @@ class FaqWidget extends StatelessWidget { ), ), ), - ) + ), ], ), ); diff --git a/lib/ui/settings/general_section_widget.dart b/lib/ui/settings/general_section_widget.dart index 428e76357..986ef3a8e 100644 --- a/lib/ui/settings/general_section_widget.dart +++ b/lib/ui/settings/general_section_widget.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:ente_auth/app/view/app.dart'; import 'package:ente_auth/core/logging/super_logging.dart'; import 'package:ente_auth/l10n/l10n.dart'; @@ -120,6 +122,23 @@ class _AdvancedSectionWidgetState extends State { ), ), sectionOptionSpacing, + if (Platform.isAndroid) ...[ + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: l10n.minimizeAppOnCopy, + ), + trailingWidget: ToggleSwitchWidget( + value: () => PreferenceService.instance.shouldMinimizeOnCopy(), + onChanged: () async { + await PreferenceService.instance.setShouldMinimizeOnCopy( + !PreferenceService.instance.shouldMinimizeOnCopy(), + ); + setState(() {}); + }, + ), + ), + sectionOptionSpacing, + ], ], ); } diff --git a/lib/utils/device_info.dart b/lib/utils/device_info.dart index 10ca82c2a..5832ec6de 100644 --- a/lib/utils/device_info.dart +++ b/lib/utils/device_info.dart @@ -27,7 +27,7 @@ late Set iOSLowEndMachineCodes = { "iPhone10,2", // iPhone 8 Plus "iPhone10,3", // iPhone X Global "iPhone10,4", // iPhone 8 - "iPhone10,5" // iPhone 8 + "iPhone10,5", // iPhone 8 }; Future isLowSpecDevice() async { diff --git a/lib/utils/email_util.dart b/lib/utils/email_util.dart index cdbbfda12..d1ae18395 100644 --- a/lib/utils/email_util.dart +++ b/lib/utils/email_util.dart @@ -277,7 +277,7 @@ void _showNoMailAppsDialog(BuildContext context, String toEmail) { onPressed: () { Navigator.pop(context); }, - ) + ), ], ); },