Update settings (#240)

This commit is contained in:
Vishnu Mohandas 2023-09-08 20:56:50 +05:30 committed by GitHub
commit ad3ae560bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 217 additions and 160 deletions

View file

@ -102,6 +102,7 @@
"no": "No",
"email": "Email",
"support": "Support",
"advanced": "Advanced",
"settings": "Settings",
"copied": "Copied",
"pleaseTryAgain": "Please try again",
@ -326,5 +327,7 @@
"signInToBackup": "Sign in to backup your codes",
"singIn": "Sign in",
"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."
"offlineModeWarning": "You have chosen to proceed without backups. Please take manual backups to make sure your codes are safe.",
"showLargeIcons": "Show large icons",
"focusOnSearchBar": "Focus search on app start"
}

View file

@ -11,6 +11,7 @@ class PreferenceService {
static const kHasShownCoachMarkKey = "has_shown_coach_mark";
static const kShouldShowLargeIconsKey = "should_show_large_icons";
static const kShouldAutoFocusOnSearchBar = "should_auto_focus_on_search_bar";
Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
@ -40,4 +41,17 @@ class PreferenceService {
await _prefs.setBool(kShouldShowLargeIconsKey, value);
Bus.instance.fire(IconsChangedEvent());
}
bool shouldAutoFocusOnSearchBar() {
if (_prefs.containsKey(kShouldAutoFocusOnSearchBar)) {
return _prefs.getBool(kShouldAutoFocusOnSearchBar)!;
} else {
return false;
}
}
Future<void> setAutoFocusOnSearchBar(bool value) async {
await _prefs.setBool(kShouldAutoFocusOnSearchBar, value);
Bus.instance.fire(IconsChangedEvent());
}
}

View file

