minor fixes
This commit is contained in:
parent
b3500edd10
commit
fcca4776c6
12 changed files with 248 additions and 266 deletions
|
@ -505,6 +505,17 @@
|
||||||
"@aboutCreditsWorldAtlas2": {},
|
"@aboutCreditsWorldAtlas2": {},
|
||||||
"aboutCreditsTranslators": "Translators:",
|
"aboutCreditsTranslators": "Translators:",
|
||||||
"@aboutCreditsTranslators": {},
|
"@aboutCreditsTranslators": {},
|
||||||
|
"aboutCreditsTranslatorLine": "{language}: {names}",
|
||||||
|
"@aboutCreditsTranslatorLine": {
|
||||||
|
"placeholders": {
|
||||||
|
"language": {
|
||||||
|
"type": "String"
|
||||||
|
},
|
||||||
|
"names": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"aboutLicenses": "Open-Source Licenses",
|
"aboutLicenses": "Open-Source Licenses",
|
||||||
"@aboutLicenses": {},
|
"@aboutLicenses": {},
|
||||||
|
@ -893,8 +904,11 @@
|
||||||
"settingsSaveSearchHistory": "Save search history",
|
"settingsSaveSearchHistory": "Save search history",
|
||||||
"@settingsSaveSearchHistory": {},
|
"@settingsSaveSearchHistory": {},
|
||||||
|
|
||||||
"settingsHiddenFiltersTile": "Hidden filters",
|
"settingsHiddenItemsTile": "Hidden items",
|
||||||
"@settingsHiddenFiltersTile": {},
|
"@settingsHiddenItemsTile": {},
|
||||||
|
"settingsHiddenItemsTitle": "Hidden Items",
|
||||||
|
"@settingsHiddenItemsTitle": {},
|
||||||
|
|
||||||
"settingsHiddenFiltersTitle": "Hidden Filters",
|
"settingsHiddenFiltersTitle": "Hidden Filters",
|
||||||
"@settingsHiddenFiltersTitle": {},
|
"@settingsHiddenFiltersTitle": {},
|
||||||
"settingsHiddenFiltersBanner": "Photos and videos matching hidden filters will not appear in your collection.",
|
"settingsHiddenFiltersBanner": "Photos and videos matching hidden filters will not appear in your collection.",
|
||||||
|
@ -902,14 +916,10 @@
|
||||||
"settingsHiddenFiltersEmpty": "No hidden filters",
|
"settingsHiddenFiltersEmpty": "No hidden filters",
|
||||||
"@settingsHiddenFiltersEmpty": {},
|
"@settingsHiddenFiltersEmpty": {},
|
||||||
|
|
||||||
"settingsHiddenPathsTile": "Hidden paths",
|
|
||||||
"@settingsHiddenPathsTile": {},
|
|
||||||
"settingsHiddenPathsTitle": "Hidden Paths",
|
"settingsHiddenPathsTitle": "Hidden Paths",
|
||||||
"@settingsHiddenPathsTitle": {},
|
"@settingsHiddenPathsTitle": {},
|
||||||
"settingsHiddenPathsBanner": "Photos and videos in these folders, or any of their subfolders, will not appear in your collection.",
|
"settingsHiddenPathsBanner": "Photos and videos in these folders, or any of their subfolders, will not appear in your collection.",
|
||||||
"@settingsHiddenPathsBanner": {},
|
"@settingsHiddenPathsBanner": {},
|
||||||
"settingsHiddenPathsEmpty": "No hidden paths",
|
|
||||||
"@settingsHiddenPathsEmpty": {},
|
|
||||||
"addPathTooltip": "Add path",
|
"addPathTooltip": "Add path",
|
||||||
"@addPathTooltip": {},
|
"@addPathTooltip": {},
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"removeTooltip": "Supprimer",
|
"removeTooltip": "Supprimer",
|
||||||
"resetButtonTooltip": "Réinitialiser",
|
"resetButtonTooltip": "Réinitialiser",
|
||||||
|
|
||||||
"doubleBackExitMessage": "Presser «\u00A0retour\u00A0» à nouveau pour quitter.",
|
"doubleBackExitMessage": "Pressez «\u00A0retour\u00A0» à nouveau pour quitter.",
|
||||||
|
|
||||||
"sourceStateLoading": "Chargement",
|
"sourceStateLoading": "Chargement",
|
||||||
"sourceStateCataloguing": "Classification",
|
"sourceStateCataloguing": "Classification",
|
||||||
|
@ -233,7 +233,8 @@
|
||||||
"aboutCredits": "Remerciements",
|
"aboutCredits": "Remerciements",
|
||||||
"aboutCreditsWorldAtlas1": "Cette app utilise un fichier TopoJSON de ",
|
"aboutCreditsWorldAtlas1": "Cette app utilise un fichier TopoJSON de ",
|
||||||
"aboutCreditsWorldAtlas2": "sous licence ISC.",
|
"aboutCreditsWorldAtlas2": "sous licence ISC.",
|
||||||
"aboutCreditsTranslators": "Traducteurs:",
|
"aboutCreditsTranslators": "Traducteurs :",
|
||||||
|
"aboutCreditsTranslatorLine": "{language} : {names}",
|
||||||
|
|
||||||
"aboutLicenses": "Licences open-source",
|
"aboutLicenses": "Licences open-source",
|
||||||
"aboutLicensesBanner": "Cette app utilise ces librairies et packages open-source.",
|
"aboutLicensesBanner": "Cette app utilise ces librairies et packages open-source.",
|
||||||
|
@ -426,15 +427,15 @@
|
||||||
"settingsAllowErrorReporting": "Autoriser l’envoi de rapports d’erreur",
|
"settingsAllowErrorReporting": "Autoriser l’envoi de rapports d’erreur",
|
||||||
"settingsSaveSearchHistory": "Maintenir un historique des recherches",
|
"settingsSaveSearchHistory": "Maintenir un historique des recherches",
|
||||||
|
|
||||||
"settingsHiddenFiltersTile": "Filtres masqués",
|
"settingsHiddenItemsTile": "Éléments masqués",
|
||||||
|
"settingsHiddenItemsTitle": "Éléments masqués",
|
||||||
|
|
||||||
"settingsHiddenFiltersTitle": "Filtres masqués",
|
"settingsHiddenFiltersTitle": "Filtres masqués",
|
||||||
"settingsHiddenFiltersBanner": "Les images et vidéos correspondantes aux filtres masqués n’apparaîtront pas dans votre collection.",
|
"settingsHiddenFiltersBanner": "Les images et vidéos correspondantes aux filtres masqués n’apparaîtront pas dans votre collection.",
|
||||||
"settingsHiddenFiltersEmpty": "Aucun filtre masqué",
|
"settingsHiddenFiltersEmpty": "Aucun filtre masqué",
|
||||||
|
|
||||||
"settingsHiddenPathsTile": "Chemins masqués",
|
|
||||||
"settingsHiddenPathsTitle": "Chemins masqués",
|
"settingsHiddenPathsTitle": "Chemins masqués",
|
||||||
"settingsHiddenPathsBanner": "Les images et vidéos dans ces dossiers, ou leurs sous-dossiers, n’apparaîtront pas dans votre collection.",
|
"settingsHiddenPathsBanner": "Les images et vidéos dans ces dossiers, ou leurs sous-dossiers, n’apparaîtront pas dans votre collection.",
|
||||||
"settingsHiddenPathsEmpty": "Aucun chemin masqué",
|
|
||||||
"addPathTooltip": "Ajouter un chemin",
|
"addPathTooltip": "Ajouter un chemin",
|
||||||
|
|
||||||
"settingsStorageAccessTile": "Accès au stockage",
|
"settingsStorageAccessTile": "Accès au stockage",
|
||||||
|
|
|
@ -233,6 +233,7 @@
|
||||||
"aboutCreditsWorldAtlas1": "이 앱은",
|
"aboutCreditsWorldAtlas1": "이 앱은",
|
||||||
"aboutCreditsWorldAtlas2": "의 TopoJSON 파일(ISC 라이선스)을 이용합니다.",
|
"aboutCreditsWorldAtlas2": "의 TopoJSON 파일(ISC 라이선스)을 이용합니다.",
|
||||||
"aboutCreditsTranslators": "번역가:",
|
"aboutCreditsTranslators": "번역가:",
|
||||||
|
"aboutCreditsTranslatorLine": "{language}: {names}",
|
||||||
|
|
||||||
"aboutLicenses": "오픈 소스 라이선스",
|
"aboutLicenses": "오픈 소스 라이선스",
|
||||||
"aboutLicensesBanner": "이 앱은 다음의 오픈 소스 패키지와 라이브러리를 이용합니다.",
|
"aboutLicensesBanner": "이 앱은 다음의 오픈 소스 패키지와 라이브러리를 이용합니다.",
|
||||||
|
@ -425,15 +426,15 @@
|
||||||
"settingsAllowErrorReporting": "오류 보고서 보내기",
|
"settingsAllowErrorReporting": "오류 보고서 보내기",
|
||||||
"settingsSaveSearchHistory": "검색기록",
|
"settingsSaveSearchHistory": "검색기록",
|
||||||
|
|
||||||
"settingsHiddenFiltersTile": "숨겨진 필터",
|
"settingsHiddenItemsTile": "숨겨진 항목",
|
||||||
|
"settingsHiddenItemsTitle": "숨겨진 항목",
|
||||||
|
|
||||||
"settingsHiddenFiltersTitle": "숨겨진 필터",
|
"settingsHiddenFiltersTitle": "숨겨진 필터",
|
||||||
"settingsHiddenFiltersBanner": "이 필터에 맞는 사진과 동영상이 숨겨지고 있으며 이 앱에서 보여지지 않을 것입니다.",
|
"settingsHiddenFiltersBanner": "이 필터에 맞는 사진과 동영상이 숨겨지고 있으며 이 앱에서 보여지지 않을 것입니다.",
|
||||||
"settingsHiddenFiltersEmpty": "숨겨진 필터가 없습니다",
|
"settingsHiddenFiltersEmpty": "숨겨진 필터가 없습니다",
|
||||||
|
|
||||||
"settingsHiddenPathsTile": "숨겨진 경로",
|
|
||||||
"settingsHiddenPathsTitle": "숨겨진 경로",
|
"settingsHiddenPathsTitle": "숨겨진 경로",
|
||||||
"settingsHiddenPathsBanner": "이 경로에 있는 사진과 동영상이 숨겨지고 있으며 이 앱에서 보여지지 않을 것입니다.",
|
"settingsHiddenPathsBanner": "이 경로에 있는 사진과 동영상이 숨겨지고 있으며 이 앱에서 보여지지 않을 것입니다.",
|
||||||
"settingsHiddenPathsEmpty": "숨겨진 경로가 없습니다",
|
|
||||||
"addPathTooltip": "경로 추가",
|
"addPathTooltip": "경로 추가",
|
||||||
|
|
||||||
"settingsStorageAccessTile": "저장공간 접근",
|
"settingsStorageAccessTile": "저장공간 접근",
|
||||||
|
|
|
@ -232,6 +232,7 @@
|
||||||
"aboutCreditsWorldAtlas1": "Это приложение использует файл TopoJSON из",
|
"aboutCreditsWorldAtlas1": "Это приложение использует файл TopoJSON из",
|
||||||
"aboutCreditsWorldAtlas2": "под лицензией ISC.",
|
"aboutCreditsWorldAtlas2": "под лицензией ISC.",
|
||||||
"aboutCreditsTranslators": "Переводчики:",
|
"aboutCreditsTranslators": "Переводчики:",
|
||||||
|
"aboutCreditsTranslatorLine": "{language}: {names}",
|
||||||
|
|
||||||
"aboutLicenses": "Лицензии с открытым исходным кодом",
|
"aboutLicenses": "Лицензии с открытым исходным кодом",
|
||||||
"aboutLicensesBanner": "Это приложение использует следующие пакеты и библиотеки с открытым исходным кодом.",
|
"aboutLicensesBanner": "Это приложение использует следующие пакеты и библиотеки с открытым исходным кодом.",
|
||||||
|
@ -423,15 +424,12 @@
|
||||||
"settingsAllowErrorReporting": "Разрешить анонимную отправку логов",
|
"settingsAllowErrorReporting": "Разрешить анонимную отправку логов",
|
||||||
"settingsSaveSearchHistory": "Сохранять историю поиска",
|
"settingsSaveSearchHistory": "Сохранять историю поиска",
|
||||||
|
|
||||||
"settingsHiddenFiltersTile": "Скрытые фильтры",
|
|
||||||
"settingsHiddenFiltersTitle": "Скрытые фильтры",
|
"settingsHiddenFiltersTitle": "Скрытые фильтры",
|
||||||
"settingsHiddenFiltersBanner": "Фотографии и видео, соответствующие скрытым фильтрам, не появятся в вашей коллекции.",
|
"settingsHiddenFiltersBanner": "Фотографии и видео, соответствующие скрытым фильтрам, не появятся в вашей коллекции.",
|
||||||
"settingsHiddenFiltersEmpty": "Нет скрытых фильтров",
|
"settingsHiddenFiltersEmpty": "Нет скрытых фильтров",
|
||||||
|
|
||||||
"settingsHiddenPathsTile": "Скрытые каталоги",
|
|
||||||
"settingsHiddenPathsTitle": "Скрытые каталоги",
|
"settingsHiddenPathsTitle": "Скрытые каталоги",
|
||||||
"settingsHiddenPathsBanner": "Фотографии и видео в этих каталогах или любых их вложенных каталогах не будут отображаться в вашей коллекции.",
|
"settingsHiddenPathsBanner": "Фотографии и видео в этих каталогах или любых их вложенных каталогах не будут отображаться в вашей коллекции.",
|
||||||
"settingsHiddenPathsEmpty": "Нет скрытых каталогов",
|
|
||||||
"addPathTooltip": "Добавить каталог",
|
"addPathTooltip": "Добавить каталог",
|
||||||
|
|
||||||
"settingsStorageAccessTile": "Доступ к хранилищу",
|
"settingsStorageAccessTile": "Доступ к хранилищу",
|
||||||
|
|
|
@ -8,12 +8,13 @@ import 'package:flutter/material.dart';
|
||||||
class AboutCredits extends StatelessWidget {
|
class AboutCredits extends StatelessWidget {
|
||||||
const AboutCredits({Key? key}) : super(key: key);
|
const AboutCredits({Key? key}) : super(key: key);
|
||||||
|
|
||||||
static const translations = [
|
static const translators = {
|
||||||
'Русский: D3ZOXY',
|
'Русский': 'D3ZOXY',
|
||||||
];
|
};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = context.l10n;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -23,13 +24,13 @@ class AboutCredits extends StatelessWidget {
|
||||||
constraints: const BoxConstraints(minHeight: 48),
|
constraints: const BoxConstraints(minHeight: 48),
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: Text(context.l10n.aboutCredits, style: Constants.titleTextStyle),
|
child: Text(l10n.aboutCredits, style: Constants.titleTextStyle),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text.rich(
|
Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: context.l10n.aboutCreditsWorldAtlas1),
|
TextSpan(text: l10n.aboutCreditsWorldAtlas1),
|
||||||
const WidgetSpan(
|
const WidgetSpan(
|
||||||
child: LinkChip(
|
child: LinkChip(
|
||||||
text: 'World Atlas',
|
text: 'World Atlas',
|
||||||
|
@ -38,17 +39,19 @@ class AboutCredits extends StatelessWidget {
|
||||||
),
|
),
|
||||||
alignment: PlaceholderAlignment.middle,
|
alignment: PlaceholderAlignment.middle,
|
||||||
),
|
),
|
||||||
TextSpan(text: context.l10n.aboutCreditsWorldAtlas2),
|
TextSpan(text: l10n.aboutCreditsWorldAtlas2),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(context.l10n.aboutCreditsTranslators),
|
Text(l10n.aboutCreditsTranslators),
|
||||||
...translations.map(
|
...translators.entries.map(
|
||||||
(line) => Padding(
|
(kv) {
|
||||||
padding: const EdgeInsetsDirectional.only(start: 8, top: 8),
|
return Padding(
|
||||||
child: Text(line),
|
padding: const EdgeInsetsDirectional.only(start: 8, top: 8),
|
||||||
),
|
child: Text(l10n.aboutCreditsTranslatorLine(kv.key, kv.value)),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
|
|
|
@ -154,7 +154,7 @@ class _TagEditorPageState extends State<TagEditorPage> {
|
||||||
duration: Durations.tagEditorTransition,
|
duration: Durations.tagEditorTransition,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 0),
|
||||||
_FilterRow(
|
_FilterRow(
|
||||||
title: l10n.tagEditorSectionRecent,
|
title: l10n.tagEditorSectionRecent,
|
||||||
filters: recentFilters,
|
filters: recentFilters,
|
||||||
|
|
|
@ -145,7 +145,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.info),
|
const Icon(AIcons.info),
|
||||||
|
@ -154,9 +154,9 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(height: 0),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.only(left: 16, top: 16, right: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
context.l10n.settingsViewerQuickActionEditorDisplayedButtons,
|
context.l10n.settingsViewerQuickActionEditorDisplayedButtons,
|
||||||
style: Constants.titleTextStyle,
|
style: Constants.titleTextStyle,
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
import 'package:aves/model/filters/filters.dart';
|
|
||||||
import 'package:aves/model/filters/path.dart';
|
|
||||||
import 'package:aves/model/settings/settings.dart';
|
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
|
||||||
import 'package:aves/widgets/common/identity/empty.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class HiddenFilterTile extends StatelessWidget {
|
|
||||||
const HiddenFilterTile({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(context.l10n.settingsHiddenFiltersTile),
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
settings: const RouteSettings(name: HiddenFilterPage.routeName),
|
|
||||||
builder: (context) => const HiddenFilterPage(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HiddenFilterPage extends StatelessWidget {
|
|
||||||
static const routeName = '/settings/hidden_filters';
|
|
||||||
|
|
||||||
const HiddenFilterPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(context.l10n.settingsHiddenFiltersTitle),
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
|
||||||
child: Selector<Settings, Set<CollectionFilter>>(
|
|
||||||
selector: (context, s) => settings.hiddenFilters.where((v) => v is! PathFilter).toSet(),
|
|
||||||
builder: (context, hiddenFilters, child) {
|
|
||||||
if (hiddenFilters.isEmpty) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const _Header(),
|
|
||||||
const Divider(),
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: EmptyContent(
|
|
||||||
icon: AIcons.hide,
|
|
||||||
text: context.l10n.settingsHiddenFiltersEmpty,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final filterList = hiddenFilters.toList()..sort();
|
|
||||||
return ListView(
|
|
||||||
children: [
|
|
||||||
const _Header(),
|
|
||||||
const Divider(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Wrap(
|
|
||||||
spacing: 8,
|
|
||||||
runSpacing: 8,
|
|
||||||
children: filterList
|
|
||||||
.map((filter) => AvesFilterChip(
|
|
||||||
filter: filter,
|
|
||||||
removable: true,
|
|
||||||
onTap: (filter) => context.read<CollectionSource>().changeFilterVisibility({filter}, true),
|
|
||||||
onLongPress: null,
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Header extends StatelessWidget {
|
|
||||||
const _Header({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(AIcons.info),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(child: Text(context.l10n.settingsHiddenFiltersBanner)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
198
lib/widgets/settings/privacy/hidden_items.dart
Normal file
198
lib/widgets/settings/privacy/hidden_items.dart
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
import 'package:aves/model/filters/path.dart';
|
||||||
|
import 'package:aves/model/settings/settings.dart';
|
||||||
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
import 'package:aves/services/common/services.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
|
class HiddenItemsTile extends StatelessWidget {
|
||||||
|
const HiddenItemsTile({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(context.l10n.settingsHiddenItemsTile),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
settings: const RouteSettings(name: HiddenItemsPage.routeName),
|
||||||
|
builder: (context) => const HiddenItemsPage(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HiddenItemsPage extends StatelessWidget {
|
||||||
|
static const routeName = '/settings/hidden_items';
|
||||||
|
|
||||||
|
const HiddenItemsPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
final tabs = <Tuple2<Tab, Widget>>[
|
||||||
|
Tuple2(
|
||||||
|
Tab(text: l10n.settingsHiddenFiltersTitle),
|
||||||
|
const _HiddenFilters(),
|
||||||
|
),
|
||||||
|
Tuple2(
|
||||||
|
Tab(text: l10n.settingsHiddenPathsTitle),
|
||||||
|
const _HiddenPaths(),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
return MediaQueryDataProvider(
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: tabs.length,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(l10n.settingsHiddenItemsTitle),
|
||||||
|
bottom: TabBar(
|
||||||
|
tabs: tabs.map((t) => t.item1).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: TabBarView(
|
||||||
|
children: tabs.map((t) => t.item2).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HiddenFilters extends StatelessWidget {
|
||||||
|
const _HiddenFilters({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Selector<Settings, Set<CollectionFilter>>(
|
||||||
|
selector: (context, s) => settings.hiddenFilters.where((v) => v is! PathFilter).toSet(),
|
||||||
|
builder: (context, hiddenFilters, child) {
|
||||||
|
if (hiddenFilters.isEmpty) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_Banner(bannerText: context.l10n.settingsHiddenFiltersBanner),
|
||||||
|
const Divider(height: 0),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: EmptyContent(
|
||||||
|
icon: AIcons.hide,
|
||||||
|
text: context.l10n.settingsHiddenFiltersEmpty,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final filterList = hiddenFilters.toList()..sort();
|
||||||
|
return ListView(
|
||||||
|
children: [
|
||||||
|
_Banner(bannerText: context.l10n.settingsHiddenFiltersBanner),
|
||||||
|
const Divider(height: 0),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
|
||||||
|
child: Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
runSpacing: 8,
|
||||||
|
children: filterList
|
||||||
|
.map((filter) => AvesFilterChip(
|
||||||
|
filter: filter,
|
||||||
|
removable: true,
|
||||||
|
onTap: (filter) => context.read<CollectionSource>().changeFilterVisibility({filter}, true),
|
||||||
|
onLongPress: null,
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HiddenPaths extends StatelessWidget {
|
||||||
|
const _HiddenPaths({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Selector<Settings, Set<PathFilter>>(
|
||||||
|
selector: (context, s) => settings.hiddenFilters.whereType<PathFilter>().toSet(),
|
||||||
|
builder: (context, hiddenPaths, child) {
|
||||||
|
final pathList = hiddenPaths.toList()..sort();
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
_Banner(bannerText: context.l10n.settingsHiddenPathsBanner),
|
||||||
|
const Divider(height: 0),
|
||||||
|
Flexible(
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
children: [
|
||||||
|
...pathList.map((pathFilter) => ListTile(
|
||||||
|
title: Text(pathFilter.path),
|
||||||
|
dense: true,
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(AIcons.clear),
|
||||||
|
onPressed: () {
|
||||||
|
context.read<CollectionSource>().changeFilterVisibility({pathFilter}, true);
|
||||||
|
},
|
||||||
|
tooltip: context.l10n.removeTooltip,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 0),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
AvesOutlinedButton(
|
||||||
|
icon: const Icon(AIcons.add),
|
||||||
|
label: context.l10n.addPathTooltip,
|
||||||
|
onPressed: () async {
|
||||||
|
final path = await storageService.selectDirectory();
|
||||||
|
if (path != null && path.isNotEmpty) {
|
||||||
|
context.read<CollectionSource>().changeFilterVisibility({PathFilter(path)}, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Banner extends StatelessWidget {
|
||||||
|
final String bannerText;
|
||||||
|
|
||||||
|
const _Banner({Key? key, required this.bannerText}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(AIcons.info),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(child: Text(bannerText)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,118 +0,0 @@
|
||||||
import 'package:aves/model/filters/path.dart';
|
|
||||||
import 'package:aves/model/settings/settings.dart';
|
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
|
||||||
import 'package:aves/services/common/services.dart';
|
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
|
||||||
import 'package:aves/widgets/common/identity/empty.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class HiddenPathTile extends StatelessWidget {
|
|
||||||
const HiddenPathTile({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(context.l10n.settingsHiddenPathsTile),
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
settings: const RouteSettings(name: HiddenPathPage.routeName),
|
|
||||||
builder: (context) => const HiddenPathPage(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HiddenPathPage extends StatelessWidget {
|
|
||||||
static const routeName = '/settings/hidden_paths';
|
|
||||||
|
|
||||||
const HiddenPathPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(context.l10n.settingsHiddenPathsTitle),
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(AIcons.add),
|
|
||||||
onPressed: () async {
|
|
||||||
final path = await storageService.selectDirectory();
|
|
||||||
if (path != null && path.isNotEmpty) {
|
|
||||||
context.read<CollectionSource>().changeFilterVisibility({PathFilter(path)}, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: context.l10n.addPathTooltip,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
|
||||||
child: Selector<Settings, Set<PathFilter>>(
|
|
||||||
selector: (context, s) => settings.hiddenFilters.whereType<PathFilter>().toSet(),
|
|
||||||
builder: (context, hiddenPaths, child) {
|
|
||||||
if (hiddenPaths.isEmpty) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const _Header(),
|
|
||||||
const Divider(),
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: EmptyContent(
|
|
||||||
icon: AIcons.hide,
|
|
||||||
text: context.l10n.settingsHiddenPathsEmpty,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final pathList = hiddenPaths.toList()..sort();
|
|
||||||
return ListView(
|
|
||||||
children: [
|
|
||||||
const _Header(),
|
|
||||||
const Divider(),
|
|
||||||
...pathList.map((pathFilter) => ListTile(
|
|
||||||
title: Text(pathFilter.path),
|
|
||||||
dense: true,
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: const Icon(AIcons.clear),
|
|
||||||
onPressed: () {
|
|
||||||
context.read<CollectionSource>().changeFilterVisibility({pathFilter}, true);
|
|
||||||
},
|
|
||||||
tooltip: context.l10n.removeTooltip,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Header extends StatelessWidget {
|
|
||||||
const _Header({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(AIcons.info),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(child: Text(context.l10n.settingsHiddenPathsBanner)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,8 +6,7 @@ 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_expansion_tile.dart';
|
||||||
import 'package:aves/widgets/settings/common/tile_leading.dart';
|
import 'package:aves/widgets/settings/common/tile_leading.dart';
|
||||||
import 'package:aves/widgets/settings/privacy/access_grants.dart';
|
import 'package:aves/widgets/settings/privacy/access_grants.dart';
|
||||||
import 'package:aves/widgets/settings/privacy/hidden_filters.dart';
|
import 'package:aves/widgets/settings/privacy/hidden_items.dart';
|
||||||
import 'package:aves/widgets/settings/privacy/hidden_paths.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -63,8 +62,7 @@ class PrivacySection extends StatelessWidget {
|
||||||
title: Text(context.l10n.settingsSaveSearchHistory),
|
title: Text(context.l10n.settingsSaveSearchHistory),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const HiddenFilterTile(),
|
const HiddenItemsTile(),
|
||||||
const HiddenPathTile(),
|
|
||||||
const StorageAccessTile(),
|
const StorageAccessTile(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
"resetButtonTooltip",
|
"resetButtonTooltip",
|
||||||
"entryInfoActionEditTags",
|
"entryInfoActionEditTags",
|
||||||
"settingsViewerMaximumBrightness",
|
"settingsViewerMaximumBrightness",
|
||||||
|
"settingsHiddenItemsTile",
|
||||||
|
"settingsHiddenItemsTitle",
|
||||||
"tagEditorPageTitle",
|
"tagEditorPageTitle",
|
||||||
"tagEditorPageNewTagFieldLabel",
|
"tagEditorPageNewTagFieldLabel",
|
||||||
"tagEditorPageAddTagTooltip"
|
"tagEditorPageAddTagTooltip"
|
||||||
|
|
Loading…
Reference in a new issue