From 412bc43cbf76a3892cc378c2cc8194d6b9ba2cf0 Mon Sep 17 00:00:00 2001 From: DattatreyaReddy Panta <58727124+DattatreyaReddy@users.noreply.github.com> Date: Wed, 14 Dec 2022 15:54:50 +0530 Subject: [PATCH] Bug fixes & new features for v0.3.1 (#93) * Added refresh button & fixed images cropping in single page screen * addded resume button to manga details screen * added last page read support * version bump to v0.3.1 --- README.md | 2 +- assets/locales/en_US.json | 119 ++++++++--------- .../about/widget/clipboard_list_tile.dart | 8 +- .../extension/extension_screen.dart | 3 +- .../widgets/extension_list_tile.dart | 5 +- .../presentation/source/source_screen.dart | 3 +- .../category/edit_category_screen.dart | 3 +- .../manga_details/manga_details_screen.dart | 42 +++++- .../widgets/big_screen_manga_details.dart | 1 + .../widgets/chapter_list_tile.dart | 29 ++++- .../widgets/manga_description.dart | 28 ++-- .../widgets/small_screen_manga_details.dart | 1 + .../presentation/reader/reader_screen.dart | 116 ++++++++--------- .../reader_mode/single_page_reader_mode.dart | 23 ++-- .../reader_mode/webtoon_reader_mode.dart | 18 ++- .../presentation/updates/updates_screen.dart | 3 +- .../widgets/chapter_manga_list_tile.dart | 4 +- .../multi_chapters_action_icon.dart | 3 +- .../single_chapter_action_icon.dart | 3 +- .../widgets/update_status_popup_menu.dart | 3 +- .../presentation/more/more_screen.dart | 6 +- .../presentation/server/server_screen.dart | 8 +- lib/src/i18n/codegen_loader.g.dart | 99 +++++++------- lib/src/i18n/locale_keys.g.dart | 121 +++++++++--------- .../custom_extensions/int_extensions.dart | 3 + lib/src/utils/misc/toast/toast.dart | 19 ++- pubspec.lock | 4 +- pubspec.yaml | 2 +- 28 files changed, 392 insertions(+), 287 deletions(-) diff --git a/README.md b/README.md index de9abed7..89d0fd9e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Tachidesk Sorayomi logo + Tachidesk Sorayomi logo

Tachidesk Sorayomi

diff --git a/assets/locales/en_US.json b/assets/locales/en_US.json index 96c345dc..2dcfce88 100644 --- a/assets/locales/en_US.json +++ b/assets/locales/en_US.json @@ -1,68 +1,17 @@ { - "AuthType": { - "basic": "Basic Auth", - "none": "None" - }, - "ChapterSort": { - "fetchedDate": "By Fetched Data", - "source": "By Source" - }, - "DisplayMode": { - "descriptiveList": "Descriptive List", - "grid": "Grid", - "list": "List" - }, - "MangaSort": { - "alphabetical": "Alphabetical", - "dateAdded": "Date Added", - "unread": "Unread" - }, - "MangaStatus": { - "cancelled": "Cancelled", - "completed": "Completed", - "licensed": "Licensed", - "onHiatus": "On Hiatus", - "ongoing": "Ongoing", - "publishingFinished": "Publishing Finished", - "unknown": "Unknown" - }, - "ReaderMode": { - "continuousHorizontalLTR": "Continuous Horizontal (LTR)", - "continuousHorizontalRTL": "Continuous Horizontal (RTL)", - "continuousVertical": "Continuous Vertical", - "defaultReader": "Default", - "singleHorizontalLTR": "Single Horizontal (LTR)", - "singleHorizontalRTL": "Single Horizontal (RTL)", - "singleVertical": "Single Vertical", - "webtoon": "Webtoon" - }, - "ReaderNavigationLayout": { - "disabled": "Disabled", - "edge": "Edge", - "kindlish": "Kindle-ish", - "lShaped": "L Shaped", - "rightAndLeft": "Right and Left", - "defaultNavigation": "Default" - }, - "SourceType": { - "filter": "Filter", - "latest": "Latest", - "popular": "Popular" - }, - "ThemeMode": { - "dark": "Dark", - "light": "Light", - "system": "System" - }, "about": "About", "add": "Add", "addCategory": "Add Category", "addCategoryHint": "Add new categories in settings", "addToLibrary": "Add to Library", + "appearance": "Appearance", "appTheme": "App Theme", "appTitle": "Tachidesk Sorayomi", - "appearance": "Appearance", "artist": "Artist", + "AuthType": { + "basic": "Basic Auth", + "none": "None" + }, "backup": "Backup & Restore", "badges": "Badges", "baseAuthType": "Authentication Type", @@ -87,6 +36,10 @@ }, "chapterNumber": "Chapter {number}", "chapters": "Chapters", + "ChapterSort": { + "fetchedDate": "By Fetched Data", + "source": "By Source" + }, "checkForServerUpdates": "Check for Server updates", "checkForUpdates": "Check for updates", "client": "Client", @@ -110,6 +63,11 @@ "discord": "Discord", "display": "Display", "displayMode": "Display Mode", + "DisplayMode": { + "descriptiveList": "Descriptive List", + "grid": "Grid", + "list": "List" + }, "downloaded": "Downloaded", "downloads": "Downloads", "edit": "Edit", @@ -152,6 +110,20 @@ "loading": "Loading!", "manga": "Manga", "mangaSearch": "Search manga..", + "MangaSort": { + "alphabetical": "Alphabetical", + "dateAdded": "Date Added", + "unread": "Unread" + }, + "MangaStatus": { + "cancelled": "Cancelled", + "completed": "Completed", + "licensed": "Licensed", + "ongoing": "Ongoing", + "onHiatus": "On Hiatus", + "publishingFinished": "Publishing Finished", + "unknown": "Unknown" + }, "missingExtension": "Missing Extensions", "missingTrackers": "Missing Trackers", "more": "More", @@ -178,6 +150,7 @@ }, "nsfw18": "18+", "numSelected": "{num} Selected", + "page": "Page: {number}", "password": "Password", "pause": "Pause", "pending": "Pending", @@ -185,9 +158,27 @@ "previousChapter": "Previous Chapter", "reader": "Reader", "readerMode": "Reading Mode", + "ReaderMode": { + "continuousHorizontalLTR": "Continuous Horizontal (LTR)", + "continuousHorizontalRTL": "Continuous Horizontal (RTL)", + "continuousVertical": "Continuous Vertical", + "defaultReader": "Default", + "singleHorizontalLTR": "Single Horizontal (LTR)", + "singleHorizontalRTL": "Single Horizontal (RTL)", + "singleVertical": "Single Vertical", + "webtoon": "Webtoon" + }, "readerNavigationLayout": "Navigation layout", - "readerNavigationLayoutInvert": "Invert tapping", + "ReaderNavigationLayout": { + "defaultNavigation": "Default", + "disabled": "Disabled", + "edge": "Edge", + "kindlish": "Kindle-ish", + "lShaped": "L Shaped", + "rightAndLeft": "Right and Left" + }, "readerNavigationLayout_": "Navigation layout", + "readerNavigationLayoutInvert": "Invert tapping", "readerSettingsView": "Reader Settings", "reddit": "Reddit", "refresh": "Refresh", @@ -206,8 +197,8 @@ "savedImagePathTitle": "Image path saved to Clipboard", "search": "Search...", "searchGlobally": "Search Globally", - "searchManga": "Search manga..", "searchingForUpdates": "Searching for updates...", + "searchManga": "Search manga..", "server": "Server", "serverVersion": "Server version", "setAsDefault": "Set as default", @@ -225,7 +216,18 @@ "sortUnread": "Unread", "source": "Source", "sources": "Sources", + "SourceType": { + "filter": "Filter", + "latest": "Latest", + "popular": "Popular" + }, + "start": "Start", "status": "Status", + "ThemeMode": { + "dark": "Dark", + "light": "Light", + "system": "System" + }, "uninstall": "Uninstall", "uninstalling": "Uninstalling", "unknown": "Unknown", @@ -234,6 +236,7 @@ "unknownSource": "Unknown Source", "unread": "Unread", "update": "Update", + "updateCompleted": "Update Completed", "updates": "Updates", "updatesSummary": "Updates Summary", "updating": "Updating", diff --git a/lib/src/features/about/presentation/about/widget/clipboard_list_tile.dart b/lib/src/features/about/presentation/about/widget/clipboard_list_tile.dart index d851b55f..1a207ad6 100644 --- a/lib/src/features/about/presentation/about/widget/clipboard_list_tile.dart +++ b/lib/src/features/about/presentation/about/widget/clipboard_list_tile.dart @@ -23,7 +23,6 @@ class ClipboardListTile extends ConsumerWidget { final String? subtitle; @override Widget build(BuildContext context, WidgetRef ref) { - final Toast toast = ref.watch(toastProvider(context)); return ListTile( title: Text(title), subtitle: subtitle.isNotBlank ? Text(subtitle!) : null, @@ -33,10 +32,9 @@ class ClipboardListTile extends ConsumerWidget { Clipboard.setData( ClipboardData(text: msg), ); - toast.close(); - toast.show( - LocaleKeys.copyMsg.tr(namedArgs: {"msg": msg}), - ); + ref.read(toastProvider(context)).instantShow( + LocaleKeys.copyMsg.tr(namedArgs: {"msg": msg}), + ); } : null, ); diff --git a/lib/src/features/browse_center/presentation/extension/extension_screen.dart b/lib/src/features/browse_center/presentation/extension/extension_screen.dart index 5e4d618b..f0b66d0f 100644 --- a/lib/src/features/browse_center/presentation/extension/extension_screen.dart +++ b/lib/src/features/browse_center/presentation/extension/extension_screen.dart @@ -51,9 +51,8 @@ class ExtensionScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); final extensionMapData = ref.watch(extensionMapFilteredAndQueriedProvider) - ..showToastOnError(toast, withMicrotask: true); + ..showToastOnError(ref.read(toastProvider(context)), withMicrotask: true); final extensionMap = {...?extensionMapData.valueOrNull}; final installed = extensionMap.remove("installed"); final update = extensionMap.remove("update"); diff --git a/lib/src/features/browse_center/presentation/extension/widgets/extension_list_tile.dart b/lib/src/features/browse_center/presentation/extension/widgets/extension_list_tile.dart index 16c7ba50..ab41a46c 100644 --- a/lib/src/features/browse_center/presentation/extension/widgets/extension_list_tile.dart +++ b/lib/src/features/browse_center/presentation/extension/widgets/extension_list_tile.dart @@ -30,7 +30,6 @@ class ExtensionListTile extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final repository = ref.watch(extensionRepositoryProvider); - final toast = ref.watch(toastProvider(context)); final isLoading = useState(false); return ListTile( key: key, @@ -85,7 +84,7 @@ class ExtensionListTile extends HookConsumerWidget { await refresh(); })) - .showToastOnError(toast); + .showToastOnError(ref.read(toastProvider(context))); isLoading.value = false; } catch (e) { // @@ -114,7 +113,7 @@ class ExtensionListTile extends HookConsumerWidget { await repository.installExtension(extension.pkgName!); await refresh(); })) - .showToastOnError(toast); + .showToastOnError(ref.read(toastProvider(context))); isLoading.value = false; } catch (e) { // diff --git a/lib/src/features/browse_center/presentation/source/source_screen.dart b/lib/src/features/browse_center/presentation/source/source_screen.dart index ead69309..2e2cc85e 100644 --- a/lib/src/features/browse_center/presentation/source/source_screen.dart +++ b/lib/src/features/browse_center/presentation/source/source_screen.dart @@ -22,9 +22,8 @@ class SourceScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); final sourceMapData = ref.watch(sourceMapFilteredProvider) - ..showToastOnError(toast, withMicrotask: true); + ..showToastOnError(ref.read(toastProvider(context)), withMicrotask: true); final sourceMap = {...?sourceMapData.valueOrNull}; final localSource = sourceMap.remove("localsourcelang"); final lastUsed = sourceMap.remove("lastUsed"); diff --git a/lib/src/features/library/presentation/category/edit_category_screen.dart b/lib/src/features/library/presentation/category/edit_category_screen.dart index 54c56908..a54ca13d 100644 --- a/lib/src/features/library/presentation/category/edit_category_screen.dart +++ b/lib/src/features/library/presentation/category/edit_category_screen.dart @@ -24,9 +24,8 @@ class EditCategoryScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); final categoryList = ref.watch(categoryListProvider()) - ..showToastOnError(toast, withMicrotask: true); + ..showToastOnError(ref.read(toastProvider(context)), withMicrotask: true); return Scaffold( appBar: AppBar( title: Text(LocaleKeys.editCategory.tr()), diff --git a/lib/src/features/manga_book/presentation/manga_details/manga_details_screen.dart b/lib/src/features/manga_book/presentation/manga_details/manga_details_screen.dart index d503d3a8..35c3333a 100644 --- a/lib/src/features/manga_book/presentation/manga_details/manga_details_screen.dart +++ b/lib/src/features/manga_book/presentation/manga_details/manga_details_screen.dart @@ -7,11 +7,14 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import '../../../../constants/app_sizes.dart'; import '../../../../i18n/locale_keys.g.dart'; +import '../../../../routes/router_config.dart'; import '../../../../utils/extensions/custom_extensions.dart'; +import '../../../../utils/misc/toast/toast.dart'; import '../../../../widgets/emoticons.dart'; import '../../domain/chapter/chapter_model.dart'; import '../../widgets/chapter_actions/multi_chapters_actions_bottom_app_bar.dart'; @@ -33,8 +36,20 @@ class MangaDetailsScreen extends HookConsumerWidget { final chapterList = ref.watch(chapterListProvider); final selectedChapters = useState>({}); refresh([useCache = true]) async { + if (context.mounted && !useCache) { + ref.read(toastProvider(context)).show( + LocaleKeys.updating.tr(), + withMicrotask: true, + ); + } await ref.read(chapterListProvider.notifier).refresh(useCache); await ref.read(provider.notifier).refresh(useCache); + if (context.mounted && !useCache) { + ref.read(toastProvider(context)).show( + LocaleKeys.updateCompleted.tr(), + withMicrotask: true, + ); + } } useEffect(() { @@ -87,6 +102,11 @@ class MangaDetailsScreen extends HookConsumerWidget { : AppBar( title: Text(data?.title ?? LocaleKeys.manga.tr()), actions: [ + if (context.isTablet) + IconButton( + onPressed: () => refresh(false), + icon: const Icon(Icons.refresh_rounded), + ), Builder( builder: (context) => IconButton( onPressed: () { @@ -113,7 +133,6 @@ class MangaDetailsScreen extends HookConsumerWidget { icon: const Icon(Icons.more_vert_rounded), itemBuilder: (context) => [ PopupMenuItem( - child: Text(LocaleKeys.editCategory.tr()), onTap: () => Future.microtask( () => showDialog( context: context, @@ -121,7 +140,13 @@ class MangaDetailsScreen extends HookConsumerWidget { EditMangaCategoryDialog(mangaId: mangaId), ), ), + child: Text(LocaleKeys.editCategory.tr()), ), + if (!context.isTablet) + PopupMenuItem( + onTap: () => refresh(false), + child: Text(LocaleKeys.refresh.tr()), + ), ], ) ], @@ -137,6 +162,21 @@ class MangaDetailsScreen extends HookConsumerWidget { selectedChapters: selectedChapters, ) : null, + floatingActionButton: FloatingActionButton.extended( + isExtended: context.isTablet, + label: Text( + data?.lastChapterRead?.index != null + ? LocaleKeys.resume.tr() + : LocaleKeys.start.tr(), + ), + icon: const Icon(Icons.play_arrow_rounded), + onPressed: () { + context.push( + Routes.getReader( + "${data?.id}", "${data?.lastChapterRead?.index ?? 1}"), + ); + }, + ), body: data != null ? context.isTablet ? BigScreenMangaDetails( diff --git a/lib/src/features/manga_book/presentation/manga_details/widgets/big_screen_manga_details.dart b/lib/src/features/manga_book/presentation/manga_details/widgets/big_screen_manga_details.dart index 9f5bf63f..270d12cc 100644 --- a/lib/src/features/manga_book/presentation/manga_details/widgets/big_screen_manga_details.dart +++ b/lib/src/features/manga_book/presentation/manga_details/widgets/big_screen_manga_details.dart @@ -74,6 +74,7 @@ class BigScreenMangaDetails extends ConsumerWidget { ), Expanded( child: ListView.builder( + physics: const AlwaysScrollableScrollPhysics(), itemBuilder: (context, index) { if (filteredChapterList.length == index) { return const ListTile(); diff --git a/lib/src/features/manga_book/presentation/manga_details/widgets/chapter_list_tile.dart b/lib/src/features/manga_book/presentation/manga_details/widgets/chapter_list_tile.dart index 34584962..0028d144 100644 --- a/lib/src/features/manga_book/presentation/manga_details/widgets/chapter_list_tile.dart +++ b/lib/src/features/manga_book/presentation/manga_details/widgets/chapter_list_tile.dart @@ -64,10 +64,26 @@ class ChapterListTile extends StatelessWidget { ], ), subtitle: chapter.uploadDate != null - ? Text( - chapter.uploadDate!.toDaysAgo, - style: - TextStyle(color: chapter.read ?? false ? Colors.grey : null), + ? Row( + children: [ + Text( + chapter.uploadDate!.toDaysAgo, + style: TextStyle( + color: chapter.read ?? false ? Colors.grey : null, + ), + ), + if ((chapter.lastPageRead).ifNullOrNegative().isNotEquals([ + 0, + chapter.pageCount ?? 0, + ((chapter.pageCount ?? 1) - 1) + ])) + Text( + " • ${LocaleKeys.page.tr( + namedArgs: {"number": "${chapter.lastPageRead}"}, + )}", + style: const TextStyle(color: Colors.grey), + ), + ], ) : null, trailing: (chapter.index != null && manga.id != null) @@ -85,7 +101,10 @@ class ChapterListTile extends StatelessWidget { onTap: canTapSelect ? () => toggleSelect(chapter) : () => context.push( - Routes.getReader("${manga.id}", "${chapter.index}"), + Routes.getReader( + "${manga.id}", + "${chapter.index}", + ), ), onLongPress: () => toggleSelect(chapter), ); diff --git a/lib/src/features/manga_book/presentation/manga_details/widgets/manga_description.dart b/lib/src/features/manga_book/presentation/manga_details/widgets/manga_description.dart index 97fd705b..43ec70dc 100644 --- a/lib/src/features/manga_book/presentation/manga_details/widgets/manga_description.dart +++ b/lib/src/features/manga_book/presentation/manga_details/widgets/manga_description.dart @@ -36,7 +36,6 @@ class MangaDescription extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final isExpanded = useState(context.isTablet); - final toast = ref.watch(toastProvider(context)); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -61,7 +60,9 @@ class MangaDescription extends HookConsumerWidget { } await refresh(); }); - val.showToastOnError(toast); + if (context.mounted) { + val.showToastOnError(ref.read(toastProvider(context))); + } }, icon: Icon( manga.inLibrary ?? false @@ -78,17 +79,18 @@ class MangaDescription extends HookConsumerWidget { : LocaleKeys.addToLibrary.tr(), ), ), - TextButton.icon( - onPressed: () async { - launchUrlInWeb( - (manga.realUrl ?? ""), - toast, - ); - }, - icon: const Icon(Icons.public), - style: TextButton.styleFrom(foregroundColor: Colors.grey), - label: Text(LocaleKeys.webView.tr()), - ), + if (manga.realUrl.isNotBlank) + TextButton.icon( + onPressed: () async { + launchUrlInWeb( + (manga.realUrl ?? ""), + ref.read(toastProvider(context)), + ); + }, + icon: const Icon(Icons.public), + style: TextButton.styleFrom(foregroundColor: Colors.grey), + label: Text(LocaleKeys.webView.tr()), + ), ], ), ), diff --git a/lib/src/features/manga_book/presentation/manga_details/widgets/small_screen_manga_details.dart b/lib/src/features/manga_book/presentation/manga_details/widgets/small_screen_manga_details.dart index 890682fb..3b19a047 100644 --- a/lib/src/features/manga_book/presentation/manga_details/widgets/small_screen_manga_details.dart +++ b/lib/src/features/manga_book/presentation/manga_details/widgets/small_screen_manga_details.dart @@ -41,6 +41,7 @@ class SmallScreenMangaDetails extends ConsumerWidget { return RefreshIndicator( onRefresh: () => onRefresh(false), child: CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverToBoxAdapter( child: SingleChildScrollView( diff --git a/lib/src/features/manga_book/presentation/reader/reader_screen.dart b/lib/src/features/manga_book/presentation/reader/reader_screen.dart index f075bcb2..c62d7693 100644 --- a/lib/src/features/manga_book/presentation/reader/reader_screen.dart +++ b/lib/src/features/manga_book/presentation/reader/reader_screen.dart @@ -54,63 +54,65 @@ class ReaderScreen extends HookConsumerWidget { return; }, []); - return manga.showUiWhenData( - addScaffoldWrapper: true, - refresh: () => ref.refresh(mangaProvider), - (data) { - if (data == null) return const SizedBox.shrink(); - final readerMode = data.meta.isNotBlank && - data.meta!.containsKey(ChapterMeta.readerMode.key) - ? ReaderMode.values.firstWhere( - (element) => - element.name == data.meta![ChapterMeta.readerMode.key], - orElse: () => defaultReaderMode ?? ReaderMode.webtoon, - ) - : defaultReaderMode; - return chapter.showUiWhenData( - refresh: () => ref.refresh(provider), - addScaffoldWrapper: true, - (chapterData) { - if (chapterData == null) return const SizedBox.shrink(); - switch (readerMode) { - case ReaderMode.singleVertical: - return SinglePageReaderMode( - chapter: chapterData, - manga: data, - onPageChanged: onPageChanged, - scrollDirection: Axis.vertical, - ); - case ReaderMode.singleHorizontalRTL: - return SinglePageReaderMode( - chapter: chapterData, - manga: data, - onPageChanged: onPageChanged, - reverse: true, - ); - case ReaderMode.singleHorizontalLTR: - return SinglePageReaderMode( - chapter: chapterData, - manga: data, - onPageChanged: onPageChanged, - ); - case ReaderMode.continuousVertical: - return WebtoonReaderMode( - chapter: chapterData, - manga: data, - onPageChanged: onPageChanged, - showSeparator: true, - ); - case ReaderMode.webtoon: - default: - return WebtoonReaderMode( - chapter: chapterData, - manga: data, - onPageChanged: onPageChanged, - ); - } - }, - ); - }, + return SafeArea( + child: manga.showUiWhenData( + addScaffoldWrapper: true, + refresh: () => ref.refresh(mangaProvider), + (data) { + if (data == null) return const SizedBox.shrink(); + final readerMode = data.meta.isNotBlank && + data.meta!.containsKey(ChapterMeta.readerMode.key) + ? ReaderMode.values.firstWhere( + (element) => + element.name == data.meta![ChapterMeta.readerMode.key], + orElse: () => defaultReaderMode ?? ReaderMode.webtoon, + ) + : defaultReaderMode; + return chapter.showUiWhenData( + refresh: () => ref.refresh(provider), + addScaffoldWrapper: true, + (chapterData) { + if (chapterData == null) return const SizedBox.shrink(); + switch (readerMode) { + case ReaderMode.singleVertical: + return SinglePageReaderMode( + chapter: chapterData, + manga: data, + onPageChanged: onPageChanged, + scrollDirection: Axis.vertical, + ); + case ReaderMode.singleHorizontalRTL: + return SinglePageReaderMode( + chapter: chapterData, + manga: data, + onPageChanged: onPageChanged, + reverse: true, + ); + case ReaderMode.singleHorizontalLTR: + return SinglePageReaderMode( + chapter: chapterData, + manga: data, + onPageChanged: onPageChanged, + ); + case ReaderMode.continuousVertical: + return WebtoonReaderMode( + chapter: chapterData, + manga: data, + onPageChanged: onPageChanged, + showSeparator: true, + ); + case ReaderMode.webtoon: + default: + return WebtoonReaderMode( + chapter: chapterData, + manga: data, + onPageChanged: onPageChanged, + ); + } + }, + ); + }, + ), ); } } diff --git a/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/single_page_reader_mode.dart b/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/single_page_reader_mode.dart index f25e6405..0b03eacb 100644 --- a/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/single_page_reader_mode.dart +++ b/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/single_page_reader_mode.dart @@ -37,8 +37,20 @@ class SinglePageReaderMode extends HookWidget { final Axis scrollDirection; @override Widget build(BuildContext context) { - final scrollController = usePageController(); - final currentIndex = useState(0); + final scrollController = + usePageController(initialPage: chapter.lastPageRead.ifNullOrNegative()); + final currentIndex = useState(scrollController.initialPage); + useEffect(() { + final index = currentIndex.value; + if (onPageChanged != null) { + if (index == ((chapter.pageCount ?? 0) - 1)) { + onPageChanged!(-1); + } else { + onPageChanged!(index); + } + } + return; + }, [currentIndex.value]); useEffect(() { listener() { final currentPage = scrollController.page; @@ -69,7 +81,7 @@ class SinglePageReaderMode extends HookWidget { controller: scrollController, itemBuilder: (BuildContext context, int index) { final image = ServerImage( - fit: BoxFit.fitHeight, + fit: BoxFit.contain, size: Size.fromHeight(context.height), appendApiToUrl: true, imageUrl: MangaUrl.chapterPageWithIndex( @@ -82,11 +94,6 @@ class SinglePageReaderMode extends HookWidget { value: downloadProgress.progress, ), ); - - if (index == ((chapter.pageCount ?? 0) - 1) && - onPageChanged != null) { - onPageChanged!(-1); - } return InteractiveViewer( maxScale: 8, child: SingleChildScrollView( diff --git a/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/webtoon_reader_mode.dart b/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/webtoon_reader_mode.dart index e3e17230..189f1ead 100644 --- a/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/webtoon_reader_mode.dart +++ b/lib/src/features/manga_book/presentation/reader/widgets/reader_mode/webtoon_reader_mode.dart @@ -37,7 +37,18 @@ class WebtoonReaderMode extends HookWidget { Widget build(BuildContext context) { final scrollController = useMemoized(() => ItemScrollController()); final positionsListener = useMemoized(() => ItemPositionsListener.create()); - final currentIndex = useState(0); + final currentIndex = useState((chapter.lastPageRead).ifNullOrNegative()); + useEffect(() { + final index = currentIndex.value; + if (onPageChanged != null) { + if (index == ((chapter.pageCount ?? 0) - 1)) { + onPageChanged!(-1); + } else { + onPageChanged!(index); + } + } + return; + }, [currentIndex.value]); useEffect(() { listener() { final positions = positionsListener.itemPositions.value.toList(); @@ -93,9 +104,11 @@ class WebtoonReaderMode extends HookWidget { ); }, child: InteractiveViewer( + maxScale: 8, child: ScrollablePositionedList.separated( itemScrollController: scrollController, itemPositionsListener: positionsListener, + initialScrollIndex: chapter.lastPageRead.ifNullOrNegative(), itemBuilder: (BuildContext context, int index) { final image = ServerImage( fit: BoxFit.fitWidth, @@ -132,9 +145,6 @@ class WebtoonReaderMode extends HookWidget { ], ); } else if (index == (chapter.pageCount ?? 0) - 1) { - if (onPageChanged != null) { - onPageChanged!(-1); - } return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/src/features/manga_book/presentation/updates/updates_screen.dart b/lib/src/features/manga_book/presentation/updates/updates_screen.dart index 72e44b35..9265714c 100644 --- a/lib/src/features/manga_book/presentation/updates/updates_screen.dart +++ b/lib/src/features/manga_book/presentation/updates/updates_screen.dart @@ -60,7 +60,6 @@ class UpdatesScreen extends HookConsumerWidget { final controller = usePagingController(firstPageKey: 0); final updatesRepository = ref.watch(updatesRepositoryProvider); - final toast = ref.watch(toastProvider(context)); useEffect(() { controller.addPageRequestListener((pageKey) => _fetchPage( updatesRepository, @@ -134,7 +133,7 @@ class UpdatesScreen extends HookConsumerWidget { mangaId: "${item.manga!.id!}", chapterIndex: "${item.chapter!.index!}", )) - .valueOrToast(toast); + .valueOrToast(ref.read(toastProvider(context))); try { controller.itemList = [...?controller.itemList] ..replaceRange(index, index + 1, [ diff --git a/lib/src/features/manga_book/presentation/updates/widgets/chapter_manga_list_tile.dart b/lib/src/features/manga_book/presentation/updates/widgets/chapter_manga_list_tile.dart index ed2d0379..d4f60926 100644 --- a/lib/src/features/manga_book/presentation/updates/widgets/chapter_manga_list_tile.dart +++ b/lib/src/features/manga_book/presentation/updates/widgets/chapter_manga_list_tile.dart @@ -80,7 +80,9 @@ class ChapterMangaListTile extends StatelessWidget { } else { context.push( Routes.getReader( - "${pair.manga!.id}", "${pair.chapter!.index}"), + "${pair.manga!.id}", + "${pair.chapter!.index}", + ), ); } } diff --git a/lib/src/features/manga_book/widgets/chapter_actions/multi_chapters_action_icon.dart b/lib/src/features/manga_book/widgets/chapter_actions/multi_chapters_action_icon.dart index 4b25a2ec..915641c0 100644 --- a/lib/src/features/manga_book/widgets/chapter_actions/multi_chapters_action_icon.dart +++ b/lib/src/features/manga_book/widgets/chapter_actions/multi_chapters_action_icon.dart @@ -29,7 +29,6 @@ class MultiChaptersActionIcon extends ConsumerWidget { final IconData icon; @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); return LoadingIconButton( icon: Icon(icon), onPressed: () async { @@ -45,7 +44,7 @@ class MultiChaptersActionIcon extends ConsumerWidget { ), ), )) - .showToastOnError(toast); + .showToastOnError(ref.read(toastProvider(context))); await refresh(change != null); }, diff --git a/lib/src/features/manga_book/widgets/chapter_actions/single_chapter_action_icon.dart b/lib/src/features/manga_book/widgets/chapter_actions/single_chapter_action_icon.dart index 660f4eae..9ee1467a 100644 --- a/lib/src/features/manga_book/widgets/chapter_actions/single_chapter_action_icon.dart +++ b/lib/src/features/manga_book/widgets/chapter_actions/single_chapter_action_icon.dart @@ -32,7 +32,6 @@ class SingleChapterActionIcon extends ConsumerWidget { final ImageIcon? imageIcon; @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); return LoadingIconButton( icon: imageIcon ?? Icon(icon), onPressed: () async { @@ -43,7 +42,7 @@ class SingleChapterActionIcon extends ConsumerWidget { patch: chapterPut, ), )) - .showToastOnError(toast); + .showToastOnError(ref.read(toastProvider(context))); await refresh(); }, diff --git a/lib/src/features/manga_book/widgets/update_status_popup_menu.dart b/lib/src/features/manga_book/widgets/update_status_popup_menu.dart index 0d32e4ea..44a74411 100644 --- a/lib/src/features/manga_book/widgets/update_status_popup_menu.dart +++ b/lib/src/features/manga_book/widgets/update_status_popup_menu.dart @@ -44,7 +44,8 @@ class UpdateStatusPopupMenu extends ConsumerWidget { if (showSummaryButton) PopupMenuItem( onTap: () => Future.microtask( - () => showUpdateStatusSummaryBottomSheet(context)), + () => showUpdateStatusSummaryBottomSheet(context), + ), child: Text( LocaleKeys.updatesSummary.tr(), ), diff --git a/lib/src/features/settings/presentation/more/more_screen.dart b/lib/src/features/settings/presentation/more/more_screen.dart index c00953a6..873bd09d 100644 --- a/lib/src/features/settings/presentation/more/more_screen.dart +++ b/lib/src/features/settings/presentation/more/more_screen.dart @@ -24,7 +24,6 @@ class MoreScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); return Scaffold( appBar: AppBar( title: Text(LocaleKeys.more.tr()), @@ -66,7 +65,10 @@ class MoreScreen extends ConsumerWidget { ListTile( title: Text(LocaleKeys.help.tr()), leading: const Icon(Icons.help_rounded), - onTap: () => launchUrlInWeb(AppUrls.tachideskHelp.url, toast), + onTap: () => launchUrlInWeb( + AppUrls.tachideskHelp.url, + ref.read(toastProvider(context)), + ), ), ], ), diff --git a/lib/src/features/settings/presentation/server/server_screen.dart b/lib/src/features/settings/presentation/server/server_screen.dart index 56a2f121..506f77a3 100644 --- a/lib/src/features/settings/presentation/server/server_screen.dart +++ b/lib/src/features/settings/presentation/server/server_screen.dart @@ -23,7 +23,6 @@ class ServerScreen extends ConsumerWidget { const ServerScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final toast = ref.watch(toastProvider(context)); final authType = ref.watch(authTypeKeyProvider); return Scaffold( appBar: AppBar( @@ -50,7 +49,12 @@ class ServerScreen extends ConsumerWidget { title: Text(LocaleKeys.webUI.tr()), onTap: () { final url = ref.read(serverUrlProvider); - if (url.isNotBlank) launchUrlInWeb(url!, toast); + if (url.isNotBlank) { + launchUrlInWeb( + url!, + ref.read(toastProvider(context)), + ); + } }, ) ], diff --git a/lib/src/i18n/codegen_loader.g.dart b/lib/src/i18n/codegen_loader.g.dart index b00d53c2..1161b4df 100644 --- a/lib/src/i18n/codegen_loader.g.dart +++ b/lib/src/i18n/codegen_loader.g.dart @@ -15,60 +15,16 @@ class CodegenLoader extends AssetLoader { } static const Map en_US = { - "AuthType": {"basic": "Basic Auth", "none": "None"}, - "ChapterSort": {"fetchedDate": "By Fetched Data", "source": "By Source"}, - "DisplayMode": { - "descriptiveList": "Descriptive List", - "grid": "Grid", - "list": "List" - }, - "MangaSort": { - "alphabetical": "Alphabetical", - "dateAdded": "Date Added", - "unread": "Unread" - }, - "MangaStatus": { - "cancelled": "Cancelled", - "completed": "Completed", - "licensed": "Licensed", - "onHiatus": "On Hiatus", - "ongoing": "Ongoing", - "publishingFinished": "Publishing Finished", - "unknown": "Unknown" - }, - "ReaderMode": { - "continuousHorizontalLTR": "Continuous Horizontal (LTR)", - "continuousHorizontalRTL": "Continuous Horizontal (RTL)", - "continuousVertical": "Continuous Vertical", - "defaultReader": "Default", - "singleHorizontalLTR": "Single Horizontal (LTR)", - "singleHorizontalRTL": "Single Horizontal (RTL)", - "singleVertical": "Single Vertical", - "webtoon": "Webtoon" - }, - "ReaderNavigationLayout": { - "disabled": "Disabled", - "edge": "Edge", - "kindlish": "Kindle-ish", - "lShaped": "L Shaped", - "rightAndLeft": "Right and Left", - "defaultNavigation": "Default" - }, - "SourceType": { - "filter": "Filter", - "latest": "Latest", - "popular": "Popular" - }, - "ThemeMode": {"dark": "Dark", "light": "Light", "system": "System"}, "about": "About", "add": "Add", "addCategory": "Add Category", "addCategoryHint": "Add new categories in settings", "addToLibrary": "Add to Library", + "appearance": "Appearance", "appTheme": "App Theme", "appTitle": "Tachidesk Sorayomi", - "appearance": "Appearance", "artist": "Artist", + "AuthType": {"basic": "Basic Auth", "none": "None"}, "backup": "Backup & Restore", "badges": "Badges", "baseAuthType": "Authentication Type", @@ -93,6 +49,7 @@ class CodegenLoader extends AssetLoader { }, "chapterNumber": "Chapter {number}", "chapters": "Chapters", + "ChapterSort": {"fetchedDate": "By Fetched Data", "source": "By Source"}, "checkForServerUpdates": "Check for Server updates", "checkForUpdates": "Check for updates", "client": "Client", @@ -116,6 +73,11 @@ class CodegenLoader extends AssetLoader { "discord": "Discord", "display": "Display", "displayMode": "Display Mode", + "DisplayMode": { + "descriptiveList": "Descriptive List", + "grid": "Grid", + "list": "List" + }, "downloaded": "Downloaded", "downloads": "Downloads", "edit": "Edit", @@ -159,6 +121,20 @@ class CodegenLoader extends AssetLoader { "loading": "Loading!", "manga": "Manga", "mangaSearch": "Search manga..", + "MangaSort": { + "alphabetical": "Alphabetical", + "dateAdded": "Date Added", + "unread": "Unread" + }, + "MangaStatus": { + "cancelled": "Cancelled", + "completed": "Completed", + "licensed": "Licensed", + "ongoing": "Ongoing", + "onHiatus": "On Hiatus", + "publishingFinished": "Publishing Finished", + "unknown": "Unknown" + }, "missingExtension": "Missing Extensions", "missingTrackers": "Missing Trackers", "more": "More", @@ -189,6 +165,7 @@ class CodegenLoader extends AssetLoader { }, "nsfw18": "18+", "numSelected": "{num} Selected", + "page": "Page: {number}", "password": "Password", "pause": "Pause", "pending": "Pending", @@ -196,9 +173,27 @@ class CodegenLoader extends AssetLoader { "previousChapter": "Previous Chapter", "reader": "Reader", "readerMode": "Reading Mode", + "ReaderMode": { + "continuousHorizontalLTR": "Continuous Horizontal (LTR)", + "continuousHorizontalRTL": "Continuous Horizontal (RTL)", + "continuousVertical": "Continuous Vertical", + "defaultReader": "Default", + "singleHorizontalLTR": "Single Horizontal (LTR)", + "singleHorizontalRTL": "Single Horizontal (RTL)", + "singleVertical": "Single Vertical", + "webtoon": "Webtoon" + }, "readerNavigationLayout": "Navigation layout", - "readerNavigationLayoutInvert": "Invert tapping", + "ReaderNavigationLayout": { + "defaultNavigation": "Default", + "disabled": "Disabled", + "edge": "Edge", + "kindlish": "Kindle-ish", + "lShaped": "L Shaped", + "rightAndLeft": "Right and Left" + }, "readerNavigationLayout_": "Navigation layout", + "readerNavigationLayoutInvert": "Invert tapping", "readerSettingsView": "Reader Settings", "reddit": "Reddit", "refresh": "Refresh", @@ -217,8 +212,8 @@ class CodegenLoader extends AssetLoader { "savedImagePathTitle": "Image path saved to Clipboard", "search": "Search...", "searchGlobally": "Search Globally", - "searchManga": "Search manga..", "searchingForUpdates": "Searching for updates...", + "searchManga": "Search manga..", "server": "Server", "serverVersion": "Server version", "setAsDefault": "Set as default", @@ -236,7 +231,14 @@ class CodegenLoader extends AssetLoader { "sortUnread": "Unread", "source": "Source", "sources": "Sources", + "SourceType": { + "filter": "Filter", + "latest": "Latest", + "popular": "Popular" + }, + "start": "Start", "status": "Status", + "ThemeMode": {"dark": "Dark", "light": "Light", "system": "System"}, "uninstall": "Uninstall", "uninstalling": "Uninstalling", "unknown": "Unknown", @@ -245,6 +247,7 @@ class CodegenLoader extends AssetLoader { "unknownSource": "Unknown Source", "unread": "Unread", "update": "Update", + "updateCompleted": "Update Completed", "updates": "Updates", "updatesSummary": "Updates Summary", "updating": "Updating", diff --git a/lib/src/i18n/locale_keys.g.dart b/lib/src/i18n/locale_keys.g.dart index 78b5b863..a2350690 100644 --- a/lib/src/i18n/locale_keys.g.dart +++ b/lib/src/i18n/locale_keys.g.dart @@ -1,71 +1,18 @@ // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart abstract class LocaleKeys { - static const AuthType_basic = 'AuthType.basic'; - static const AuthType_none = 'AuthType.none'; - static const AuthType = 'AuthType'; - static const ChapterSort_fetchedDate = 'ChapterSort.fetchedDate'; - static const ChapterSort_source = 'ChapterSort.source'; - static const ChapterSort = 'ChapterSort'; - static const DisplayMode_descriptiveList = 'DisplayMode.descriptiveList'; - static const DisplayMode_grid = 'DisplayMode.grid'; - static const DisplayMode_list = 'DisplayMode.list'; - static const DisplayMode = 'DisplayMode'; - static const MangaSort_alphabetical = 'MangaSort.alphabetical'; - static const MangaSort_dateAdded = 'MangaSort.dateAdded'; - static const MangaSort_unread = 'MangaSort.unread'; - static const MangaSort = 'MangaSort'; - static const MangaStatus_cancelled = 'MangaStatus.cancelled'; - static const MangaStatus_completed = 'MangaStatus.completed'; - static const MangaStatus_licensed = 'MangaStatus.licensed'; - static const MangaStatus_onHiatus = 'MangaStatus.onHiatus'; - static const MangaStatus_ongoing = 'MangaStatus.ongoing'; - static const MangaStatus_publishingFinished = - 'MangaStatus.publishingFinished'; - static const MangaStatus_unknown = 'MangaStatus.unknown'; - static const MangaStatus = 'MangaStatus'; - static const ReaderMode_continuousHorizontalLTR = - 'ReaderMode.continuousHorizontalLTR'; - static const ReaderMode_continuousHorizontalRTL = - 'ReaderMode.continuousHorizontalRTL'; - static const ReaderMode_continuousVertical = 'ReaderMode.continuousVertical'; - static const ReaderMode_defaultReader = 'ReaderMode.defaultReader'; - static const ReaderMode_singleHorizontalLTR = - 'ReaderMode.singleHorizontalLTR'; - static const ReaderMode_singleHorizontalRTL = - 'ReaderMode.singleHorizontalRTL'; - static const ReaderMode_singleVertical = 'ReaderMode.singleVertical'; - static const ReaderMode_webtoon = 'ReaderMode.webtoon'; - static const ReaderMode = 'ReaderMode'; - static const ReaderNavigationLayout_disabled = - 'ReaderNavigationLayout.disabled'; - static const ReaderNavigationLayout_edge = 'ReaderNavigationLayout.edge'; - static const ReaderNavigationLayout_kindlish = - 'ReaderNavigationLayout.kindlish'; - static const ReaderNavigationLayout_lShaped = - 'ReaderNavigationLayout.lShaped'; - static const ReaderNavigationLayout_rightAndLeft = - 'ReaderNavigationLayout.rightAndLeft'; - static const ReaderNavigationLayout_defaultNavigation = - 'ReaderNavigationLayout.defaultNavigation'; - static const ReaderNavigationLayout = 'ReaderNavigationLayout'; - static const SourceType_filter = 'SourceType.filter'; - static const SourceType_latest = 'SourceType.latest'; - static const SourceType_popular = 'SourceType.popular'; - static const SourceType = 'SourceType'; - static const ThemeMode_dark = 'ThemeMode.dark'; - static const ThemeMode_light = 'ThemeMode.light'; - static const ThemeMode_system = 'ThemeMode.system'; - static const ThemeMode = 'ThemeMode'; static const about = 'about'; static const add = 'add'; static const addCategory = 'addCategory'; static const addCategoryHint = 'addCategoryHint'; static const addToLibrary = 'addToLibrary'; + static const appearance = 'appearance'; static const appTheme = 'appTheme'; static const appTitle = 'appTitle'; - static const appearance = 'appearance'; static const artist = 'artist'; + static const AuthType_basic = 'AuthType.basic'; + static const AuthType_none = 'AuthType.none'; + static const AuthType = 'AuthType'; static const backup = 'backup'; static const badges = 'badges'; static const baseAuthType = 'baseAuthType'; @@ -89,6 +36,9 @@ abstract class LocaleKeys { static const chapterList = 'chapterList'; static const chapterNumber = 'chapterNumber'; static const chapters = 'chapters'; + static const ChapterSort_fetchedDate = 'ChapterSort.fetchedDate'; + static const ChapterSort_source = 'ChapterSort.source'; + static const ChapterSort = 'ChapterSort'; static const checkForServerUpdates = 'checkForServerUpdates'; static const checkForUpdates = 'checkForUpdates'; static const client = 'client'; @@ -110,6 +60,10 @@ abstract class LocaleKeys { static const discord = 'discord'; static const display = 'display'; static const displayMode = 'displayMode'; + static const DisplayMode_descriptiveList = 'DisplayMode.descriptiveList'; + static const DisplayMode_grid = 'DisplayMode.grid'; + static const DisplayMode_list = 'DisplayMode.list'; + static const DisplayMode = 'DisplayMode'; static const downloaded = 'downloaded'; static const downloads = 'downloads'; static const edit = 'edit'; @@ -152,6 +106,19 @@ abstract class LocaleKeys { static const loading = 'loading'; static const manga = 'manga'; static const mangaSearch = 'mangaSearch'; + static const MangaSort_alphabetical = 'MangaSort.alphabetical'; + static const MangaSort_dateAdded = 'MangaSort.dateAdded'; + static const MangaSort_unread = 'MangaSort.unread'; + static const MangaSort = 'MangaSort'; + static const MangaStatus_cancelled = 'MangaStatus.cancelled'; + static const MangaStatus_completed = 'MangaStatus.completed'; + static const MangaStatus_licensed = 'MangaStatus.licensed'; + static const MangaStatus_ongoing = 'MangaStatus.ongoing'; + static const MangaStatus_onHiatus = 'MangaStatus.onHiatus'; + static const MangaStatus_publishingFinished = + 'MangaStatus.publishingFinished'; + static const MangaStatus_unknown = 'MangaStatus.unknown'; + static const MangaStatus = 'MangaStatus'; static const missingExtension = 'missingExtension'; static const missingTrackers = 'missingTrackers'; static const more = 'more'; @@ -177,6 +144,7 @@ abstract class LocaleKeys { static const nsfw = 'nsfw'; static const nsfw18 = 'nsfw18'; static const numSelected = 'numSelected'; + static const page = 'page'; static const password = 'password'; static const pause = 'pause'; static const pending = 'pending'; @@ -184,9 +152,34 @@ abstract class LocaleKeys { static const previousChapter = 'previousChapter'; static const reader = 'reader'; static const readerMode = 'readerMode'; + static const ReaderMode_continuousHorizontalLTR = + 'ReaderMode.continuousHorizontalLTR'; + static const ReaderMode_continuousHorizontalRTL = + 'ReaderMode.continuousHorizontalRTL'; + static const ReaderMode_continuousVertical = 'ReaderMode.continuousVertical'; + static const ReaderMode_defaultReader = 'ReaderMode.defaultReader'; + static const ReaderMode_singleHorizontalLTR = + 'ReaderMode.singleHorizontalLTR'; + static const ReaderMode_singleHorizontalRTL = + 'ReaderMode.singleHorizontalRTL'; + static const ReaderMode_singleVertical = 'ReaderMode.singleVertical'; + static const ReaderMode_webtoon = 'ReaderMode.webtoon'; + static const ReaderMode = 'ReaderMode'; static const readerNavigationLayout = 'readerNavigationLayout'; - static const readerNavigationLayoutInvert = 'readerNavigationLayoutInvert'; + static const ReaderNavigationLayout_defaultNavigation = + 'ReaderNavigationLayout.defaultNavigation'; + static const ReaderNavigationLayout_disabled = + 'ReaderNavigationLayout.disabled'; + static const ReaderNavigationLayout_edge = 'ReaderNavigationLayout.edge'; + static const ReaderNavigationLayout_kindlish = + 'ReaderNavigationLayout.kindlish'; + static const ReaderNavigationLayout_lShaped = + 'ReaderNavigationLayout.lShaped'; + static const ReaderNavigationLayout_rightAndLeft = + 'ReaderNavigationLayout.rightAndLeft'; + static const ReaderNavigationLayout = 'ReaderNavigationLayout'; static const readerNavigationLayout_ = 'readerNavigationLayout_'; + static const readerNavigationLayoutInvert = 'readerNavigationLayoutInvert'; static const readerSettingsView = 'readerSettingsView'; static const reddit = 'reddit'; static const refresh = 'refresh'; @@ -204,8 +197,8 @@ abstract class LocaleKeys { static const savedImagePathTitle = 'savedImagePathTitle'; static const search = 'search'; static const searchGlobally = 'searchGlobally'; - static const searchManga = 'searchManga'; static const searchingForUpdates = 'searchingForUpdates'; + static const searchManga = 'searchManga'; static const server = 'server'; static const serverVersion = 'serverVersion'; static const setAsDefault = 'setAsDefault'; @@ -223,7 +216,16 @@ abstract class LocaleKeys { static const sortUnread = 'sortUnread'; static const source = 'source'; static const sources = 'sources'; + static const SourceType_filter = 'SourceType.filter'; + static const SourceType_latest = 'SourceType.latest'; + static const SourceType_popular = 'SourceType.popular'; + static const SourceType = 'SourceType'; + static const start = 'start'; static const status = 'status'; + static const ThemeMode_dark = 'ThemeMode.dark'; + static const ThemeMode_light = 'ThemeMode.light'; + static const ThemeMode_system = 'ThemeMode.system'; + static const ThemeMode = 'ThemeMode'; static const uninstall = 'uninstall'; static const uninstalling = 'uninstalling'; static const unknown = 'unknown'; @@ -232,6 +234,7 @@ abstract class LocaleKeys { static const unknownSource = 'unknownSource'; static const unread = 'unread'; static const update = 'update'; + static const updateCompleted = 'updateCompleted'; static const updates = 'updates'; static const updatesSummary = 'updatesSummary'; static const updating = 'updating'; diff --git a/lib/src/utils/extensions/custom_extensions/int_extensions.dart b/lib/src/utils/extensions/custom_extensions/int_extensions.dart index 5f520375..2a5b0733 100644 --- a/lib/src/utils/extensions/custom_extensions/int_extensions.dart +++ b/lib/src/utils/extensions/custom_extensions/int_extensions.dart @@ -12,6 +12,9 @@ extension IntExtensions on int? { this != null ? this! >= lower && this! <= upper : false; bool isGreaterThan(int i) => isNull ? false : this! > i; bool isLessThan(int i) => isNull ? false : this! < i; + int ifNullOrNegative([int i = 0]) => isNull || this!.isNegative ? i : this!; + bool isNotEquals(List lst) => + isNull || lst.isBlank ? true : lst.every((e) => e != this); bool? get toBool => (this == null || this == 0) ? null : this == 1; diff --git a/lib/src/utils/misc/toast/toast.dart b/lib/src/utils/misc/toast/toast.dart index c00920d3..ef1d04ce 100644 --- a/lib/src/utils/misc/toast/toast.dart +++ b/lib/src/utils/misc/toast/toast.dart @@ -25,10 +25,21 @@ class Toast { show(msg); } - void show(String msg) => _fToast.showToast( - child: ToastWidget(text: msg), - gravity: ToastGravity.BOTTOM, - ); + void show(String msg, {bool withMicrotask = false}) { + { + if (withMicrotask) { + Future.microtask(() => _fToast.showToast( + child: ToastWidget(text: msg), + gravity: ToastGravity.BOTTOM, + )); + } else { + _fToast.showToast( + child: ToastWidget(text: msg), + gravity: ToastGravity.BOTTOM, + ); + } + } + } void showError(String error) => _fToast.showToast( child: ToastWidget( diff --git a/pubspec.lock b/pubspec.lock index 100700d5..e5130294 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -417,10 +417,10 @@ packages: dependency: "direct main" description: name: fluttertoast - sha256: "7a738eddad04c7b27a1ecfecd12e8ecd4b188cdd2d91c252a02a4aba65838c9d" + sha256: "7cc92eabe01e3f1babe1571c5560b135dfc762a34e41e9056881e2196b178ec1" url: "https://pub.dev" source: hosted - version: "8.1.1" + version: "8.1.2" font_awesome_flutter: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 6b4316eb..1858f08c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: tachidesk_sorayomi description: A new Flutter frontend for Tachidesk. publish_to: "none" -version: 0.3.0+1 +version: 0.3.1+1 environment: sdk: ">=2.18.1 <3.0.0"