@ -16,9 +16,7 @@ import 'package:ente_auth/utils/toast_util.dart';
import 'package:ente_auth/utils/totp_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:local_hero/local_hero.dart';
import 'package:logging/logging.dart';
import 'package:uuid/uuid.dart';
class CodeWidget extends StatefulWidget {
final Code code;
@ -37,7 +35,6 @@ class _CodeWidgetState extends State<CodeWidget> {
bool _isInitialized = false;
late bool hasConfiguredAccount;
late bool _shouldShowLargeIcon;
final String _key = const Uuid().v4();
@override
void initState() {
@ -152,116 +149,109 @@ class _CodeWidgetState extends State<CodeWidget> {
}
Widget _getCardContents(AppLocalizations l10n) {
return LocalHeroScope(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.code.type == Type.totp)
CodeTimerProgress(
period: widget.code.period,
),
const SizedBox(
height: 16,
return SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.code.type == Type.totp)
CodeTimerProgress(
period: widget.code.period,
),
Row(
children: [
_shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(),
Expanded(
child: Column(
children: [
_getTopRow(),
const SizedBox(height: 4),
_getBottomRow(l10n),
],
),
const SizedBox(
height: 16,
),
Row(
children: [
_shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(),
Expanded(
child: Column(
children: [
_getTopRow(),
const SizedBox(height: 4),
_getBottomRow(l10n),
],
),
],
),
const SizedBox(
height: 20,
),
],
),
),
],
),
const SizedBox(
height: 20,
),
],
),
);
}
Widget _getBottomRow(AppLocalizations l10n) {
return LocalHero(
tag: _key + "_bottom_row",
child: Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: ValueListenableBuilder<String>(
valueListenable: _currentCode,
builder: (context, value, child) {
return Material(
type: MaterialType.transparency,
child: Text(
_getFormattedCode(value),
style: const TextStyle(fontSize: 24),
),
);
},
),
return Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: ValueListenableBuilder<String>(
valueListenable: _currentCode,
builder: (context, value, child) {
return Material(
type: MaterialType.transparency,
child: Text(
_getFormattedCode(value),
style: const TextStyle(fontSize: 24),
),
);
},
),
widget.code.type == Type.totp
? GestureDetector(
onTap: () {
_copyNextToClipboard();
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
l10n.nextTotpTitle,
style: Theme.of(context).textTheme.bodySmall,
),
ValueListenableBuilder<String>(
valueListenable: _nextCode,
builder: (context, value, child) {
return Material(
type: MaterialType.transparency,
child: Text(
_getFormattedCode(value),
style: const TextStyle(
fontSize: 18,
color: Colors.grey,
),
),
);
},
),
],
),
)
: Column(
),
widget.code.type == Type.totp
? GestureDetector(
onTap: () {
_copyNextToClipboard();
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
l10n.nextTotpTitle,
style: Theme.of(context).textTheme.bodySmall,
),
InkWell(
onTap: _onNextHotpTapped,
child: const Icon(
Icons.forward_outlined,
size: 32,
color: Colors.grey,
),
ValueListenableBuilder<String>(
valueListenable: _nextCode,
builder: (context, value, child) {
return Material(
type: MaterialType.transparency,
child: Text(
_getFormattedCode(value),
style: const TextStyle(
fontSize: 18,
color: Colors.grey,
),
),
);
},
),
],
),
],
),
)
: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
l10n.nextTotpTitle,
style: Theme.of(context).textTheme.bodySmall,
),
InkWell(
onTap: _onNextHotpTapped,
child: const Icon(
Icons.forward_outlined,
size: 32,
color: Colors.grey,
),
),
],
),
],
),
);
}
@ -273,25 +263,22 @@ class _CodeWidgetState extends State<CodeWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocalHero(
tag: _key + "_top_row",
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
safeDecode(widget.code.issuer).trim(),
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 2),
Text(
safeDecode(widget.code.account).trim(),
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontSize: 12,
color: Colors.grey,
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
safeDecode(widget.code.issuer).trim(),
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 2),
Text(
safeDecode(widget.code.account).trim(),
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontSize: 12,
color: Colors.grey,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
@ -314,21 +301,13 @@ class _CodeWidgetState extends State<CodeWidget> {
}
Widget _getIcon() {
return LocalHero(
tag: _key,
child: Padding(
padding: _shouldShowLargeIcon
? const EdgeInsets.only(left: 16)
: const EdgeInsets.all(0),
child: GestureDetector(
onTap: () {
PreferenceService.instance.setShowLargeIcons(!_shouldShowLargeIcon);
},
child: IconUtils.instance.getIcon(
safeDecode(widget.code.issuer).trim(),
width: _shouldShowLargeIcon ? 42 : 24,
),
),
return Padding(
padding: _shouldShowLargeIcon
? const EdgeInsets.only(left: 16)
: const EdgeInsets.all(0),
child: IconUtils.instance.getIcon(
safeDecode(widget.code.issuer).trim(),
width: _shouldShowLargeIcon ? 42 : 24,
),
);
}

View file

@ -74,6 +74,7 @@ class _HomePageState extends State<HomePage> {
_iconsChangedEvent = Bus.instance.on<IconsChangedEvent>().listen((event) {
setState(() {});
});
_showSearchBox = PreferenceService.instance.shouldAutoFocusOnSearchBar();
}
void _loadCodes() {
@ -177,7 +178,7 @@ class _HomePageState extends State<HomePage> {
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: !_showSearchBox
? const Text('ente Authenticator')
? const Text('ente Auth')
: TextField(
autofocus: _searchText.isEmpty,
controller: _textController,
@ -188,6 +189,7 @@ class _HomePageState extends State<HomePage> {
decoration: InputDecoration(
hintText: l10n.searchHint,
border: InputBorder.none,
focusedBorder: InputBorder.none,
),
),
actions: <Widget>[

View file

@ -0,0 +1,83 @@
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/services/preference_service.dart';
import 'package:ente_auth/ui/components/captioned_text_widget.dart';
import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart';
import 'package:ente_auth/ui/components/menu_item_widget.dart';
import 'package:ente_auth/ui/components/toggle_switch_widget.dart';
import 'package:ente_auth/ui/settings/common_settings.dart';
import 'package:flutter/material.dart';
class AdvancedSectionWidget extends StatefulWidget {
const AdvancedSectionWidget({Key? key}) : super(key: key);
@override
State<AdvancedSectionWidget> createState() => _AdvancedSectionWidgetState();
}
class _AdvancedSectionWidgetState extends State<AdvancedSectionWidget> {
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return ExpandableMenuItemWidget(
title: l10n.advanced,
selectionOptionsWidget: _getSectionOptions(context),
leadingIcon: Icons.graphic_eq,
);
}
Widget _getSectionOptions(BuildContext context) {
final l10n = context.l10n;
return Column(
children: [
sectionOptionSpacing,
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.showLargeIcons,
),
trailingWidget: ToggleSwitchWidget(
value: () => PreferenceService.instance.shouldShowLargeIcons(),
onChanged: () async {
await PreferenceService.instance.setShowLargeIcons(
!PreferenceService.instance.shouldShowLargeIcons(),
);
setState(() {});
},
),
),
sectionOptionSpacing,
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.focusOnSearchBar,
),
trailingWidget: ToggleSwitchWidget(
value: () =>
PreferenceService.instance.shouldAutoFocusOnSearchBar(),
onChanged: () async {
await PreferenceService.instance.setAutoFocusOnSearchBar(
!PreferenceService.instance.shouldAutoFocusOnSearchBar(),
);
setState(() {});
},
),
),
sectionOptionSpacing,
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.crashAndErrorReporting,
),
trailingWidget: ToggleSwitchWidget(
value: () => SuperLogging.shouldReportErrors(),
onChanged: () async {
await SuperLogging.setShouldReportErrors(
!SuperLogging.shouldReportErrors(),
);
setState(() {});
},
),
),
sectionOptionSpacing,
],
);
}
}

