minor fixes

This commit is contained in:
Thibault Deckers 2021-11-25 18:45:37 +09:00
parent b3500edd10
commit fcca4776c6
12 changed files with 248 additions and 266 deletions

View file

@ -505,6 +505,17 @@
"@aboutCreditsWorldAtlas2": {},
"aboutCreditsTranslators": "Translators:",
"@aboutCreditsTranslators": {},
"aboutCreditsTranslatorLine": "{language}: {names}",
"@aboutCreditsTranslatorLine": {
"placeholders": {
"language": {
"type": "String"
},
"names": {
"type": "String"
}
}
},
"aboutLicenses": "Open-Source Licenses",
"@aboutLicenses": {},
@ -893,8 +904,11 @@
"settingsSaveSearchHistory": "Save search history",
"@settingsSaveSearchHistory": {},
"settingsHiddenFiltersTile": "Hidden filters",
"@settingsHiddenFiltersTile": {},
"settingsHiddenItemsTile": "Hidden items",
"@settingsHiddenItemsTile": {},
"settingsHiddenItemsTitle": "Hidden Items",
"@settingsHiddenItemsTitle": {},
"settingsHiddenFiltersTitle": "Hidden Filters",
"@settingsHiddenFiltersTitle": {},
"settingsHiddenFiltersBanner": "Photos and videos matching hidden filters will not appear in your collection.",
@ -902,14 +916,10 @@
"settingsHiddenFiltersEmpty": "No hidden filters",
"@settingsHiddenFiltersEmpty": {},
"settingsHiddenPathsTile": "Hidden paths",
"@settingsHiddenPathsTile": {},
"settingsHiddenPathsTitle": "Hidden Paths",
"@settingsHiddenPathsTitle": {},
"settingsHiddenPathsBanner": "Photos and videos in these folders, or any of their subfolders, will not appear in your collection.",
"@settingsHiddenPathsBanner": {},
"settingsHiddenPathsEmpty": "No hidden paths",
"@settingsHiddenPathsEmpty": {},
"addPathTooltip": "Add path",
"@addPathTooltip": {},

View file

@ -24,7 +24,7 @@
"removeTooltip": "Supprimer",
"resetButtonTooltip": "Réinitialiser",
"doubleBackExitMessage": "Presser «\u00A0retour\u00A0» à nouveau pour quitter.",
"doubleBackExitMessage": "Pressez «\u00A0retour\u00A0» à nouveau pour quitter.",
"sourceStateLoading": "Chargement",
"sourceStateCataloguing": "Classification",
@ -233,7 +233,8 @@
"aboutCredits": "Remerciements",
"aboutCreditsWorldAtlas1": "Cette app utilise un fichier TopoJSON de ",
"aboutCreditsWorldAtlas2": "sous licence ISC.",
"aboutCreditsTranslators": "Traducteurs:",
"aboutCreditsTranslators": "Traducteurs :",
"aboutCreditsTranslatorLine": "{language} : {names}",
"aboutLicenses": "Licences open-source",
"aboutLicensesBanner": "Cette app utilise ces librairies et packages open-source.",
@ -426,15 +427,15 @@
"settingsAllowErrorReporting": "Autoriser lenvoi de rapports derreur",
"settingsSaveSearchHistory": "Maintenir un historique des recherches",
"settingsHiddenFiltersTile": "Filtres masqués",
"settingsHiddenItemsTile": "Éléments masqués",
"settingsHiddenItemsTitle": "Éléments masqués",
"settingsHiddenFiltersTitle": "Filtres masqués",
"settingsHiddenFiltersBanner": "Les images et vidéos correspondantes aux filtres masqués napparaîtront pas dans votre collection.",
"settingsHiddenFiltersEmpty": "Aucun filtre masqué",
"settingsHiddenPathsTile": "Chemins masqués",
"settingsHiddenPathsTitle": "Chemins masqués",
"settingsHiddenPathsBanner": "Les images et vidéos dans ces dossiers, ou leurs sous-dossiers, napparaîtront pas dans votre collection.",
"settingsHiddenPathsEmpty": "Aucun chemin masqué",
"addPathTooltip": "Ajouter un chemin",
"settingsStorageAccessTile": "Accès au stockage",

View file

@ -233,6 +233,7 @@
"aboutCreditsWorldAtlas1": "이 앱은",
"aboutCreditsWorldAtlas2": "의 TopoJSON 파일(ISC 라이선스)을 이용합니다.",
"aboutCreditsTranslators": "번역가:",
"aboutCreditsTranslatorLine": "{language}: {names}",
"aboutLicenses": "오픈 소스 라이선스",
"aboutLicensesBanner": "이 앱은 다음의 오픈 소스 패키지와 라이브러리를 이용합니다.",
@ -425,15 +426,15 @@
"settingsAllowErrorReporting": "오류 보고서 보내기",
"settingsSaveSearchHistory": "검색기록",
"settingsHiddenFiltersTile": "숨겨진 필터",
"settingsHiddenItemsTile": "숨겨진 항목",
"settingsHiddenItemsTitle": "숨겨진 항목",
"settingsHiddenFiltersTitle": "숨겨진 필터",
"settingsHiddenFiltersBanner": "이 필터에 맞는 사진과 동영상이 숨겨지고 있으며 이 앱에서 보여지지 않을 것입니다.",
"settingsHiddenFiltersEmpty": "숨겨진 필터가 없습니다",
"settingsHiddenPathsTile": "숨겨진 경로",
"settingsHiddenPathsTitle": "숨겨진 경로",
"settingsHiddenPathsBanner": "이 경로에 있는 사진과 동영상이 숨겨지고 있으며 이 앱에서 보여지지 않을 것입니다.",
"settingsHiddenPathsEmpty": "숨겨진 경로가 없습니다",
"addPathTooltip": "경로 추가",
"settingsStorageAccessTile": "저장공간 접근",

