diff --git a/lib/api/client.dart b/lib/api/client.dart index 431f167..fee9042 100644 --- a/lib/api/client.dart +++ b/lib/api/client.dart @@ -43,6 +43,22 @@ enum ThumbnailAlign { static const bottom = right; } +enum SortByGid { + none, + asc, + desc; + bool? toBool() { + switch (this) { + case SortByGid.asc: + return true; + case SortByGid.desc: + return false; + default: + return null; + } + } +} + @RestApi() abstract class _EHApi { factory _EHApi(Dio dio, {required String baseUrl}) = __EHApi; @@ -130,6 +146,7 @@ abstract class _EHApi { {@Query("all") bool? all, @Query("offset") int? offset, @Query("limit") int? limit, + @Query("sort_by_gid") bool? sortByGid, @CancelRequest() CancelToken? cancel}); @GET('/tag/{id}') diff --git a/lib/api/client.g.dart b/lib/api/client.g.dart index d400d7f..da14bb8 100644 --- a/lib/api/client.g.dart +++ b/lib/api/client.g.dart @@ -530,6 +530,7 @@ class __EHApi implements _EHApi { bool? all, int? offset, int? limit, + bool? sortByGid, CancelToken? cancel, }) async { const _extra = {}; @@ -537,6 +538,7 @@ class __EHApi implements _EHApi { r'all': all, r'offset': offset, r'limit': limit, + r'sort_by_gid': sortByGid, }; queryParameters.removeWhere((k, v) => v == null); final _headers = {}; diff --git a/lib/galleries.dart b/lib/galleries.dart index 1bae5d6..cb3ed2a 100644 --- a/lib/galleries.dart +++ b/lib/galleries.dart @@ -3,13 +3,15 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:go_router/go_router.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:logging/logging.dart'; +import 'api/client.dart'; import 'api/gallery.dart'; import 'globals.dart'; final _log = Logger("GalleriesPage"); class GalleriesPage extends StatefulWidget { - const GalleriesPage({Key? key}) : super(key: key); + const GalleriesPage({Key? key, this.sortByGid}) : super(key: key); + final SortByGid? sortByGid; static const String routeName = '/galleries'; @@ -19,14 +21,17 @@ class GalleriesPage extends StatefulWidget { class _GalleriesPage extends State with ThemeModeWidget { static const int _pageSize = 20; + bool? _sortByGid; + SortByGid _sortByGid2 = SortByGid.none; final PagingController _pagingController = PagingController(firstPageKey: 0); Future _fetchPage(int pageKey) async { try { - final list = - (await api.listGalleries(offset: pageKey, limit: _pageSize)).unwrap(); + final list = (await api.listGalleries( + offset: pageKey, limit: _pageSize, sortByGid: _sortByGid)) + .unwrap(); final isLastPage = list.length < _pageSize; if (isLastPage) { _pagingController.appendLastPage(list); @@ -42,6 +47,14 @@ class _GalleriesPage extends State with ThemeModeWidget { @override void initState() { + try { + _sortByGid2 = widget.sortByGid != null + ? widget.sortByGid! + : SortByGid.values[prefs.getInt("sortByGid") ?? 0]; + _sortByGid = _sortByGid2.toBool(); + } catch (e) { + _log.warning("Failed to load sortByGid from prefs:", e); + } _pagingController.addPageRequestListener((pageKey) { _fetchPage(pageKey); }); @@ -61,6 +74,37 @@ class _GalleriesPage extends State with ThemeModeWidget { ), title: Text(AppLocalizations.of(context)!.galleries), actions: [ + Padding( + padding: const EdgeInsets.only(top: 4.0), + child: DropdownMenu( + initialSelection: _sortByGid2, + onSelected: (v) { + if (v != null) { + prefs.setInt("sortByGid", v!.index).catchError((error) { + _log.warning( + "Failed to save sortByGid to prefs:", error); + }); + context.pushReplacementNamed("/galleries", + queryParameters: { + "sortByGid": [v!.index.toString()], + }); + } + }, + label: Text(AppLocalizations.of(context)!.sortByGid, + style: Theme.of(context).primaryTextTheme.labelMedium), + 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), + ], + leadingIcon: const Icon(Icons.sort), + )), buildThemeModeIcon(context), buildMoreVertSettingsButon(context), ]), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4336235..e313588 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -31,5 +31,9 @@ "copyImgUrl": "Copy image URL to clipboard", "retry": "Retry", "displayAd": "Display Ad pages", - "showTranslatedTag": "Show translated tag (Chinese only)" + "showTranslatedTag": "Show translated tag (Chinese only)", + "none": "none", + "sortByGid": "Sort by gallery id", + "asc": "Ascending", + "desc": "Descending" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 7ecb011..9997bcc 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -31,5 +31,9 @@ "copyImgUrl": "复制图片链接到剪贴板", "retry": "重试", "displayAd": "显示广告页面", - "showTranslatedTag": "显示标签翻译(仅限中文)" + "showTranslatedTag": "显示标签翻译(仅限中文)", + "none": "无", + "sortByGid": "按画廊ID排序", + "asc": "升序", + "desc": "降序" } diff --git a/lib/main.dart b/lib/main.dart index 3989329..b7db6b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:flutter_web_plugins/url_strategy.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:window_manager/window_manager.dart'; +import 'api/client.dart'; import 'create_root_user.dart'; import 'galleries.dart'; import 'gallery.dart'; @@ -42,9 +43,20 @@ final _router = GoRouter( builder: (context, state) => const SettingsPage(), ), GoRoute( - path: GalleriesPage.routeName, - builder: (context, state) => const GalleriesPage(), - ), + name: GalleriesPage.routeName, + path: GalleriesPage.routeName, + builder: (context, state) { + SortByGid? sortByGid; + try { + if (state.uri.queryParameters.containsKey("sortByGid")) { + sortByGid = SortByGid + .values[int.parse(state.uri.queryParameters["sortByGid"]!)]; + } + } catch (e) { + _routerLog.warning("Failed to load sortByGid from prefs:", e); + } + return GalleriesPage(sortByGid: sortByGid); + }), GoRoute( path: GalleryPage.routeName, builder: (context, state) => GalleryPage(