From 3bb9790229a7835d6ec92f796eb65749f956684c Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:27:26 +0530 Subject: [PATCH] [auth][mob] Add compact mode --- auth/lib/l10n/arb/app_en.arb | 1 + auth/lib/services/preference_service.dart | 9 +++ auth/lib/store/code_store.dart | 3 + auth/lib/ui/code_timer_progress.dart | 5 +- auth/lib/ui/code_widget.dart | 70 ++++++++++++------- auth/lib/ui/home_page.dart | 4 ++ .../ui/settings/general_section_widget.dart | 20 +++++- 7 files changed, 83 insertions(+), 29 deletions(-) diff --git a/auth/lib/l10n/arb/app_en.arb b/auth/lib/l10n/arb/app_en.arb index 4229d3d9aa..148f386d7f 100644 --- a/auth/lib/l10n/arb/app_en.arb +++ b/auth/lib/l10n/arb/app_en.arb @@ -364,6 +364,7 @@ "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", + "compactMode": "Compact mode", "shouldHideCode": "Hide codes", "doubleTapToViewHiddenCode": "You can double tap on an entry to view code", "focusOnSearchBar": "Focus search on app start", diff --git a/auth/lib/services/preference_service.dart b/auth/lib/services/preference_service.dart index 66d96c7fdd..6da91465ea 100644 --- a/auth/lib/services/preference_service.dart +++ b/auth/lib/services/preference_service.dart @@ -14,6 +14,7 @@ class PreferenceService { static const kShouldHideCodesKey = "should_hide_codes"; static const kShouldAutoFocusOnSearchBar = "should_auto_focus_on_search_bar"; static const kShouldMinimizeOnCopy = "should_minimize_on_copy"; + static const kCompactMode = "vi.compactMode"; Future init() async { _prefs = await SharedPreferences.getInstance(); @@ -48,6 +49,14 @@ class PreferenceService { return _prefs.getBool(kShouldHideCodesKey) ?? false; } + bool isCompactMode() { + return _prefs.getBool(kCompactMode) ?? false; + } + + Future setCompactMode(bool value) async { + await _prefs.setBool(kCompactMode, value); + } + Future setHideCodes(bool value) async { await _prefs.setBool(kShouldHideCodesKey, value); Bus.instance.fire(IconsChangedEvent()); diff --git a/auth/lib/store/code_store.dart b/auth/lib/store/code_store.dart index 449bb93166..eb0906d976 100644 --- a/auth/lib/store/code_store.dart +++ b/auth/lib/store/code_store.dart @@ -48,6 +48,9 @@ class CodeStore { code.generatedID = entity.generatedID; code.hasSynced = entity.hasSynced; codes.add(code); + codes.add(code); + codes.add(code); + codes.add(code); } if (sortCodes) { diff --git a/auth/lib/ui/code_timer_progress.dart b/auth/lib/ui/code_timer_progress.dart index a825a6ca43..e594e15fb1 100644 --- a/auth/lib/ui/code_timer_progress.dart +++ b/auth/lib/ui/code_timer_progress.dart @@ -1,3 +1,4 @@ +import 'package:ente_auth/services/preference_service.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -30,6 +31,7 @@ class _CodeTimerProgressState extends State late final Ticker _ticker; late final ValueNotifier _progress; late final int _microSecondsInPeriod; + late bool _isCompactMode=false; @override void initState() { @@ -38,6 +40,7 @@ class _CodeTimerProgressState extends State _progress = ValueNotifier(0.0); _ticker = createTicker(_updateTimeRemaining); _ticker.start(); + _isCompactMode = PreferenceService.instance.isCompactMode(); _updateTimeRemaining(Duration.zero); } @@ -57,7 +60,7 @@ class _CodeTimerProgressState extends State @override Widget build(BuildContext context) { return SizedBox( - height: 3, + height: _isCompactMode ?1:3, child: ValueListenableBuilder( valueListenable: _progress, builder: (context, progress, _) { diff --git a/auth/lib/ui/code_widget.dart b/auth/lib/ui/code_widget.dart index 3bc0245100..e9ac384889 100644 --- a/auth/lib/ui/code_widget.dart +++ b/auth/lib/ui/code_widget.dart @@ -30,10 +30,12 @@ import 'package:move_to_background/move_to_background.dart'; class CodeWidget extends StatefulWidget { final Code code; + final bool isCompactMode; const CodeWidget( this.code, { super.key, + required this.isCompactMode, }); @override @@ -50,12 +52,14 @@ class _CodeWidgetState extends State { late bool _shouldShowLargeIcon; late bool _hideCode; bool isMaskingEnabled = false; + bool isCompactMode = true; int _codeTimeStep = -1; @override void initState() { super.initState(); isMaskingEnabled = PreferenceService.instance.shouldHideCodes(); + _hideCode = isMaskingEnabled; _everySecondTimer = Timer.periodic(const Duration(milliseconds: 500), (Timer t) { @@ -116,7 +120,7 @@ class _CodeWidgetState extends State { painter: PinBgPainter( color: colorScheme.pinnedBgColor, ), - size: const Size(39, 39), + size: isCompactMode ? const Size(24, 24) : const Size(39, 39), ), ), if (widget.code.isTrashed && kDebugMode) @@ -137,7 +141,9 @@ class _CodeWidgetState extends State { CodeTimerProgressCache.getCachedWidget( widget.code.period, ), - const SizedBox(height: 28), + widget.isCompactMode + ? const SizedBox(height: 4) + : const SizedBox(height: 28), Row( children: [ _shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(), @@ -145,22 +151,32 @@ class _CodeWidgetState extends State { child: Column( children: [ _getTopRow(), - const SizedBox(height: 4), + widget.isCompactMode + ? const SizedBox.shrink() + : const SizedBox(height: 4), _getBottomRow(l10n), ], ), ), ], ), - const SizedBox(height: 32), + isCompactMode + ? const SizedBox(height: 4) + : const SizedBox(height: 32), ], ), if (widget.code.isPinned) ...[ Align( alignment: Alignment.topRight, child: Padding( - padding: const EdgeInsets.only(right: 6, top: 6), - child: SvgPicture.asset("assets/svg/pin-card.svg"), + padding: widget.isCompactMode + ? const EdgeInsets.only(right: 2, top: 2) + : const EdgeInsets.only(right: 6, top: 6), + child: SvgPicture.asset( + "assets/svg/pin-card.svg", + width: widget.isCompactMode ? 8 : null, + height: widget.isCompactMode ? 8 : null, + ), ), ), ], @@ -207,7 +223,9 @@ class _CodeWidgetState extends State { } return Container( - margin: const EdgeInsets.only(left: 16, right: 16, bottom: 8, top: 8), + margin: widget.isCompactMode + ? const EdgeInsets.only(left: 16, right: 16, bottom: 6, top: 6) + : const EdgeInsets.only(left: 16, right: 16, bottom: 8, top: 8), child: Builder( builder: (context) { if (PlatformUtil.isDesktop()) { @@ -248,6 +266,7 @@ class _CodeWidgetState extends State { child: clippedCard(l10n), ); } + double slideSpace = isCompactMode ? 4 : 8; return Slidable( key: ValueKey(widget.code.hashCode), @@ -255,9 +274,7 @@ class _CodeWidgetState extends State { extentRatio: 0.90, motion: const ScrollMotion(), children: [ - const SizedBox( - width: 14, - ), + SizedBox(width: slideSpace), SlidableAction( onPressed: _onShowQrPressed, backgroundColor: Colors.grey.withOpacity(0.1), @@ -269,9 +286,7 @@ class _CodeWidgetState extends State { padding: const EdgeInsets.only(left: 4, right: 0), spacing: 8, ), - const SizedBox( - width: 14, - ), + SizedBox(width: slideSpace), CustomSlidableAction( onPressed: _onPinPressed, backgroundColor: Colors.grey.withOpacity(0.1), @@ -305,9 +320,7 @@ class _CodeWidgetState extends State { ), padding: const EdgeInsets.only(left: 4, right: 0), ), - const SizedBox( - width: 14, - ), + SizedBox(width: slideSpace), SlidableAction( onPressed: _onEditPressed, backgroundColor: Colors.grey.withOpacity(0.1), @@ -319,9 +332,7 @@ class _CodeWidgetState extends State { padding: const EdgeInsets.only(left: 4, right: 0), spacing: 8, ), - const SizedBox( - width: 14, - ), + SizedBox(width: slideSpace), SlidableAction( onPressed: widget.code.isTrashed ? _onDeletePressed @@ -362,7 +373,7 @@ class _CodeWidgetState extends State { type: MaterialType.transparency, child: AutoSizeText( _getFormattedCode(value), - style: const TextStyle(fontSize: 24), + style: TextStyle(fontSize: widget.isCompactMode ? 14 : 24), maxLines: 1, ), ); @@ -389,8 +400,8 @@ class _CodeWidgetState extends State { type: MaterialType.transparency, child: Text( _getFormattedCode(value), - style: const TextStyle( - fontSize: 18, + style: TextStyle( + fontSize: widget.isCompactMode ? 12 : 18, color: Colors.grey, ), ), @@ -423,6 +434,7 @@ class _CodeWidgetState extends State { } Widget _getTopRow() { + bool isCompactMode = widget.isCompactMode; return Padding( padding: const EdgeInsets.only(left: 16, right: 16), child: Row( @@ -434,13 +446,15 @@ class _CodeWidgetState extends State { children: [ Text( safeDecode(widget.code.issuer).trim(), - style: Theme.of(context).textTheme.titleLarge, + style: isCompactMode + ? Theme.of(context).textTheme.bodyMedium + : Theme.of(context).textTheme.titleLarge, ), - const SizedBox(height: 2), + if (!isCompactMode) const SizedBox(height: 2), Text( safeDecode(widget.code.account).trim(), style: Theme.of(context).textTheme.bodySmall?.copyWith( - fontSize: 12, + fontSize: isCompactMode ? 12 : 12, color: Colors.grey, ), ), @@ -471,12 +485,14 @@ class _CodeWidgetState extends State { Widget _getIcon() { return Padding( padding: _shouldShowLargeIcon - ? const EdgeInsets.only(left: 16) + ? EdgeInsets.only(left: widget.isCompactMode ? 12 : 16) : const EdgeInsets.all(0), child: IconUtils.instance.getIcon( context, safeDecode(widget.code.issuer).trim(), - width: _shouldShowLargeIcon ? 42 : 24, + width: widget.isCompactMode + ? (_shouldShowLargeIcon ? 32 : 24) + : (_shouldShowLargeIcon ? 42 : 24), ), ); } diff --git a/auth/lib/ui/home_page.dart b/auth/lib/ui/home_page.dart index 8e1134a951..48e017e667 100644 --- a/auth/lib/ui/home_page.dart +++ b/auth/lib/ui/home_page.dart @@ -76,6 +76,7 @@ class _HomePageState extends State { String selectedTag = ""; bool _isTrashOpen = false; bool hasTrashedCodes = false; + bool isCompactMode = false; @override void initState() { @@ -244,6 +245,7 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { final l10n = context.l10n; + isCompactMode = PreferenceService.instance.isCompactMode(); return PopScope( onPopInvokedWithResult: (_, result) async { @@ -446,6 +448,7 @@ class _HomePageState extends State { child: CodeWidget( key: ValueKey(code.hashCode), code, + isCompactMode: isCompactMode, ), ); }), @@ -476,6 +479,7 @@ class _HomePageState extends State { final codeState = _filteredCodes[index]; return CodeWidget( codeState, + isCompactMode: isCompactMode, ); }), itemCount: _filteredCodes.length, diff --git a/auth/lib/ui/settings/general_section_widget.dart b/auth/lib/ui/settings/general_section_widget.dart index 2b74cbf80d..2089b9f3ca 100644 --- a/auth/lib/ui/settings/general_section_widget.dart +++ b/auth/lib/ui/settings/general_section_widget.dart @@ -1,7 +1,9 @@ import 'dart:io'; import 'package:ente_auth/app/view/app.dart'; +import 'package:ente_auth/core/event_bus.dart'; import 'package:ente_auth/core/logging/super_logging.dart'; +import 'package:ente_auth/events/icons_changed_event.dart'; import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/locale.dart'; import 'package:ente_auth/services/preference_service.dart'; @@ -78,6 +80,22 @@ class _AdvancedSectionWidgetState extends State { ), ), sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: l10n.compactMode, + ), + trailingWidget: ToggleSwitchWidget( + value: () => PreferenceService.instance.isCompactMode(), + onChanged: () async { + await PreferenceService.instance.setCompactMode( + !PreferenceService.instance.isCompactMode(), + ); + Bus.instance.fire(IconsChangedEvent()); + setState(() {}); + }, + ), + ), + sectionOptionSpacing, MenuItemWidget( captionedTextWidget: CaptionedTextWidget( title: l10n.shouldHideCode, @@ -88,7 +106,7 @@ class _AdvancedSectionWidgetState extends State { await PreferenceService.instance.setHideCodes( !PreferenceService.instance.shouldHideCodes(), ); - if(PreferenceService.instance.shouldHideCodes()) { + if (PreferenceService.instance.shouldHideCodes()) { showToast(context, context.l10n.doubleTapToViewHiddenCode); } setState(() {});