diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d921c17ae..ce0ef1418 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -500,25 +500,12 @@ "@settingsSectionNavigation": {}, "settingsHome": "Home", "@settingsHome": {}, - "settingsDoubleBackExit": "Tap “back” twice to exit", - "@settingsDoubleBackExit": {}, - - "settingsSectionDisplay": "Display", - "@settingsSectionDisplay": {}, - "settingsLanguage": "Language", - "@settingsLanguage": {}, "settingsKeepScreenOnTile": "Keep screen on", "@settingsKeepScreenOnTile": {}, "settingsKeepScreenOnTitle": "Keep Screen On", "@settingsKeepScreenOnTitle": {}, - "settingsRasterImageBackground": "Raster image background", - "@settingsRasterImageBackground": {}, - "settingsVectorImageBackground": "Vector image background", - "@settingsVectorImageBackground": {}, - "settingsCoordinateFormatTile": "Coordinate format", - "@settingsCoordinateFormatTile": {}, - "settingsCoordinateFormatTitle": "Coordinate Format", - "@settingsCoordinateFormatTitle": {}, + "settingsDoubleBackExit": "Tap “back” twice to exit", + "@settingsDoubleBackExit": {}, "settingsSectionThumbnails": "Thumbnails", "@settingsSectionThumbnails": {}, @@ -531,6 +518,10 @@ "settingsSectionViewer": "Viewer", "@settingsSectionViewer": {}, + "settingsRasterImageBackground": "Raster image background", + "@settingsRasterImageBackground": {}, + "settingsVectorImageBackground": "Vector image background", + "@settingsVectorImageBackground": {}, "settingsViewerShowMinimap": "Show minimap", "@settingsViewerShowMinimap": {}, "settingsViewerShowInformation": "Show information", @@ -545,15 +536,12 @@ "settingsVideoShowVideos": "Show videos", "@settingsVideoShowVideos": {}, - "settingsSectionSearch": "Search", - "@settingsSectionSearch": {}, - "settingsSaveSearchHistory": "Save search history", - "@settingsSaveSearchHistory": {}, - "settingsSectionPrivacy": "Privacy", "@settingsSectionPrivacy": {}, "settingsEnableAnalytics": "Allow anonymous analytics and crash reporting", "@settingsEnableAnalytics": {}, + "settingsSaveSearchHistory": "Save search history", + "@settingsSaveSearchHistory": {}, "settingsHiddenFiltersTile": "Hidden filters", "@settingsHiddenFiltersTile": {}, @@ -575,6 +563,15 @@ "settingsStorageAccessRevokeTooltip": "Revoke", "@settingsStorageAccessRevokeTooltip": {}, + "settingsSectionLanguage": "Language & Formats", + "@settingsSectionLanguage": {}, + "settingsLanguage": "Language", + "@settingsLanguage": {}, + "settingsCoordinateFormatTile": "Coordinate format", + "@settingsCoordinateFormatTile": {}, + "settingsCoordinateFormatTitle": "Coordinate Format", + "@settingsCoordinateFormatTitle": {}, + "statsPageTitle": "Stats", "@statsPageTitle": {}, "statsImage": "{count, plural, =1{image} other{images}}", diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index d9dd708cd..5dab2c8d7 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -229,16 +229,9 @@ "settingsSectionNavigation": "탐색", "settingsHome": "홈", - "settingsDoubleBackExit": "뒤로가기 두번 눌러 앱 종료하기", - - "settingsSectionDisplay": "디스플레이", - "settingsLanguage": "언어", "settingsKeepScreenOnTile": "화면 자동 꺼짐 방지", "settingsKeepScreenOnTitle": "화면 자동 꺼짐 방지", - "settingsRasterImageBackground": "래스터 그래픽스 배경", - "settingsVectorImageBackground": "벡터 그래픽스 배경", - "settingsCoordinateFormatTile": "좌표 표현", - "settingsCoordinateFormatTitle": "좌표 표현", + "settingsDoubleBackExit": "뒤로가기 두번 눌러 앱 종료하기", "settingsSectionThumbnails": "섬네일", "settingsThumbnailShowLocationIcon": "위치 아이콘 표시", @@ -246,6 +239,8 @@ "settingsThumbnailShowVideoDuration": "동영상 길이 표시", "settingsSectionViewer": "뷰어", + "settingsRasterImageBackground": "래스터 그래픽스 배경", + "settingsVectorImageBackground": "벡터 그래픽스 배경", "settingsViewerShowMinimap": "미니맵 표시", "settingsViewerShowInformation": "상세 정보 표시", "settingsViewerShowInformationSubtitle": "제목, 날짜, 장소 등 표시", @@ -254,11 +249,9 @@ "settingsSectionVideo": "동영상", "settingsVideoShowVideos": "미디어에 동영상 표시", - "settingsSectionSearch": "검색", - "settingsSaveSearchHistory": "검색기록", - "settingsSectionPrivacy": "개인정보 보호", "settingsEnableAnalytics": "진단 데이터 보내기", + "settingsSaveSearchHistory": "검색기록", "settingsHiddenFiltersTile": "숨겨진 필터", "settingsHiddenFiltersTitle": "숨겨진 필터", @@ -271,6 +264,11 @@ "settingsStorageAccessEmpty": "접근 허용이 없습니다", "settingsStorageAccessRevokeTooltip": "취소", + "settingsSectionLanguage": "언어 및 표시 형식", + "settingsLanguage": "언어", + "settingsCoordinateFormatTile": "좌표 표현", + "settingsCoordinateFormatTitle": "좌표 표현", + "statsPageTitle": "통계", "statsImage": "{count, plural, other{사진}}", "statsVideo": "{count, plural, other{동영상}}", diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index 13d002866..4573ac7e7 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -13,8 +13,12 @@ class AIcons { static const IconData date = Icons.calendar_today_outlined; static const IconData disc = Icons.fiber_manual_record; static const IconData error = Icons.error_outline; + static const IconData grid = Icons.grid_on_outlined; + static const IconData home = Icons.home_outlined; + static const IconData language = Icons.translate_outlined; static const IconData location = Icons.place_outlined; static const IconData locationOff = Icons.location_off_outlined; + static const IconData privacy = MdiIcons.shieldAccountOutline; static const IconData raw = Icons.camera_outlined; static const IconData shooting = Icons.camera_outlined; static const IconData removableStorage = Icons.sd_storage_outlined; diff --git a/lib/widgets/common/identity/aves_expansion_tile.dart b/lib/widgets/common/identity/aves_expansion_tile.dart index 7eabb8a4d..9cbc8df7f 100644 --- a/lib/widgets/common/identity/aves_expansion_tile.dart +++ b/lib/widgets/common/identity/aves_expansion_tile.dart @@ -3,23 +3,41 @@ import 'package:expansion_tile_card/expansion_tile_card.dart'; import 'package:flutter/material.dart'; class AvesExpansionTile extends StatelessWidget { + final Widget leading; final String title; final Color color; final ValueNotifier expandedNotifier; - final bool initiallyExpanded; + final bool initiallyExpanded, showHighlight; final List children; const AvesExpansionTile({ + this.leading, @required this.title, this.color, this.expandedNotifier, this.initiallyExpanded = false, + this.showHighlight = true, @required this.children, }); @override Widget build(BuildContext context) { final enabled = children?.isNotEmpty == true; + Widget titleChild = HighlightTitle( + title, + color: color, + enabled: enabled, + showHighlight: showHighlight, + ); + if (leading != null) { + titleChild = Row( + children: [ + leading, + SizedBox(width: 8), + Expanded(child: titleChild), + ], + ); + } return Theme( data: Theme.of(context).copyWith( // color used by the `ExpansionTileCard` for selected text and icons @@ -29,11 +47,7 @@ class AvesExpansionTile extends StatelessWidget { key: Key('tilecard-$title'), value: title, expandedNotifier: expandedNotifier, - title: HighlightTitle( - title, - color: color, - enabled: enabled, - ), + title: titleChild, expandable: enabled, initiallyExpanded: initiallyExpanded, finalPadding: EdgeInsets.symmetric(vertical: 6.0), diff --git a/lib/widgets/common/identity/highlight_title.dart b/lib/widgets/common/identity/highlight_title.dart index 0672f52a8..c36ff5ffc 100644 --- a/lib/widgets/common/identity/highlight_title.dart +++ b/lib/widgets/common/identity/highlight_title.dart @@ -9,6 +9,7 @@ class HighlightTitle extends StatelessWidget { final Color color; final double fontSize; final bool enabled, selectable; + final bool showHighlight; const HighlightTitle( this.title, { @@ -16,6 +17,7 @@ class HighlightTitle extends StatelessWidget { this.fontSize = 18, this.enabled = true, this.selectable = false, + this.showHighlight = true, }) : assert(title != null); static const disabledColor = Colors.grey; @@ -38,9 +40,11 @@ class HighlightTitle extends StatelessWidget { return Align( alignment: AlignmentDirectional.centerStart, child: Container( - decoration: HighlightDecoration( - color: enabled ? color ?? stringToColor(title) : disabledColor, - ), + decoration: showHighlight + ? HighlightDecoration( + color: enabled ? color ?? stringToColor(title) : disabledColor, + ) + : null, margin: EdgeInsets.symmetric(vertical: 4.0), child: selectable ? SelectableText( diff --git a/lib/widgets/settings/settings_page.dart b/lib/widgets/settings/settings_page.dart index c94d23f97..53f00356b 100644 --- a/lib/widgets/settings/settings_page.dart +++ b/lib/widgets/settings/settings_page.dart @@ -6,15 +6,19 @@ import 'package:aves/model/settings/screen_on.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/theme/durations.dart'; +import 'package:aves/theme/icons.dart'; +import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_expansion_tile.dart'; +import 'package:aves/widgets/common/identity/aves_filter_chip.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/dialogs/aves_selection_dialog.dart'; import 'package:aves/widgets/settings/access_grants.dart'; import 'package:aves/widgets/settings/entry_background.dart'; import 'package:aves/widgets/settings/hidden_filters.dart'; import 'package:aves/widgets/settings/language.dart'; +import 'package:decorated_icon/decorated_icon.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:provider/provider.dart'; @@ -60,12 +64,11 @@ class _SettingsPageState extends State { ), children: [ _buildNavigationSection(context), - _buildDisplaySection(context), _buildThumbnailsSection(context), _buildViewerSection(context), _buildVideoSection(context), - _buildSearchSection(context), _buildPrivacySection(context), + _buildLanguageSection(context), ], ), ), @@ -79,8 +82,10 @@ class _SettingsPageState extends State { Widget _buildNavigationSection(BuildContext context) { return AvesExpansionTile( + leading: _buildLeading(AIcons.home, stringToColor('Navigation')), title: context.l10n.settingsSectionNavigation, expandedNotifier: _expandedNotifier, + showHighlight: false, children: [ ListTile( title: Text(context.l10n.settingsHome), @@ -99,21 +104,6 @@ class _SettingsPageState extends State { } }, ), - SwitchListTile( - value: settings.mustBackTwiceToExit, - onChanged: (v) => settings.mustBackTwiceToExit = v, - title: Text(context.l10n.settingsDoubleBackExit), - ), - ], - ); - } - - Widget _buildDisplaySection(BuildContext context) { - return AvesExpansionTile( - title: context.l10n.settingsSectionDisplay, - expandedNotifier: _expandedNotifier, - children: [ - LanguageTile(), ListTile( title: Text(context.l10n.settingsKeepScreenOnTile), subtitle: Text(settings.keepScreenOn.getName(context)), @@ -131,6 +121,66 @@ class _SettingsPageState extends State { } }, ), + SwitchListTile( + value: settings.mustBackTwiceToExit, + onChanged: (v) => settings.mustBackTwiceToExit = v, + title: Text(context.l10n.settingsDoubleBackExit), + ), + ], + ); + } + + Widget _buildThumbnailsSection(BuildContext context) { + final iconColor = IconTheme.of(context).color; + Color iconColorFor(bool enabled) => iconColor.withOpacity(enabled ? 1 : .12); + return AvesExpansionTile( + leading: _buildLeading(AIcons.grid, stringToColor('Thumbnails')), + title: context.l10n.settingsSectionThumbnails, + expandedNotifier: _expandedNotifier, + showHighlight: false, + children: [ + SwitchListTile( + value: settings.showThumbnailLocation, + onChanged: (v) => settings.showThumbnailLocation = v, + title: Row( + children: [ + Expanded(child: Text(context.l10n.settingsThumbnailShowLocationIcon)), + Icon( + AIcons.location, + color: iconColorFor(settings.showThumbnailLocation), + ), + ], + ), + ), + SwitchListTile( + value: settings.showThumbnailRaw, + onChanged: (v) => settings.showThumbnailRaw = v, + title: Row( + children: [ + Expanded(child: Text(context.l10n.settingsThumbnailShowRawIcon)), + Icon( + AIcons.raw, + color: iconColorFor(settings.showThumbnailRaw), + ), + ], + ), + ), + SwitchListTile( + value: settings.showThumbnailVideoDuration, + onChanged: (v) => settings.showThumbnailVideoDuration = v, + title: Text(context.l10n.settingsThumbnailShowVideoDuration), + ), + ], + ); + } + + Widget _buildViewerSection(BuildContext context) { + return AvesExpansionTile( + leading: _buildLeading(AIcons.image, stringToColor('Image')), + title: context.l10n.settingsSectionViewer, + expandedNotifier: _expandedNotifier, + showHighlight: false, + children: [ ListTile( title: Text(context.l10n.settingsRasterImageBackground), trailing: EntryBackgroundSelector( @@ -145,57 +195,6 @@ class _SettingsPageState extends State { setter: (value) => settings.vectorBackground = value, ), ), - ListTile( - title: Text(context.l10n.settingsCoordinateFormatTile), - subtitle: Text(settings.coordinateFormat.getName(context)), - onTap: () async { - final value = await showDialog( - context: context, - builder: (context) => AvesSelectionDialog( - initialValue: settings.coordinateFormat, - options: Map.fromEntries(CoordinateFormat.values.map((v) => MapEntry(v, v.getName(context)))), - optionSubtitleBuilder: (value) => value.format(Constants.pointNemo), - title: context.l10n.settingsCoordinateFormatTitle, - ), - ); - if (value != null) { - settings.coordinateFormat = value; - } - }, - ), - ], - ); - } - - Widget _buildThumbnailsSection(BuildContext context) { - return AvesExpansionTile( - title: context.l10n.settingsSectionThumbnails, - expandedNotifier: _expandedNotifier, - children: [ - SwitchListTile( - value: settings.showThumbnailLocation, - onChanged: (v) => settings.showThumbnailLocation = v, - title: Text(context.l10n.settingsThumbnailShowLocationIcon), - ), - SwitchListTile( - value: settings.showThumbnailRaw, - onChanged: (v) => settings.showThumbnailRaw = v, - title: Text(context.l10n.settingsThumbnailShowRawIcon), - ), - SwitchListTile( - value: settings.showThumbnailVideoDuration, - onChanged: (v) => settings.showThumbnailVideoDuration = v, - title: Text(context.l10n.settingsThumbnailShowVideoDuration), - ), - ], - ); - } - - Widget _buildViewerSection(BuildContext context) { - return AvesExpansionTile( - title: context.l10n.settingsSectionViewer, - expandedNotifier: _expandedNotifier, - children: [ SwitchListTile( value: settings.showOverlayMinimap, onChanged: (v) => settings.showOverlayMinimap = v, @@ -220,8 +219,10 @@ class _SettingsPageState extends State { final hiddenFilters = settings.hiddenFilters; final showVideos = !hiddenFilters.contains(MimeFilter.video); return AvesExpansionTile( + leading: _buildLeading(AIcons.video, stringToColor('Video')), title: context.l10n.settingsSectionVideo, expandedNotifier: _expandedNotifier, + showHighlight: false, children: [ SwitchListTile( value: showVideos, @@ -232,11 +233,18 @@ class _SettingsPageState extends State { ); } - Widget _buildSearchSection(BuildContext context) { + Widget _buildPrivacySection(BuildContext context) { return AvesExpansionTile( - title: context.l10n.settingsSectionSearch, + leading: _buildLeading(AIcons.privacy, stringToColor('Privacy')), + title: context.l10n.settingsSectionPrivacy, expandedNotifier: _expandedNotifier, + showHighlight: false, children: [ + SwitchListTile( + value: settings.isCrashlyticsEnabled, + onChanged: (v) => settings.isCrashlyticsEnabled = v, + title: Text(context.l10n.settingsEnableAnalytics), + ), SwitchListTile( value: settings.saveSearchHistory, onChanged: (v) { @@ -247,23 +255,55 @@ class _SettingsPageState extends State { }, title: Text(context.l10n.settingsSaveSearchHistory), ), - ], - ); - } - - Widget _buildPrivacySection(BuildContext context) { - return AvesExpansionTile( - title: context.l10n.settingsSectionPrivacy, - expandedNotifier: _expandedNotifier, - children: [ - SwitchListTile( - value: settings.isCrashlyticsEnabled, - onChanged: (v) => settings.isCrashlyticsEnabled = v, - title: Text(context.l10n.settingsEnableAnalytics), - ), HiddenFilterTile(), StorageAccessTile(), ], ); } + + Widget _buildLanguageSection(BuildContext context) { + return AvesExpansionTile( + leading: _buildLeading(AIcons.language, stringToColor('Language')), + title: context.l10n.settingsSectionLanguage, + expandedNotifier: _expandedNotifier, + showHighlight: false, + children: [ + LanguageTile(), + ListTile( + title: Text(context.l10n.settingsCoordinateFormatTile), + subtitle: Text(settings.coordinateFormat.getName(context)), + onTap: () async { + final value = await showDialog( + context: context, + builder: (context) => AvesSelectionDialog( + initialValue: settings.coordinateFormat, + options: Map.fromEntries(CoordinateFormat.values.map((v) => MapEntry(v, v.getName(context)))), + optionSubtitleBuilder: (value) => value.format(Constants.pointNemo), + title: context.l10n.settingsCoordinateFormatTitle, + ), + ); + if (value != null) { + settings.coordinateFormat = value; + } + }, + ), + ], + ); + } + + Widget _buildLeading(IconData icon, Color color) => Container( + padding: EdgeInsets.all(6), + decoration: BoxDecoration( + border: Border.all( + color: color, + width: AvesFilterChip.outlineWidth, + ), + shape: BoxShape.circle, + ), + child: DecoratedIcon( + icon, + shadows: [Constants.embossShadow], + size: 18, + ), + ); }