View file

@ -232,6 +232,7 @@
"aboutCreditsWorldAtlas1": "Это приложение использует файл TopoJSON из",
"aboutCreditsWorldAtlas2": "под лицензией ISC.",
"aboutCreditsTranslators": "Переводчики:",
"aboutCreditsTranslatorLine": "{language}: {names}",
"aboutLicenses": "Лицензии с открытым исходным кодом",
"aboutLicensesBanner": "Это приложение использует следующие пакеты и библиотеки с открытым исходным кодом.",
@ -423,15 +424,12 @@
"settingsAllowErrorReporting": "Разрешить анонимную отправку логов",
"settingsSaveSearchHistory": "Сохранять историю поиска",
"settingsHiddenFiltersTile": "Скрытые фильтры",
"settingsHiddenFiltersTitle": "Скрытые фильтры",
"settingsHiddenFiltersBanner": "Фотографии и видео, соответствующие скрытым фильтрам, не появятся в вашей коллекции.",
"settingsHiddenFiltersEmpty": "Нет скрытых фильтров",
"settingsHiddenPathsTile": "Скрытые каталоги",
"settingsHiddenPathsTitle": "Скрытые каталоги",
"settingsHiddenPathsBanner": "Фотографии и видео в этих каталогах или любых их вложенных каталогах не будут отображаться в вашей коллекции.",
"settingsHiddenPathsEmpty": "Нет скрытых каталогов",
"addPathTooltip": "Добавить каталог",
"settingsStorageAccessTile": "Доступ к хранилищу",

View file

@ -8,12 +8,13 @@ import 'package:flutter/material.dart';
class AboutCredits extends StatelessWidget {
const AboutCredits({Key? key}) : super(key: key);
static const translations = [
'Русский: D3ZOXY',
];
static const translators = {
'Русский': 'D3ZOXY',
};
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
@ -23,13 +24,13 @@ class AboutCredits extends StatelessWidget {
constraints: const BoxConstraints(minHeight: 48),
child: Align(
alignment: AlignmentDirectional.centerStart,
child: Text(context.l10n.aboutCredits, style: Constants.titleTextStyle),
child: Text(l10n.aboutCredits, style: Constants.titleTextStyle),
),
),
Text.rich(
TextSpan(
children: [
TextSpan(text: context.l10n.aboutCreditsWorldAtlas1),
TextSpan(text: l10n.aboutCreditsWorldAtlas1),
const WidgetSpan(
child: LinkChip(
text: 'World Atlas',
@ -38,17 +39,19 @@ class AboutCredits extends StatelessWidget {
),
alignment: PlaceholderAlignment.middle,
),
TextSpan(text: context.l10n.aboutCreditsWorldAtlas2),
TextSpan(text: l10n.aboutCreditsWorldAtlas2),
],
),
),
const SizedBox(height: 16),
Text(context.l10n.aboutCreditsTranslators),
...translations.map(
(line) => Padding(
padding: const EdgeInsetsDirectional.only(start: 8, top: 8),
child: Text(line),
),
Text(l10n.aboutCreditsTranslators),
...translators.entries.map(
(kv) {
return Padding(
padding: const EdgeInsetsDirectional.only(start: 8, top: 8),
child: Text(l10n.aboutCreditsTranslatorLine(kv.key, kv.value)),
);
},
),
const SizedBox(height: 16),
],

View file

@ -154,7 +154,7 @@ class _TagEditorPageState extends State<TagEditorPage> {
duration: Durations.tagEditorTransition,
),
),
const Divider(height: 1),
const Divider(height: 0),
_FilterRow(
title: l10n.tagEditorSectionRecent,
filters: recentFilters,

View file

@ -145,7 +145,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
child: ListView(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
padding: const EdgeInsets.all(16),
child: Row(
children: [
const Icon(AIcons.info),
@ -154,9 +154,9 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
],
),
),
const Divider(),
const Divider(height: 0),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
padding: const EdgeInsets.only(left: 16, top: 16, right: 16),
child: Text(
context.l10n.settingsViewerQuickActionEditorDisplayedButtons,
style: Constants.titleTextStyle,

View file

@ -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)),
],
),
);
}
}

View 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)),
],
),
);
}
}

View file

@ -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)),
],
),
);
}
}

View file

@ -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/settings/common/tile_leading.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_paths.dart';
import 'package:aves/widgets/settings/privacy/hidden_items.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -63,8 +62,7 @@ class PrivacySection extends StatelessWidget {
title: Text(context.l10n.settingsSaveSearchHistory),
),
),
const HiddenFilterTile(),
const HiddenPathTile(),
const HiddenItemsTile(),
const StorageAccessTile(),
],
);

View file

@ -10,6 +10,8 @@
"resetButtonTooltip",
"entryInfoActionEditTags",
"settingsViewerMaximumBrightness",
"settingsHiddenItemsTile",
"settingsHiddenItemsTitle",
"tagEditorPageTitle",
"tagEditorPageNewTagFieldLabel",
"tagEditorPageAddTagTooltip"