View file

@ -1,11 +1,9 @@
import 'package:ente_auth/core/constants.dart';
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/l10n/l10n.dart';
import 'package:ente_auth/theme/ente_theme.dart';
import 'package:ente_auth/ui/components/captioned_text_widget.dart';
import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart';
import 'package:ente_auth/ui/components/menu_item_widget.dart';
import 'package:ente_auth/ui/components/toggle_switch_widget.dart';
import 'package:ente_auth/ui/settings/common_settings.dart';
import 'package:ente_auth/ui/settings/faq.dart';
import 'package:ente_auth/utils/email_util.dart';
@ -35,7 +33,6 @@ class _SupportSectionWidgetState extends State<SupportSectionWidget> {
return Column(
children: [
sectionOptionSpacing,
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.faq,
@ -98,21 +95,6 @@ class _SupportSectionWidgetState extends State<SupportSectionWidget> {
},
),
sectionOptionSpacing,
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.crashAndErrorReporting,
),
trailingWidget: ToggleSwitchWidget(
value: () => SuperLogging.shouldReportErrors(),
onChanged: () async {
await SuperLogging.setShouldReportErrors(
!SuperLogging.shouldReportErrors(),
);
setState(() {});
},
),
),
sectionOptionSpacing,
],
);
}

View file

@ -14,6 +14,7 @@ import 'package:ente_auth/ui/settings/account_section_widget.dart';
import 'package:ente_auth/ui/settings/app_version_widget.dart';
import 'package:ente_auth/ui/settings/data/data_section_widget.dart';
import 'package:ente_auth/ui/settings/data/export_widget.dart';
import 'package:ente_auth/ui/settings/advanced_section_widget.dart';
import 'package:ente_auth/ui/settings/security_section_widget.dart';
import 'package:ente_auth/ui/settings/social_section_widget.dart';
import 'package:ente_auth/ui/settings/support_dev_widget.dart';
@ -125,6 +126,8 @@ class SettingsPage extends StatelessWidget {
}
contents.addAll([
const AdvancedSectionWidget(),
sectionSpacing,
const SupportSectionWidget(),
sectionSpacing,
const SocialSectionWidget(),

View file

@ -783,14 +783,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
local_hero:
dependency: "direct main"
description:
name: local_hero
sha256: "2dd2904c46d786dbc6f7179ba863e04f2be1fd603c530501a336a07744b60c7b"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
logging:
dependency: "direct main"
description:

View file

@ -1,6 +1,6 @@
name: ente_auth
description: ente two-factor authenticator
version: 2.0.1+201
version: 2.0.2+202
publish_to: none
environment:
@ -51,7 +51,6 @@ dependencies:
intl: ^0.18.0
json_annotation: ^4.5.0
local_auth: ^2.1.3
local_hero: ^0.2.0
logging: ^1.0.1
modal_bottom_sheet: ^3.0.0-pre
move_to_background: ^1.0.2