diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 57bc8ca00..326971550 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -330,5 +330,6 @@ "sigInBackupReminder": "Please export your codes to ensure that you have a backup you can restore from.", "offlineModeWarning": "You have chosen to proceed without backups. Please take manual backups to make sure your codes are safe.", "showLargeIcons": "Show large icons", + "shouldHideCode": "Hide codes", "focusOnSearchBar": "Focus search on app start" } diff --git a/lib/services/preference_service.dart b/lib/services/preference_service.dart index 57bfbefc6..cad38143d 100644 --- a/lib/services/preference_service.dart +++ b/lib/services/preference_service.dart @@ -11,6 +11,7 @@ class PreferenceService { static const kHasShownCoachMarkKey = "has_shown_coach_mark"; static const kShouldShowLargeIconsKey = "should_show_large_icons"; + static const kShouldHideCodesKey = "should_hide_codes"; static const kShouldAutoFocusOnSearchBar = "should_auto_focus_on_search_bar"; Future init() async { @@ -42,6 +43,15 @@ class PreferenceService { Bus.instance.fire(IconsChangedEvent()); } + bool shouldHideCodes() { + return _prefs.getBool(kShouldHideCodesKey) ?? false; + } + + Future setHideCodes(bool value) async { + await _prefs.setBool(kShouldHideCodesKey, value); + Bus.instance.fire(IconsChangedEvent()); + } + bool shouldAutoFocusOnSearchBar() { if (_prefs.containsKey(kShouldAutoFocusOnSearchBar)) { return _prefs.getBool(kShouldAutoFocusOnSearchBar)!; diff --git a/lib/ui/code_widget.dart b/lib/ui/code_widget.dart index d2a32ee4e..b3f240224 100644 --- a/lib/ui/code_widget.dart +++ b/lib/ui/code_widget.dart @@ -35,11 +35,14 @@ class _CodeWidgetState extends State { bool _isInitialized = false; late bool hasConfiguredAccount; late bool _shouldShowLargeIcon; + late bool _hideCode; + bool isMaskingEnabled = false; @override void initState() { super.initState(); - + isMaskingEnabled = PreferenceService.instance.shouldHideCodes(); + _hideCode = isMaskingEnabled; _everySecondTimer = Timer.periodic(const Duration(milliseconds: 500), (Timer t) { String newCode = _getCurrentOTP(); @@ -63,6 +66,10 @@ class _CodeWidgetState extends State { @override Widget build(BuildContext context) { + if (isMaskingEnabled != PreferenceService.instance.shouldHideCodes()) { + isMaskingEnabled = PreferenceService.instance.shouldHideCodes(); + _hideCode = isMaskingEnabled; + } _shouldShowLargeIcon = PreferenceService.instance.shouldShowLargeIcons(); if (!_isInitialized) { _currentCode.value = _getCurrentOTP(); @@ -136,6 +143,15 @@ class _CodeWidgetState extends State { onTap: () { _copyToClipboard(); }, + onDoubleTap: isMaskingEnabled + ? () { + setState( + () { + _hideCode = !_hideCode; + }, + ); + } + : null, onLongPress: () { _copyToClipboard(); }, @@ -390,6 +406,10 @@ class _CodeWidgetState extends State { } String _getFormattedCode(String code) { + if (_hideCode) { + // replace all digits with • + code = code.replaceAll(RegExp(r'\d'), '•'); + } if (code.length == 6) { return code.substring(0, 3) + " " + code.substring(3, 6); } diff --git a/lib/ui/settings/general_section_widget.dart b/lib/ui/settings/general_section_widget.dart index 63338e1e9..428e76357 100644 --- a/lib/ui/settings/general_section_widget.dart +++ b/lib/ui/settings/general_section_widget.dart @@ -74,6 +74,21 @@ class _AdvancedSectionWidgetState extends State { ), ), sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: l10n.shouldHideCode, + ), + trailingWidget: ToggleSwitchWidget( + value: () => PreferenceService.instance.shouldHideCodes(), + onChanged: () async { + await PreferenceService.instance.setHideCodes( + !PreferenceService.instance.shouldHideCodes(), + ); + setState(() {}); + }, + ), + ), + sectionOptionSpacing, MenuItemWidget( captionedTextWidget: CaptionedTextWidget( title: l10n.focusOnSearchBar, diff --git a/pubspec.yaml b/pubspec.yaml index bf70f5e16..20a06144e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: ente_auth description: ente two-factor authenticator -version: 2.0.4+204 +version: 2.0.5+205 publish_to: none environment: