diff --git a/lib/components/tag.dart b/lib/components/tag.dart new file mode 100644 index 0000000..96d2ff3 --- /dev/null +++ b/lib/components/tag.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import '../api/gallery.dart'; +import '../globals.dart'; + +class TagWidget extends StatelessWidget { + const TagWidget(this.tag, {Key? key, this.name}) : super(key: key); + final Tag tag; + final String? name; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + context.pushNamed("/galleries", + queryParameters: { + "tag": [tag.tag] + }, + extra: GalleriesPageExtra(translatedTag: tag.translated)); + }, + child: Text(name ?? tag.tag)); + } +} diff --git a/lib/components/tag_tooltip.dart b/lib/components/tag_tooltip.dart index 2897d85..b9934fe 100644 --- a/lib/components/tag_tooltip.dart +++ b/lib/components/tag_tooltip.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - import '../api/gallery.dart'; +import 'tag.dart'; String _getTag(Tag tag) { final tags = tag.tag.split(":"); @@ -17,13 +16,7 @@ class TagTooltip extends StatelessWidget { @override Widget build(BuildContext context) { final name = _getTag(tag); - final t = InkWell( - onTap: () { - context.pushNamed("/galleries", queryParameters: { - "tag": [tag.tag] - }); - }, - child: Text(name)); + final t = TagWidget(tag, name: name); return tag.intro != null && tag.intro!.isNotEmpty ? Tooltip( message: tag.intro!, diff --git a/lib/components/tags.dart b/lib/components/tags.dart index 245b4c1..d52daac 100644 --- a/lib/components/tags.dart +++ b/lib/components/tags.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:go_router/go_router.dart'; import '../api/gallery.dart'; import '../globals.dart'; import '../main.dart'; +import 'tag.dart'; import 'tag_tooltip.dart'; import 'scroll_parent.dart'; @@ -74,13 +74,7 @@ class _TagsPanel extends State { ), child: stt ? TagTooltip(ta[index - 1]!) - : InkWell( - onTap: () { - context.pushNamed("/galleries", queryParameters: { - "tag": [ta[index - 1]!.tag] - }); - }, - child: Text(ta[index - 1]!.tag))); + : TagWidget(ta[index - 1]!)); } })); }); diff --git a/lib/galleries.dart b/lib/galleries.dart index f9c008f..6a9f444 100644 --- a/lib/galleries.dart +++ b/lib/galleries.dart @@ -6,15 +6,28 @@ import 'package:logging/logging.dart'; import 'api/client.dart'; import 'api/gallery.dart'; import 'globals.dart'; +import 'main.dart'; final _log = Logger("GalleriesPage"); +class GalleriesPageExtra { + const GalleriesPageExtra({this.translatedTag}); + final String? translatedTag; +} + class GalleriesPage extends StatefulWidget { - const GalleriesPage({Key? key, this.sortByGid, this.uploader, this.tag}) + const GalleriesPage( + {Key? key, this.sortByGid, this.uploader, this.tag, this.translatedTag}) : super(key: key); final SortByGid? sortByGid; final String? uploader; final String? tag; + final String? translatedTag; + bool _stt(BuildContext context) => + prefs.getBool("showTranslatedTag") ?? + MainApp.of(context).lang.toLocale().languageCode == "zh"; + String? preferredTag(BuildContext context) => + _stt(context) ? translatedTag ?? tag : tag; static const String routeName = '/galleries'; @@ -22,7 +35,8 @@ class GalleriesPage extends StatefulWidget { State createState() => _GalleriesPage(); } -class _GalleriesPage extends State with ThemeModeWidget { +class _GalleriesPage extends State + with ThemeModeWidget, IsTopWidget2 { static const int _pageSize = 20; bool? _sortByGid; SortByGid _sortByGid2 = SortByGid.none; @@ -71,6 +85,7 @@ class _GalleriesPage extends State with ThemeModeWidget { @override Widget build(BuildContext context) { tryInitApi(context); + final i18n = AppLocalizations.of(context)!; final sortByGidMenu = DropdownMenu( initialSelection: _sortByGid2, onSelected: (v) { @@ -90,22 +105,28 @@ class _GalleriesPage extends State with ThemeModeWidget { queryParameters: queryParameters); } }, - label: Text(AppLocalizations.of(context)!.sortByGid, + label: Text(i18n.sortByGid, style: MediaQuery.of(context).size.width > 810 ? Theme.of(context).textTheme.labelMedium : Theme.of(context).textTheme.labelLarge), dropdownMenuEntries: [ - DropdownMenuEntry( - value: SortByGid.none, label: AppLocalizations.of(context)!.none), - DropdownMenuEntry( - value: SortByGid.asc, label: AppLocalizations.of(context)!.asc), - DropdownMenuEntry( - value: SortByGid.desc, label: AppLocalizations.of(context)!.desc), + DropdownMenuEntry(value: SortByGid.none, label: i18n.none), + DropdownMenuEntry(value: SortByGid.asc, label: i18n.asc), + DropdownMenuEntry(value: SortByGid.desc, label: i18n.desc), ], leadingIcon: const Icon(Icons.sort), ); - setCurrentTitle(AppLocalizations.of(context)!.galleries, - Theme.of(context).primaryColor.value); + final title = widget.uploader != null && widget.tag != null + ? i18n.tagUploaderGalleries( + widget.preferredTag(context)!, widget.uploader!) + : widget.uploader != null + ? i18n.uploaderGalleries(widget.uploader!) + : widget.tag != null + ? i18n.tagGalleries(widget.preferredTag(context)!) + : i18n.galleries; + if (isTop(context)) { + setCurrentTitle(title, Theme.of(context).primaryColor.value); + } return Scaffold( appBar: AppBar( leading: IconButton( @@ -114,7 +135,7 @@ class _GalleriesPage extends State with ThemeModeWidget { context.canPop() ? context.pop() : context.go("/"); }, ), - title: Text(AppLocalizations.of(context)!.galleries), + title: Text(title), actions: [ MediaQuery.of(context).size.width > 810 ? Padding( diff --git a/lib/gallery.dart b/lib/gallery.dart index 8ad35b7..d3ea169 100644 --- a/lib/gallery.dart +++ b/lib/gallery.dart @@ -29,7 +29,8 @@ class GalleryPage extends StatefulWidget { State createState() => _GalleryPage(); } -class _GalleryPage extends State with ThemeModeWidget { +class _GalleryPage extends State + with ThemeModeWidget, IsTopWidget2 { _GalleryPage(); int _gid = 0; GalleryData? _data; @@ -84,14 +85,16 @@ class _GalleryPage extends State with ThemeModeWidget { : _data != null ? _data!.meta.preferredTitle : i18n.gallery; - if (!kIsWeb || (_data != null && kIsWeb)) { - setCurrentTitle(title, Theme.of(context).primaryColor.value, - includePrefix: false); - } else if (kIsWeb && widget.title != null) { - // 设置预加载标题 - // Chrome 和 Firefox 必须尽快设置标题以确保在历史记录菜单显示正确的标题 - setCurrentTitle(widget.title!, Theme.of(context).primaryColor.value, - includePrefix: false); + if (isTop(context)) { + if (!kIsWeb || (_data != null && kIsWeb)) { + setCurrentTitle(title, Theme.of(context).primaryColor.value, + includePrefix: false); + } else if (kIsWeb && widget.title != null) { + // 设置预加载标题 + // Chrome 和 Firefox 必须尽快设置标题以确保在历史记录菜单显示正确的标题 + setCurrentTitle(widget.title!, Theme.of(context).primaryColor.value, + includePrefix: false); + } } return Scaffold( appBar: _data == null diff --git a/lib/globals.dart b/lib/globals.dart index 214079e..b0563ed 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -25,6 +25,7 @@ import 'platform/clipboard.dart'; import 'platform/path.dart'; import 'tags.dart'; import 'utils.dart'; +export 'galleries.dart' show GalleriesPageExtra; export 'gallery.dart' show GalleryPageExtra; final dio = Dio() @@ -243,6 +244,32 @@ mixin ThemeModeWidget on State { } } +mixin IsTopWidget on Widget { + @protected + bool isTop(BuildContext context) { + final last = GoRouter.of(context) + .routerDelegate + .currentConfiguration + .matches + .last + .pageKey; + return last == key; + } +} + +mixin IsTopWidget2 on State { + @protected + bool isTop(BuildContext context) { + final last = GoRouter.of(context) + .routerDelegate + .currentConfiguration + .matches + .last + .pageKey; + return last == widget.key; + } +} + enum Lang { system("System"), english("English"), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index e69fd5a..2cc8676 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -52,5 +52,32 @@ } } }, - "gid": "Gallery Id" + "gid": "Gallery Id", + "tagGalleries": "Galleries tagged {tag}", + "@tagGalleries": { + "placeholders": { + "tag": { + "type": "String" + } + } + }, + "tagUploaderGalleries": "Galleries tagged {tag} by {uploader}", + "@tagUploaderGalleries": { + "placeholders": { + "tag": { + "type": "String" + }, + "uploader": { + "type": "String" + } + } + }, + "uploaderGalleries": "Galleries uploaded by {uploader}", + "@uploaderGalleries": { + "placeholders": { + "uploader": { + "type": "String" + } + } + } } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index e50d941..7c3d85d 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -52,5 +52,32 @@ } } }, - "gid": "画廊ID" + "gid": "画廊ID", + "tagGalleries": "带有 {tag} 标签的画廊", + "@tagGalleries": { + "placeholders": { + "tag": { + "type": "String" + } + } + }, + "tagUploaderGalleries": "{uploader} 上传的带有 {tag} 标签的画廊", + "@tagUploaderGalleries": { + "placeholders": { + "tag": { + "type": "String" + }, + "uploader": { + "type": "String" + } + } + }, + "uploaderGalleries": "{uploader} 上传的画廊", + "@uploaderGalleries": { + "placeholders": { + "uploader": { + "type": "String" + } + } + } } diff --git a/lib/main.dart b/lib/main.dart index a135b3d..a5dde05 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -57,8 +57,13 @@ final _router = GoRouter( } final tag = state.uri.queryParameters["tag"]; final uploader = state.uri.queryParameters["uploader"]; + final extra = state.extra as GalleriesPageExtra?; return GalleriesPage( - sortByGid: sortByGid, tag: tag, uploader: uploader); + key: state.pageKey, + sortByGid: sortByGid, + tag: tag, + uploader: uploader, + translatedTag: extra?.translatedTag); }), GoRoute( path: GalleryPage.routeName, @@ -66,6 +71,7 @@ final _router = GoRouter( final extra = state.extra as GalleryPageExtra?; return GalleryPage( int.parse(state.pathParameters["gid"]!), + key: state.pageKey, title: extra?.title, ); },