feature/264 - Add clipboard minimize (#273)
This commit is contained in:
commit
a5a287912b
27 changed files with 88 additions and 35 deletions
|
@ -45,7 +45,7 @@ class Configuration {
|
|||
final List<String> onlineSecureKeys = [
|
||||
keyKey,
|
||||
secretKeyKey,
|
||||
authSecretKeyKey
|
||||
authSecretKeyKey,
|
||||
];
|
||||
|
||||
final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds;
|
||||
|
|
|
@ -122,7 +122,7 @@ class _CredentialBuilder {
|
|||
return headers
|
||||
..addAll(
|
||||
<String, String>{
|
||||
'X-Sentry-Auth': '$_authHeader, sentry_timestamp=$timestamp'
|
||||
'X-Sentry-Auth': '$_authHeader, sentry_timestamp=$timestamp',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Locale localResolutionCallBack(locales, supportedLocales) {
|
|||
Locale? languageCodeMatch;
|
||||
final Map<String, Locale> languageCodeToLocale = {
|
||||
for (Locale supportedLocale in appSupportedLocales)
|
||||
supportedLocale.languageCode: supportedLocale
|
||||
supportedLocale.languageCode: supportedLocale,
|
||||
};
|
||||
|
||||
for (Locale locale in locales) {
|
||||
|
|
|
@ -89,7 +89,7 @@ class ViewQrPage extends StatelessWidget {
|
|||
child: Text(l10n.back),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<void> 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<void> setShouldMinimizeOnCopy(bool value) async {
|
||||
await _prefs.setBool(kShouldMinimizeOnCopy, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
)
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -204,14 +204,14 @@ class _LoginPageState extends State<LoginPage> {
|
|||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
)
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Container(),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -221,7 +221,7 @@ State<LoginPasswordVerificationPage> {
|
|||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -152,7 +152,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
height: 1,
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -203,7 +203,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -310,7 +310,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -191,7 +191,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
children: _saveOptions(context, recoveryKey),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
), // columnEnds
|
||||
),
|
||||
|
|
|
@ -196,7 +196,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20)
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<CodeWidget> {
|
|||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
onTap: () {
|
||||
_copyToClipboard();
|
||||
_copyCurrentOTPToClipboard();
|
||||
},
|
||||
onDoubleTap: isMaskingEnabled
|
||||
? () {
|
||||
|
@ -153,7 +155,7 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
}
|
||||
: null,
|
||||
onLongPress: () {
|
||||
_copyToClipboard();
|
||||
_copyCurrentOTPToClipboard();
|
||||
},
|
||||
child: _getCardContents(l10n),
|
||||
),
|
||||
|
@ -328,17 +330,34 @@ class _CodeWidgetState extends State<CodeWidget> {
|
|||
);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -30,7 +30,7 @@ class DynamicFAB extends StatelessWidget {
|
|||
spreadRadius: 200,
|
||||
blurRadius: 100,
|
||||
offset: const Offset(0, 230),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
width: double.infinity,
|
||||
|
|
|
@ -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),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
@ -308,7 +308,7 @@ class _ButtonChildWidgetState extends State<ButtonChildWidget> {
|
|||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
|
@ -48,7 +48,7 @@ class CaptionedTextWidget extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -280,7 +280,7 @@ class _TextInputDialogState extends State<TextInputDialog> {
|
|||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -56,7 +56,7 @@ class CoachMarkWidget extends StatelessWidget {
|
|||
},
|
||||
child: Text(l10n.ok),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
@ -46,7 +46,8 @@ class ScannerGoogleAuthPageState extends State<ScannerGoogleAuthPage> {
|
|||
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<ScannerGoogleAuthPage> {
|
|||
child: Center(
|
||||
child: (totp != null) ? Text(totp!) : Text(l10n.scanACode),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -51,7 +51,7 @@ class ScannerPageState extends State<ScannerPage> {
|
|||
child: Center(
|
||||
child: (totp != null) ? Text(totp!) : Text(l10n.scanACode),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -95,7 +95,7 @@ class FaqWidget extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -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<AdvancedSectionWidget> {
|
|||
),
|
||||
),
|
||||
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,
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ late Set<String> iOSLowEndMachineCodes = <String>{
|
|||
"iPhone10,2", // iPhone 8 Plus
|
||||
"iPhone10,3", // iPhone X Global
|
||||
"iPhone10,4", // iPhone 8
|
||||
"iPhone10,5" // iPhone 8
|
||||
"iPhone10,5", // iPhone 8
|
||||
};
|
||||
|
||||
Future<bool> isLowSpecDevice() async {
|
||||
|
|
|
@ -277,7 +277,7 @@ void _showNoMailAppsDialog(BuildContext context, String toEmail) {
|
|||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue