From 7cf5614bb50761a99ad952635af4ac76dc4afb2c Mon Sep 17 00:00:00 2001 From: kodjomoustapha <107993382+kodjodevf@users.noreply.github.com> Date: Tue, 31 Dec 2024 09:47:28 +0100 Subject: [PATCH] refactor: rename backup and restore to data and storage, update related imports and UI elements --- lib/l10n/app_en.arb | 12 +- lib/main.dart | 8 + lib/models/settings.dart | 17 +- lib/models/settings.g.dart | 696 ++++++++++-------- lib/modules/main_view/main_screen.dart | 2 +- .../backup_and_restore.dart | 401 ---------- .../more/data_and_storage/create_backup.dart | 206 ++++++ .../data_and_storage/data_and_storage.dart | 379 ++++++++++ .../providers/auto_backup.dart | 12 +- .../providers/auto_backup.g.dart | 2 +- .../providers/backup.dart | 53 +- .../providers/backup.g.dart | 2 +- .../providers/restore.dart | 6 +- .../providers/restore.g.dart | 2 +- .../providers/storage_usage.dart | 101 +++ .../providers/storage_usage.g.dart | 44 ++ lib/modules/more/more_screen.dart | 6 +- .../settings/downloads/downloads_screen.dart | 81 -- .../providers/downloads_state_provider.dart | 3 +- .../providers/downloads_state_provider.g.dart | 2 +- lib/router/router.dart | 24 +- lib/services/sync_server.dart | 2 +- 22 files changed, 1215 insertions(+), 846 deletions(-) delete mode 100644 lib/modules/more/backup_and_restore/backup_and_restore.dart create mode 100644 lib/modules/more/data_and_storage/create_backup.dart create mode 100644 lib/modules/more/data_and_storage/data_and_storage.dart rename lib/modules/more/{backup_and_restore => data_and_storage}/providers/auto_backup.dart (92%) rename lib/modules/more/{backup_and_restore => data_and_storage}/providers/auto_backup.g.dart (98%) rename lib/modules/more/{backup_and_restore => data_and_storage}/providers/backup.dart (97%) rename lib/modules/more/{backup_and_restore => data_and_storage}/providers/backup.g.dart (98%) rename lib/modules/more/{backup_and_restore => data_and_storage}/providers/restore.dart (97%) rename lib/modules/more/{backup_and_restore => data_and_storage}/providers/restore.g.dart (99%) create mode 100644 lib/modules/more/data_and_storage/providers/storage_usage.dart create mode 100644 lib/modules/more/data_and_storage/providers/storage_usage.g.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d2998d0..39129e7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -389,5 +389,15 @@ "n_minutes_ago": "{minutes} minutes ago", "n_day_ago": "{day} day ago", "now": "now", - "library_last_updated": "Library last updated: {lastUpdated}" + "library_last_updated": "Library last updated: {lastUpdated}", + "data_and_storage": "Data and storage", + "download_location_info": "Used for chapter downloads", + "storage": "Storage", + "clear_chapter_and_episode_cache": "Clear chapter and episode cache", + "cache_cleared": "Cache cleared", + "clear_chapter_or_episode_cache_on_app_launch": "Clear chapter/episode cache on app launch", + "app_settings": "App settings", + "sources_settings": "Sources settings", + "include_sensitive_settings": "Include sensitive settings (e.g., tracker login tokens)", + "create": "Create" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index e88e328..71e9ea5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/intl.dart'; import 'package:isar/isar.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/storage_usage.dart'; import 'package:mangayomi/modules/more/settings/appearance/providers/app_font_family.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/providers/storage_provider.dart'; @@ -75,6 +76,13 @@ class _MyAppState extends ConsumerState { @override void initState() { iniDateFormatting(); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (ref.read(clearChapterCacheOnAppLaunchStateProvider)) { + ref + .read(totalChapterCacheSizeStateProvider.notifier) + .clearCache(showToast: false); + } + }); super.initState(); } diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 4198efc..4faad98 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -133,7 +133,7 @@ class Settings { int? backupFrequency; - List? backupFrequencyOptions; + List? backupListOptions; String? autoBackupLocation; @@ -221,6 +221,8 @@ class Settings { bool? hideNovel; + bool? clearChapterCacheOnAppLaunch; + Settings( {this.id = 227, this.displayType = DisplayType.compactGrid, @@ -277,7 +279,7 @@ class Settings { this.backgroundColor = BackgroundColor.black, this.personalPageModeList, this.backupFrequency, - this.backupFrequencyOptions, + this.backupListOptions, this.autoBackupLocation, this.startDatebackup, this.usePageTapZones = true, @@ -318,7 +320,8 @@ class Settings { this.novelDisplayType = DisplayType.comfortableGrid, this.hideManga = false, this.hideAnime = false, - this.hideNovel = false}); + this.hideNovel = false, + this.clearChapterCacheOnAppLaunch = false}); Settings.fromJson(Map json) { animatePageTransitions = json['animatePageTransitions']; @@ -438,7 +441,7 @@ class Settings { themeIsDark = json['themeIsDark']; userAgent = json['userAgent']; backupFrequency = json['backupFrequency']; - backupFrequencyOptions = json['backupFrequencyOptions']?.cast(); + backupListOptions = json['backupListOptions']?.cast(); autoBackupLocation = json['autoBackupLocation']; startDatebackup = json['startDatebackup']; usePageTapZones = json['usePageTapZones']; @@ -491,6 +494,7 @@ class Settings { hideManga = json['hideManga']; hideAnime = json['hideAnime']; hideNovel = json['hideNovel']; + clearChapterCacheOnAppLaunch = json['clearChapterCacheOnAppLaunch']; } Map toJson() => { @@ -562,7 +566,7 @@ class Settings { 'themeIsDark': themeIsDark, 'userAgent': userAgent, 'backupFrequency': backupFrequency, - 'backupFrequencyOptions': backupFrequencyOptions, + 'backupListOptions': backupListOptions, 'autoBackupLocation': autoBackupLocation, 'startDatebackup': startDatebackup, 'usePageTapZones': usePageTapZones, @@ -605,7 +609,8 @@ class Settings { 'novelDisplayType': novelDisplayType.index, 'hideManga': hideManga, 'hideAnime': hideAnime, - 'hideNovel': hideNovel + 'hideNovel': hideNovel, + 'clearChapterCacheOnAppLaunch': clearChapterCacheOnAppLaunch }; } diff --git a/lib/models/settings.g.dart b/lib/models/settings.g.dart index 62a3670..d367238 100644 --- a/lib/models/settings.g.dart +++ b/lib/models/settings.g.dart @@ -100,9 +100,9 @@ const SettingsSchema = CollectionSchema( name: r'backupFrequency', type: IsarType.long, ), - r'backupFrequencyOptions': PropertySchema( + r'backupListOptions': PropertySchema( id: 16, - name: r'backupFrequencyOptions', + name: r'backupListOptions', type: IsarType.longList, ), r'btServerAddress': PropertySchema( @@ -150,401 +150,406 @@ const SettingsSchema = CollectionSchema( name: r'checkForExtensionUpdates', type: IsarType.bool, ), - r'colorFilterBlendMode': PropertySchema( + r'clearChapterCacheOnAppLaunch': PropertySchema( id: 25, + name: r'clearChapterCacheOnAppLaunch', + type: IsarType.bool, + ), + r'colorFilterBlendMode': PropertySchema( + id: 26, name: r'colorFilterBlendMode', type: IsarType.byte, enumMap: _SettingscolorFilterBlendModeEnumValueMap, ), r'cookiesList': PropertySchema( - id: 26, + id: 27, name: r'cookiesList', type: IsarType.objectList, target: r'MCookie', ), r'cropBorders': PropertySchema( - id: 27, + id: 28, name: r'cropBorders', type: IsarType.bool, ), r'customColorFilter': PropertySchema( - id: 28, + id: 29, name: r'customColorFilter', type: IsarType.object, target: r'CustomColorFilter', ), r'dateFormat': PropertySchema( - id: 29, + id: 30, name: r'dateFormat', type: IsarType.string, ), r'defaultDoubleTapToSkipLength': PropertySchema( - id: 30, + id: 31, name: r'defaultDoubleTapToSkipLength', type: IsarType.long, ), r'defaultPlayBackSpeed': PropertySchema( - id: 31, + id: 32, name: r'defaultPlayBackSpeed', type: IsarType.double, ), r'defaultReaderMode': PropertySchema( - id: 32, + id: 33, name: r'defaultReaderMode', type: IsarType.byte, enumMap: _SettingsdefaultReaderModeEnumValueMap, ), r'defaultSkipIntroLength': PropertySchema( - id: 33, + id: 34, name: r'defaultSkipIntroLength', type: IsarType.long, ), r'disableSectionType': PropertySchema( - id: 34, + id: 35, name: r'disableSectionType', type: IsarType.byte, enumMap: _SettingsdisableSectionTypeEnumValueMap, ), r'displayType': PropertySchema( - id: 35, + id: 36, name: r'displayType', type: IsarType.byte, enumMap: _SettingsdisplayTypeEnumValueMap, ), r'doubleTapAnimationSpeed': PropertySchema( - id: 36, + id: 37, name: r'doubleTapAnimationSpeed', type: IsarType.long, ), r'downloadLocation': PropertySchema( - id: 37, + id: 38, name: r'downloadLocation', type: IsarType.string, ), r'downloadOnlyOnWifi': PropertySchema( - id: 38, + id: 39, name: r'downloadOnlyOnWifi', type: IsarType.bool, ), r'enableAniSkip': PropertySchema( - id: 39, + id: 40, name: r'enableAniSkip', type: IsarType.bool, ), r'enableAutoSkip': PropertySchema( - id: 40, + id: 41, name: r'enableAutoSkip', type: IsarType.bool, ), r'enableCustomColorFilter': PropertySchema( - id: 41, + id: 42, name: r'enableCustomColorFilter', type: IsarType.bool, ), r'filterScanlatorList': PropertySchema( - id: 42, + id: 43, name: r'filterScanlatorList', type: IsarType.objectList, target: r'FilterScanlator', ), r'flexColorSchemeBlendLevel': PropertySchema( - id: 43, + id: 44, name: r'flexColorSchemeBlendLevel', type: IsarType.double, ), r'flexSchemeColorIndex': PropertySchema( - id: 44, + id: 45, name: r'flexSchemeColorIndex', type: IsarType.long, ), r'fullScreenPlayer': PropertySchema( - id: 45, + id: 46, name: r'fullScreenPlayer', type: IsarType.bool, ), r'fullScreenReader': PropertySchema( - id: 46, + id: 47, name: r'fullScreenReader', type: IsarType.bool, ), r'hideAnime': PropertySchema( - id: 47, + id: 48, name: r'hideAnime', type: IsarType.bool, ), r'hideManga': PropertySchema( - id: 48, + id: 49, name: r'hideManga', type: IsarType.bool, ), r'hideNovel': PropertySchema( - id: 49, + id: 50, name: r'hideNovel', type: IsarType.bool, ), r'incognitoMode': PropertySchema( - id: 50, + id: 51, name: r'incognitoMode', type: IsarType.bool, ), r'libraryDownloadedChapters': PropertySchema( - id: 51, + id: 52, name: r'libraryDownloadedChapters', type: IsarType.bool, ), r'libraryFilterAnimeBookMarkedType': PropertySchema( - id: 52, + id: 53, name: r'libraryFilterAnimeBookMarkedType', type: IsarType.long, ), r'libraryFilterAnimeDownloadType': PropertySchema( - id: 53, + id: 54, name: r'libraryFilterAnimeDownloadType', type: IsarType.long, ), r'libraryFilterAnimeStartedType': PropertySchema( - id: 54, + id: 55, name: r'libraryFilterAnimeStartedType', type: IsarType.long, ), r'libraryFilterAnimeUnreadType': PropertySchema( - id: 55, + id: 56, name: r'libraryFilterAnimeUnreadType', type: IsarType.long, ), r'libraryFilterMangasBookMarkedType': PropertySchema( - id: 56, + id: 57, name: r'libraryFilterMangasBookMarkedType', type: IsarType.long, ), r'libraryFilterMangasDownloadType': PropertySchema( - id: 57, + id: 58, name: r'libraryFilterMangasDownloadType', type: IsarType.long, ), r'libraryFilterMangasStartedType': PropertySchema( - id: 58, + id: 59, name: r'libraryFilterMangasStartedType', type: IsarType.long, ), r'libraryFilterMangasUnreadType': PropertySchema( - id: 59, + id: 60, name: r'libraryFilterMangasUnreadType', type: IsarType.long, ), r'libraryFilterNovelBookMarkedType': PropertySchema( - id: 60, + id: 61, name: r'libraryFilterNovelBookMarkedType', type: IsarType.long, ), r'libraryFilterNovelDownloadType': PropertySchema( - id: 61, + id: 62, name: r'libraryFilterNovelDownloadType', type: IsarType.long, ), r'libraryFilterNovelStartedType': PropertySchema( - id: 62, + id: 63, name: r'libraryFilterNovelStartedType', type: IsarType.long, ), r'libraryFilterNovelUnreadType': PropertySchema( - id: 63, + id: 64, name: r'libraryFilterNovelUnreadType', type: IsarType.long, ), r'libraryLocalSource': PropertySchema( - id: 64, + id: 65, name: r'libraryLocalSource', type: IsarType.bool, ), r'libraryShowCategoryTabs': PropertySchema( - id: 65, + id: 66, name: r'libraryShowCategoryTabs', type: IsarType.bool, ), r'libraryShowContinueReadingButton': PropertySchema( - id: 66, + id: 67, name: r'libraryShowContinueReadingButton', type: IsarType.bool, ), r'libraryShowLanguage': PropertySchema( - id: 67, + id: 68, name: r'libraryShowLanguage', type: IsarType.bool, ), r'libraryShowNumbersOfItems': PropertySchema( - id: 68, + id: 69, name: r'libraryShowNumbersOfItems', type: IsarType.bool, ), r'locale': PropertySchema( - id: 69, + id: 70, name: r'locale', type: IsarType.object, target: r'L10nLocale', ), r'mangaGridSize': PropertySchema( - id: 70, + id: 71, name: r'mangaGridSize', type: IsarType.long, ), r'mangaHomeDisplayType': PropertySchema( - id: 71, + id: 72, name: r'mangaHomeDisplayType', type: IsarType.byte, enumMap: _SettingsmangaHomeDisplayTypeEnumValueMap, ), r'markEpisodeAsSeenType': PropertySchema( - id: 72, + id: 73, name: r'markEpisodeAsSeenType', type: IsarType.long, ), r'novelDisplayType': PropertySchema( - id: 73, + id: 74, name: r'novelDisplayType', type: IsarType.byte, enumMap: _SettingsnovelDisplayTypeEnumValueMap, ), r'novelGridSize': PropertySchema( - id: 74, + id: 75, name: r'novelGridSize', type: IsarType.long, ), r'novelLibraryDownloadedChapters': PropertySchema( - id: 75, + id: 76, name: r'novelLibraryDownloadedChapters', type: IsarType.bool, ), r'novelLibraryLocalSource': PropertySchema( - id: 76, + id: 77, name: r'novelLibraryLocalSource', type: IsarType.bool, ), r'novelLibraryShowCategoryTabs': PropertySchema( - id: 77, + id: 78, name: r'novelLibraryShowCategoryTabs', type: IsarType.bool, ), r'novelLibraryShowContinueReadingButton': PropertySchema( - id: 78, + id: 79, name: r'novelLibraryShowContinueReadingButton', type: IsarType.bool, ), r'novelLibraryShowLanguage': PropertySchema( - id: 79, + id: 80, name: r'novelLibraryShowLanguage', type: IsarType.bool, ), r'novelLibraryShowNumbersOfItems': PropertySchema( - id: 80, + id: 81, name: r'novelLibraryShowNumbersOfItems', type: IsarType.bool, ), r'onlyIncludePinnedSources': PropertySchema( - id: 81, + id: 82, name: r'onlyIncludePinnedSources', type: IsarType.bool, ), r'pagePreloadAmount': PropertySchema( - id: 82, + id: 83, name: r'pagePreloadAmount', type: IsarType.long, ), r'personalPageModeList': PropertySchema( - id: 83, + id: 84, name: r'personalPageModeList', type: IsarType.objectList, target: r'PersonalPageMode', ), r'personalReaderModeList': PropertySchema( - id: 84, + id: 85, name: r'personalReaderModeList', type: IsarType.objectList, target: r'PersonalReaderMode', ), r'playerSubtitleSettings': PropertySchema( - id: 85, + id: 86, name: r'playerSubtitleSettings', type: IsarType.object, target: r'PlayerSubtitleSettings', ), r'pureBlackDarkMode': PropertySchema( - id: 86, + id: 87, name: r'pureBlackDarkMode', type: IsarType.bool, ), r'relativeTimesTamps': PropertySchema( - id: 87, + id: 88, name: r'relativeTimesTamps', type: IsarType.long, ), r'saveAsCBZArchive': PropertySchema( - id: 88, + id: 89, name: r'saveAsCBZArchive', type: IsarType.bool, ), r'scaleType': PropertySchema( - id: 89, + id: 90, name: r'scaleType', type: IsarType.byte, enumMap: _SettingsscaleTypeEnumValueMap, ), r'showPagesNumber': PropertySchema( - id: 90, + id: 91, name: r'showPagesNumber', type: IsarType.bool, ), r'sortChapterList': PropertySchema( - id: 91, + id: 92, name: r'sortChapterList', type: IsarType.objectList, target: r'SortChapter', ), r'sortLibraryAnime': PropertySchema( - id: 92, + id: 93, name: r'sortLibraryAnime', type: IsarType.object, target: r'SortLibraryManga', ), r'sortLibraryManga': PropertySchema( - id: 93, + id: 94, name: r'sortLibraryManga', type: IsarType.object, target: r'SortLibraryManga', ), r'sortLibraryNovel': PropertySchema( - id: 94, + id: 95, name: r'sortLibraryNovel', type: IsarType.object, target: r'SortLibraryManga', ), r'startDatebackup': PropertySchema( - id: 95, + id: 96, name: r'startDatebackup', type: IsarType.long, ), r'themeIsDark': PropertySchema( - id: 96, + id: 97, name: r'themeIsDark', type: IsarType.bool, ), r'updateProgressAfterReading': PropertySchema( - id: 97, + id: 98, name: r'updateProgressAfterReading', type: IsarType.bool, ), r'useLibass': PropertySchema( - id: 98, + id: 99, name: r'useLibass', type: IsarType.bool, ), r'usePageTapZones': PropertySchema( - id: 99, + id: 100, name: r'usePageTapZones', type: IsarType.bool, ), r'userAgent': PropertySchema( - id: 100, + id: 101, name: r'userAgent', type: IsarType.string, ) @@ -619,7 +624,7 @@ int _settingsEstimateSize( } } { - final value = object.backupFrequencyOptions; + final value = object.backupListOptions; if (value != null) { bytesCount += 3 + value.length * 8; } @@ -865,7 +870,7 @@ void _settingsSerialize( ); writer.writeByte(offsets[14], object.backgroundColor.index); writer.writeLong(offsets[15], object.backupFrequency); - writer.writeLongList(offsets[16], object.backupFrequencyOptions); + writer.writeLongList(offsets[16], object.backupListOptions); writer.writeString(offsets[17], object.btServerAddress); writer.writeLong(offsets[18], object.btServerPort); writer.writeObjectList( @@ -899,137 +904,138 @@ void _settingsSerialize( object.chapterPageUrlsList, ); writer.writeBool(offsets[24], object.checkForExtensionUpdates); - writer.writeByte(offsets[25], object.colorFilterBlendMode.index); + writer.writeBool(offsets[25], object.clearChapterCacheOnAppLaunch); + writer.writeByte(offsets[26], object.colorFilterBlendMode.index); writer.writeObjectList( - offsets[26], + offsets[27], allOffsets, MCookieSchema.serialize, object.cookiesList, ); - writer.writeBool(offsets[27], object.cropBorders); + writer.writeBool(offsets[28], object.cropBorders); writer.writeObject( - offsets[28], + offsets[29], allOffsets, CustomColorFilterSchema.serialize, object.customColorFilter, ); - writer.writeString(offsets[29], object.dateFormat); - writer.writeLong(offsets[30], object.defaultDoubleTapToSkipLength); - writer.writeDouble(offsets[31], object.defaultPlayBackSpeed); - writer.writeByte(offsets[32], object.defaultReaderMode.index); - writer.writeLong(offsets[33], object.defaultSkipIntroLength); - writer.writeByte(offsets[34], object.disableSectionType.index); - writer.writeByte(offsets[35], object.displayType.index); - writer.writeLong(offsets[36], object.doubleTapAnimationSpeed); - writer.writeString(offsets[37], object.downloadLocation); - writer.writeBool(offsets[38], object.downloadOnlyOnWifi); - writer.writeBool(offsets[39], object.enableAniSkip); - writer.writeBool(offsets[40], object.enableAutoSkip); - writer.writeBool(offsets[41], object.enableCustomColorFilter); + writer.writeString(offsets[30], object.dateFormat); + writer.writeLong(offsets[31], object.defaultDoubleTapToSkipLength); + writer.writeDouble(offsets[32], object.defaultPlayBackSpeed); + writer.writeByte(offsets[33], object.defaultReaderMode.index); + writer.writeLong(offsets[34], object.defaultSkipIntroLength); + writer.writeByte(offsets[35], object.disableSectionType.index); + writer.writeByte(offsets[36], object.displayType.index); + writer.writeLong(offsets[37], object.doubleTapAnimationSpeed); + writer.writeString(offsets[38], object.downloadLocation); + writer.writeBool(offsets[39], object.downloadOnlyOnWifi); + writer.writeBool(offsets[40], object.enableAniSkip); + writer.writeBool(offsets[41], object.enableAutoSkip); + writer.writeBool(offsets[42], object.enableCustomColorFilter); writer.writeObjectList( - offsets[42], + offsets[43], allOffsets, FilterScanlatorSchema.serialize, object.filterScanlatorList, ); - writer.writeDouble(offsets[43], object.flexColorSchemeBlendLevel); - writer.writeLong(offsets[44], object.flexSchemeColorIndex); - writer.writeBool(offsets[45], object.fullScreenPlayer); - writer.writeBool(offsets[46], object.fullScreenReader); - writer.writeBool(offsets[47], object.hideAnime); - writer.writeBool(offsets[48], object.hideManga); - writer.writeBool(offsets[49], object.hideNovel); - writer.writeBool(offsets[50], object.incognitoMode); - writer.writeBool(offsets[51], object.libraryDownloadedChapters); - writer.writeLong(offsets[52], object.libraryFilterAnimeBookMarkedType); - writer.writeLong(offsets[53], object.libraryFilterAnimeDownloadType); - writer.writeLong(offsets[54], object.libraryFilterAnimeStartedType); - writer.writeLong(offsets[55], object.libraryFilterAnimeUnreadType); - writer.writeLong(offsets[56], object.libraryFilterMangasBookMarkedType); - writer.writeLong(offsets[57], object.libraryFilterMangasDownloadType); - writer.writeLong(offsets[58], object.libraryFilterMangasStartedType); - writer.writeLong(offsets[59], object.libraryFilterMangasUnreadType); - writer.writeLong(offsets[60], object.libraryFilterNovelBookMarkedType); - writer.writeLong(offsets[61], object.libraryFilterNovelDownloadType); - writer.writeLong(offsets[62], object.libraryFilterNovelStartedType); - writer.writeLong(offsets[63], object.libraryFilterNovelUnreadType); - writer.writeBool(offsets[64], object.libraryLocalSource); - writer.writeBool(offsets[65], object.libraryShowCategoryTabs); - writer.writeBool(offsets[66], object.libraryShowContinueReadingButton); - writer.writeBool(offsets[67], object.libraryShowLanguage); - writer.writeBool(offsets[68], object.libraryShowNumbersOfItems); + writer.writeDouble(offsets[44], object.flexColorSchemeBlendLevel); + writer.writeLong(offsets[45], object.flexSchemeColorIndex); + writer.writeBool(offsets[46], object.fullScreenPlayer); + writer.writeBool(offsets[47], object.fullScreenReader); + writer.writeBool(offsets[48], object.hideAnime); + writer.writeBool(offsets[49], object.hideManga); + writer.writeBool(offsets[50], object.hideNovel); + writer.writeBool(offsets[51], object.incognitoMode); + writer.writeBool(offsets[52], object.libraryDownloadedChapters); + writer.writeLong(offsets[53], object.libraryFilterAnimeBookMarkedType); + writer.writeLong(offsets[54], object.libraryFilterAnimeDownloadType); + writer.writeLong(offsets[55], object.libraryFilterAnimeStartedType); + writer.writeLong(offsets[56], object.libraryFilterAnimeUnreadType); + writer.writeLong(offsets[57], object.libraryFilterMangasBookMarkedType); + writer.writeLong(offsets[58], object.libraryFilterMangasDownloadType); + writer.writeLong(offsets[59], object.libraryFilterMangasStartedType); + writer.writeLong(offsets[60], object.libraryFilterMangasUnreadType); + writer.writeLong(offsets[61], object.libraryFilterNovelBookMarkedType); + writer.writeLong(offsets[62], object.libraryFilterNovelDownloadType); + writer.writeLong(offsets[63], object.libraryFilterNovelStartedType); + writer.writeLong(offsets[64], object.libraryFilterNovelUnreadType); + writer.writeBool(offsets[65], object.libraryLocalSource); + writer.writeBool(offsets[66], object.libraryShowCategoryTabs); + writer.writeBool(offsets[67], object.libraryShowContinueReadingButton); + writer.writeBool(offsets[68], object.libraryShowLanguage); + writer.writeBool(offsets[69], object.libraryShowNumbersOfItems); writer.writeObject( - offsets[69], + offsets[70], allOffsets, L10nLocaleSchema.serialize, object.locale, ); - writer.writeLong(offsets[70], object.mangaGridSize); - writer.writeByte(offsets[71], object.mangaHomeDisplayType.index); - writer.writeLong(offsets[72], object.markEpisodeAsSeenType); - writer.writeByte(offsets[73], object.novelDisplayType.index); - writer.writeLong(offsets[74], object.novelGridSize); - writer.writeBool(offsets[75], object.novelLibraryDownloadedChapters); - writer.writeBool(offsets[76], object.novelLibraryLocalSource); - writer.writeBool(offsets[77], object.novelLibraryShowCategoryTabs); - writer.writeBool(offsets[78], object.novelLibraryShowContinueReadingButton); - writer.writeBool(offsets[79], object.novelLibraryShowLanguage); - writer.writeBool(offsets[80], object.novelLibraryShowNumbersOfItems); - writer.writeBool(offsets[81], object.onlyIncludePinnedSources); - writer.writeLong(offsets[82], object.pagePreloadAmount); + writer.writeLong(offsets[71], object.mangaGridSize); + writer.writeByte(offsets[72], object.mangaHomeDisplayType.index); + writer.writeLong(offsets[73], object.markEpisodeAsSeenType); + writer.writeByte(offsets[74], object.novelDisplayType.index); + writer.writeLong(offsets[75], object.novelGridSize); + writer.writeBool(offsets[76], object.novelLibraryDownloadedChapters); + writer.writeBool(offsets[77], object.novelLibraryLocalSource); + writer.writeBool(offsets[78], object.novelLibraryShowCategoryTabs); + writer.writeBool(offsets[79], object.novelLibraryShowContinueReadingButton); + writer.writeBool(offsets[80], object.novelLibraryShowLanguage); + writer.writeBool(offsets[81], object.novelLibraryShowNumbersOfItems); + writer.writeBool(offsets[82], object.onlyIncludePinnedSources); + writer.writeLong(offsets[83], object.pagePreloadAmount); writer.writeObjectList( - offsets[83], + offsets[84], allOffsets, PersonalPageModeSchema.serialize, object.personalPageModeList, ); writer.writeObjectList( - offsets[84], + offsets[85], allOffsets, PersonalReaderModeSchema.serialize, object.personalReaderModeList, ); writer.writeObject( - offsets[85], + offsets[86], allOffsets, PlayerSubtitleSettingsSchema.serialize, object.playerSubtitleSettings, ); - writer.writeBool(offsets[86], object.pureBlackDarkMode); - writer.writeLong(offsets[87], object.relativeTimesTamps); - writer.writeBool(offsets[88], object.saveAsCBZArchive); - writer.writeByte(offsets[89], object.scaleType.index); - writer.writeBool(offsets[90], object.showPagesNumber); + writer.writeBool(offsets[87], object.pureBlackDarkMode); + writer.writeLong(offsets[88], object.relativeTimesTamps); + writer.writeBool(offsets[89], object.saveAsCBZArchive); + writer.writeByte(offsets[90], object.scaleType.index); + writer.writeBool(offsets[91], object.showPagesNumber); writer.writeObjectList( - offsets[91], + offsets[92], allOffsets, SortChapterSchema.serialize, object.sortChapterList, ); writer.writeObject( - offsets[92], + offsets[93], allOffsets, SortLibraryMangaSchema.serialize, object.sortLibraryAnime, ); writer.writeObject( - offsets[93], + offsets[94], allOffsets, SortLibraryMangaSchema.serialize, object.sortLibraryManga, ); writer.writeObject( - offsets[94], + offsets[95], allOffsets, SortLibraryMangaSchema.serialize, object.sortLibraryNovel, ); - writer.writeLong(offsets[95], object.startDatebackup); - writer.writeBool(offsets[96], object.themeIsDark); - writer.writeBool(offsets[97], object.updateProgressAfterReading); - writer.writeBool(offsets[98], object.useLibass); - writer.writeBool(offsets[99], object.usePageTapZones); - writer.writeString(offsets[100], object.userAgent); + writer.writeLong(offsets[96], object.startDatebackup); + writer.writeBool(offsets[97], object.themeIsDark); + writer.writeBool(offsets[98], object.updateProgressAfterReading); + writer.writeBool(offsets[99], object.useLibass); + writer.writeBool(offsets[100], object.usePageTapZones); + writer.writeString(offsets[101], object.userAgent); } Settings _settingsDeserialize( @@ -1064,7 +1070,7 @@ Settings _settingsDeserialize( reader.readByteOrNull(offsets[14])] ?? BackgroundColor.black, backupFrequency: reader.readLongOrNull(offsets[15]), - backupFrequencyOptions: reader.readLongList(offsets[16]), + backupListOptions: reader.readLongList(offsets[16]), btServerAddress: reader.readStringOrNull(offsets[17]), btServerPort: reader.readLongOrNull(offsets[18]), chapterFilterDownloadedList: reader.readObjectList( @@ -1086,134 +1092,135 @@ Settings _settingsDeserialize( ChapterPageurls(), ), checkForExtensionUpdates: reader.readBoolOrNull(offsets[24]), + clearChapterCacheOnAppLaunch: reader.readBoolOrNull(offsets[25]), colorFilterBlendMode: _SettingscolorFilterBlendModeValueEnumMap[ - reader.readByteOrNull(offsets[25])] ?? + reader.readByteOrNull(offsets[26])] ?? ColorFilterBlendMode.none, cookiesList: reader.readObjectList( - offsets[26], + offsets[27], MCookieSchema.deserialize, allOffsets, MCookie(), ), - cropBorders: reader.readBoolOrNull(offsets[27]), + cropBorders: reader.readBoolOrNull(offsets[28]), customColorFilter: reader.readObjectOrNull( - offsets[28], + offsets[29], CustomColorFilterSchema.deserialize, allOffsets, ), - dateFormat: reader.readStringOrNull(offsets[29]), - defaultDoubleTapToSkipLength: reader.readLongOrNull(offsets[30]), - defaultPlayBackSpeed: reader.readDoubleOrNull(offsets[31]), + dateFormat: reader.readStringOrNull(offsets[30]), + defaultDoubleTapToSkipLength: reader.readLongOrNull(offsets[31]), + defaultPlayBackSpeed: reader.readDoubleOrNull(offsets[32]), defaultReaderMode: _SettingsdefaultReaderModeValueEnumMap[ - reader.readByteOrNull(offsets[32])] ?? + reader.readByteOrNull(offsets[33])] ?? ReaderMode.vertical, - defaultSkipIntroLength: reader.readLongOrNull(offsets[33]), + defaultSkipIntroLength: reader.readLongOrNull(offsets[34]), disableSectionType: _SettingsdisableSectionTypeValueEnumMap[ - reader.readByteOrNull(offsets[34])] ?? + reader.readByteOrNull(offsets[35])] ?? SectionType.all, displayType: - _SettingsdisplayTypeValueEnumMap[reader.readByteOrNull(offsets[35])] ?? + _SettingsdisplayTypeValueEnumMap[reader.readByteOrNull(offsets[36])] ?? DisplayType.compactGrid, - doubleTapAnimationSpeed: reader.readLongOrNull(offsets[36]), - downloadLocation: reader.readStringOrNull(offsets[37]), - downloadOnlyOnWifi: reader.readBoolOrNull(offsets[38]), - enableAniSkip: reader.readBoolOrNull(offsets[39]), - enableAutoSkip: reader.readBoolOrNull(offsets[40]), - enableCustomColorFilter: reader.readBoolOrNull(offsets[41]), - flexColorSchemeBlendLevel: reader.readDoubleOrNull(offsets[43]), - flexSchemeColorIndex: reader.readLongOrNull(offsets[44]), - fullScreenPlayer: reader.readBoolOrNull(offsets[45]), - fullScreenReader: reader.readBoolOrNull(offsets[46]), - hideAnime: reader.readBoolOrNull(offsets[47]), - hideManga: reader.readBoolOrNull(offsets[48]), - hideNovel: reader.readBoolOrNull(offsets[49]), + doubleTapAnimationSpeed: reader.readLongOrNull(offsets[37]), + downloadLocation: reader.readStringOrNull(offsets[38]), + downloadOnlyOnWifi: reader.readBoolOrNull(offsets[39]), + enableAniSkip: reader.readBoolOrNull(offsets[40]), + enableAutoSkip: reader.readBoolOrNull(offsets[41]), + enableCustomColorFilter: reader.readBoolOrNull(offsets[42]), + flexColorSchemeBlendLevel: reader.readDoubleOrNull(offsets[44]), + flexSchemeColorIndex: reader.readLongOrNull(offsets[45]), + fullScreenPlayer: reader.readBoolOrNull(offsets[46]), + fullScreenReader: reader.readBoolOrNull(offsets[47]), + hideAnime: reader.readBoolOrNull(offsets[48]), + hideManga: reader.readBoolOrNull(offsets[49]), + hideNovel: reader.readBoolOrNull(offsets[50]), id: id, - incognitoMode: reader.readBoolOrNull(offsets[50]), - libraryDownloadedChapters: reader.readBoolOrNull(offsets[51]), - libraryFilterAnimeBookMarkedType: reader.readLongOrNull(offsets[52]), - libraryFilterAnimeDownloadType: reader.readLongOrNull(offsets[53]), - libraryFilterAnimeStartedType: reader.readLongOrNull(offsets[54]), - libraryFilterAnimeUnreadType: reader.readLongOrNull(offsets[55]), - libraryFilterMangasBookMarkedType: reader.readLongOrNull(offsets[56]), - libraryFilterMangasDownloadType: reader.readLongOrNull(offsets[57]), - libraryFilterMangasStartedType: reader.readLongOrNull(offsets[58]), - libraryFilterMangasUnreadType: reader.readLongOrNull(offsets[59]), - libraryFilterNovelBookMarkedType: reader.readLongOrNull(offsets[60]), - libraryFilterNovelDownloadType: reader.readLongOrNull(offsets[61]), - libraryFilterNovelStartedType: reader.readLongOrNull(offsets[62]), - libraryFilterNovelUnreadType: reader.readLongOrNull(offsets[63]), - libraryLocalSource: reader.readBoolOrNull(offsets[64]), - libraryShowCategoryTabs: reader.readBoolOrNull(offsets[65]), - libraryShowContinueReadingButton: reader.readBoolOrNull(offsets[66]), - libraryShowLanguage: reader.readBoolOrNull(offsets[67]), - libraryShowNumbersOfItems: reader.readBoolOrNull(offsets[68]), - mangaGridSize: reader.readLongOrNull(offsets[70]), + incognitoMode: reader.readBoolOrNull(offsets[51]), + libraryDownloadedChapters: reader.readBoolOrNull(offsets[52]), + libraryFilterAnimeBookMarkedType: reader.readLongOrNull(offsets[53]), + libraryFilterAnimeDownloadType: reader.readLongOrNull(offsets[54]), + libraryFilterAnimeStartedType: reader.readLongOrNull(offsets[55]), + libraryFilterAnimeUnreadType: reader.readLongOrNull(offsets[56]), + libraryFilterMangasBookMarkedType: reader.readLongOrNull(offsets[57]), + libraryFilterMangasDownloadType: reader.readLongOrNull(offsets[58]), + libraryFilterMangasStartedType: reader.readLongOrNull(offsets[59]), + libraryFilterMangasUnreadType: reader.readLongOrNull(offsets[60]), + libraryFilterNovelBookMarkedType: reader.readLongOrNull(offsets[61]), + libraryFilterNovelDownloadType: reader.readLongOrNull(offsets[62]), + libraryFilterNovelStartedType: reader.readLongOrNull(offsets[63]), + libraryFilterNovelUnreadType: reader.readLongOrNull(offsets[64]), + libraryLocalSource: reader.readBoolOrNull(offsets[65]), + libraryShowCategoryTabs: reader.readBoolOrNull(offsets[66]), + libraryShowContinueReadingButton: reader.readBoolOrNull(offsets[67]), + libraryShowLanguage: reader.readBoolOrNull(offsets[68]), + libraryShowNumbersOfItems: reader.readBoolOrNull(offsets[69]), + mangaGridSize: reader.readLongOrNull(offsets[71]), mangaHomeDisplayType: _SettingsmangaHomeDisplayTypeValueEnumMap[ - reader.readByteOrNull(offsets[71])] ?? + reader.readByteOrNull(offsets[72])] ?? DisplayType.comfortableGrid, - markEpisodeAsSeenType: reader.readLongOrNull(offsets[72]), + markEpisodeAsSeenType: reader.readLongOrNull(offsets[73]), novelDisplayType: _SettingsnovelDisplayTypeValueEnumMap[ - reader.readByteOrNull(offsets[73])] ?? + reader.readByteOrNull(offsets[74])] ?? DisplayType.comfortableGrid, - novelLibraryDownloadedChapters: reader.readBoolOrNull(offsets[75]), - novelLibraryLocalSource: reader.readBoolOrNull(offsets[76]), - novelLibraryShowCategoryTabs: reader.readBoolOrNull(offsets[77]), - novelLibraryShowContinueReadingButton: reader.readBoolOrNull(offsets[78]), - novelLibraryShowLanguage: reader.readBoolOrNull(offsets[79]), - novelLibraryShowNumbersOfItems: reader.readBoolOrNull(offsets[80]), - onlyIncludePinnedSources: reader.readBoolOrNull(offsets[81]), - pagePreloadAmount: reader.readLongOrNull(offsets[82]), + novelLibraryDownloadedChapters: reader.readBoolOrNull(offsets[76]), + novelLibraryLocalSource: reader.readBoolOrNull(offsets[77]), + novelLibraryShowCategoryTabs: reader.readBoolOrNull(offsets[78]), + novelLibraryShowContinueReadingButton: reader.readBoolOrNull(offsets[79]), + novelLibraryShowLanguage: reader.readBoolOrNull(offsets[80]), + novelLibraryShowNumbersOfItems: reader.readBoolOrNull(offsets[81]), + onlyIncludePinnedSources: reader.readBoolOrNull(offsets[82]), + pagePreloadAmount: reader.readLongOrNull(offsets[83]), personalPageModeList: reader.readObjectList( - offsets[83], + offsets[84], PersonalPageModeSchema.deserialize, allOffsets, PersonalPageMode(), ), personalReaderModeList: reader.readObjectList( - offsets[84], + offsets[85], PersonalReaderModeSchema.deserialize, allOffsets, PersonalReaderMode(), ), playerSubtitleSettings: reader.readObjectOrNull( - offsets[85], + offsets[86], PlayerSubtitleSettingsSchema.deserialize, allOffsets, ), - pureBlackDarkMode: reader.readBoolOrNull(offsets[86]), - relativeTimesTamps: reader.readLongOrNull(offsets[87]), - saveAsCBZArchive: reader.readBoolOrNull(offsets[88]), + pureBlackDarkMode: reader.readBoolOrNull(offsets[87]), + relativeTimesTamps: reader.readLongOrNull(offsets[88]), + saveAsCBZArchive: reader.readBoolOrNull(offsets[89]), scaleType: - _SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offsets[89])] ?? + _SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offsets[90])] ?? ScaleType.fitScreen, - showPagesNumber: reader.readBoolOrNull(offsets[90]), + showPagesNumber: reader.readBoolOrNull(offsets[91]), sortChapterList: reader.readObjectList( - offsets[91], + offsets[92], SortChapterSchema.deserialize, allOffsets, SortChapter(), ), sortLibraryAnime: reader.readObjectOrNull( - offsets[92], - SortLibraryMangaSchema.deserialize, - allOffsets, - ), - sortLibraryManga: reader.readObjectOrNull( offsets[93], SortLibraryMangaSchema.deserialize, allOffsets, ), - sortLibraryNovel: reader.readObjectOrNull( + sortLibraryManga: reader.readObjectOrNull( offsets[94], SortLibraryMangaSchema.deserialize, allOffsets, ), - startDatebackup: reader.readLongOrNull(offsets[95]), - themeIsDark: reader.readBoolOrNull(offsets[96]), - updateProgressAfterReading: reader.readBoolOrNull(offsets[97]), - useLibass: reader.readBoolOrNull(offsets[98]), - usePageTapZones: reader.readBoolOrNull(offsets[99]), - userAgent: reader.readStringOrNull(offsets[100]), + sortLibraryNovel: reader.readObjectOrNull( + offsets[95], + SortLibraryMangaSchema.deserialize, + allOffsets, + ), + startDatebackup: reader.readLongOrNull(offsets[96]), + themeIsDark: reader.readBoolOrNull(offsets[97]), + updateProgressAfterReading: reader.readBoolOrNull(offsets[98]), + useLibass: reader.readBoolOrNull(offsets[99]), + usePageTapZones: reader.readBoolOrNull(offsets[100]), + userAgent: reader.readStringOrNull(offsets[101]), ); object.chapterFilterBookmarkedList = reader.readObjectList( @@ -1229,17 +1236,17 @@ Settings _settingsDeserialize( ChapterFilterUnread(), ); object.filterScanlatorList = reader.readObjectList( - offsets[42], + offsets[43], FilterScanlatorSchema.deserialize, allOffsets, FilterScanlator(), ); object.locale = reader.readObjectOrNull( - offsets[69], + offsets[70], L10nLocaleSchema.deserialize, allOffsets, ); - object.novelGridSize = reader.readLongOrNull(offsets[74]); + object.novelGridSize = reader.readLongOrNull(offsets[75]); return object; } @@ -1335,49 +1342,49 @@ P _settingsDeserializeProp

( case 24: return (reader.readBoolOrNull(offset)) as P; case 25: + return (reader.readBoolOrNull(offset)) as P; + case 26: return (_SettingscolorFilterBlendModeValueEnumMap[ reader.readByteOrNull(offset)] ?? ColorFilterBlendMode.none) as P; - case 26: + case 27: return (reader.readObjectList( offset, MCookieSchema.deserialize, allOffsets, MCookie(), )) as P; - case 27: - return (reader.readBoolOrNull(offset)) as P; case 28: + return (reader.readBoolOrNull(offset)) as P; + case 29: return (reader.readObjectOrNull( offset, CustomColorFilterSchema.deserialize, allOffsets, )) as P; - case 29: - return (reader.readStringOrNull(offset)) as P; case 30: - return (reader.readLongOrNull(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 31: - return (reader.readDoubleOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 32: + return (reader.readDoubleOrNull(offset)) as P; + case 33: return (_SettingsdefaultReaderModeValueEnumMap[ reader.readByteOrNull(offset)] ?? ReaderMode.vertical) as P; - case 33: - return (reader.readLongOrNull(offset)) as P; case 34: + return (reader.readLongOrNull(offset)) as P; + case 35: return (_SettingsdisableSectionTypeValueEnumMap[ reader.readByteOrNull(offset)] ?? SectionType.all) as P; - case 35: + case 36: return (_SettingsdisplayTypeValueEnumMap[reader.readByteOrNull(offset)] ?? DisplayType.compactGrid) as P; - case 36: - return (reader.readLongOrNull(offset)) as P; case 37: - return (reader.readStringOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 38: - return (reader.readBoolOrNull(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 39: return (reader.readBoolOrNull(offset)) as P; case 40: @@ -1385,18 +1392,18 @@ P _settingsDeserializeProp

( case 41: return (reader.readBoolOrNull(offset)) as P; case 42: + return (reader.readBoolOrNull(offset)) as P; + case 43: return (reader.readObjectList( offset, FilterScanlatorSchema.deserialize, allOffsets, FilterScanlator(), )) as P; - case 43: - return (reader.readDoubleOrNull(offset)) as P; case 44: - return (reader.readLongOrNull(offset)) as P; + return (reader.readDoubleOrNull(offset)) as P; case 45: - return (reader.readBoolOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 46: return (reader.readBoolOrNull(offset)) as P; case 47: @@ -1410,7 +1417,7 @@ P _settingsDeserializeProp

( case 51: return (reader.readBoolOrNull(offset)) as P; case 52: - return (reader.readLongOrNull(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 53: return (reader.readLongOrNull(offset)) as P; case 54: @@ -1434,7 +1441,7 @@ P _settingsDeserializeProp

( case 63: return (reader.readLongOrNull(offset)) as P; case 64: - return (reader.readBoolOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 65: return (reader.readBoolOrNull(offset)) as P; case 66: @@ -1444,27 +1451,27 @@ P _settingsDeserializeProp

( case 68: return (reader.readBoolOrNull(offset)) as P; case 69: + return (reader.readBoolOrNull(offset)) as P; + case 70: return (reader.readObjectOrNull( offset, L10nLocaleSchema.deserialize, allOffsets, )) as P; - case 70: - return (reader.readLongOrNull(offset)) as P; case 71: + return (reader.readLongOrNull(offset)) as P; + case 72: return (_SettingsmangaHomeDisplayTypeValueEnumMap[ reader.readByteOrNull(offset)] ?? DisplayType.comfortableGrid) as P; - case 72: - return (reader.readLongOrNull(offset)) as P; case 73: + return (reader.readLongOrNull(offset)) as P; + case 74: return (_SettingsnovelDisplayTypeValueEnumMap[ reader.readByteOrNull(offset)] ?? DisplayType.comfortableGrid) as P; - case 74: - return (reader.readLongOrNull(offset)) as P; case 75: - return (reader.readBoolOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 76: return (reader.readBoolOrNull(offset)) as P; case 77: @@ -1478,51 +1485,47 @@ P _settingsDeserializeProp

( case 81: return (reader.readBoolOrNull(offset)) as P; case 82: - return (reader.readLongOrNull(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 83: + return (reader.readLongOrNull(offset)) as P; + case 84: return (reader.readObjectList( offset, PersonalPageModeSchema.deserialize, allOffsets, PersonalPageMode(), )) as P; - case 84: + case 85: return (reader.readObjectList( offset, PersonalReaderModeSchema.deserialize, allOffsets, PersonalReaderMode(), )) as P; - case 85: + case 86: return (reader.readObjectOrNull( offset, PlayerSubtitleSettingsSchema.deserialize, allOffsets, )) as P; - case 86: - return (reader.readBoolOrNull(offset)) as P; case 87: - return (reader.readLongOrNull(offset)) as P; - case 88: return (reader.readBoolOrNull(offset)) as P; + case 88: + return (reader.readLongOrNull(offset)) as P; case 89: + return (reader.readBoolOrNull(offset)) as P; + case 90: return (_SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offset)] ?? ScaleType.fitScreen) as P; - case 90: - return (reader.readBoolOrNull(offset)) as P; case 91: + return (reader.readBoolOrNull(offset)) as P; + case 92: return (reader.readObjectList( offset, SortChapterSchema.deserialize, allOffsets, SortChapter(), )) as P; - case 92: - return (reader.readObjectOrNull( - offset, - SortLibraryMangaSchema.deserialize, - allOffsets, - )) as P; case 93: return (reader.readObjectOrNull( offset, @@ -1536,9 +1539,13 @@ P _settingsDeserializeProp

( allOffsets, )) as P; case 95: - return (reader.readLongOrNull(offset)) as P; + return (reader.readObjectOrNull( + offset, + SortLibraryMangaSchema.deserialize, + allOffsets, + )) as P; case 96: - return (reader.readBoolOrNull(offset)) as P; + return (reader.readLongOrNull(offset)) as P; case 97: return (reader.readBoolOrNull(offset)) as P; case 98: @@ -1546,6 +1553,8 @@ P _settingsDeserializeProp

( case 99: return (reader.readBoolOrNull(offset)) as P; case 100: + return (reader.readBoolOrNull(offset)) as P; + case 101: return (reader.readStringOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); @@ -2745,63 +2754,63 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsIsNull() { + backupListOptionsIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( - property: r'backupFrequencyOptions', + property: r'backupListOptions', )); }); } QueryBuilder - backupFrequencyOptionsIsNotNull() { + backupListOptionsIsNotNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNotNull( - property: r'backupFrequencyOptions', + property: r'backupListOptions', )); }); } QueryBuilder - backupFrequencyOptionsElementEqualTo(int value) { + backupListOptionsElementEqualTo(int value) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.equalTo( - property: r'backupFrequencyOptions', + property: r'backupListOptions', value: value, )); }); } QueryBuilder - backupFrequencyOptionsElementGreaterThan( + backupListOptionsElementGreaterThan( int value, { bool include = false, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.greaterThan( include: include, - property: r'backupFrequencyOptions', + property: r'backupListOptions', value: value, )); }); } QueryBuilder - backupFrequencyOptionsElementLessThan( + backupListOptionsElementLessThan( int value, { bool include = false, }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.lessThan( include: include, - property: r'backupFrequencyOptions', + property: r'backupListOptions', value: value, )); }); } QueryBuilder - backupFrequencyOptionsElementBetween( + backupListOptionsElementBetween( int lower, int upper, { bool includeLower = true, @@ -2809,7 +2818,7 @@ extension SettingsQueryFilter }) { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(FilterCondition.between( - property: r'backupFrequencyOptions', + property: r'backupListOptions', lower: lower, includeLower: includeLower, upper: upper, @@ -2819,10 +2828,10 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsLengthEqualTo(int length) { + backupListOptionsLengthEqualTo(int length) { return QueryBuilder.apply(this, (query) { return query.listLength( - r'backupFrequencyOptions', + r'backupListOptions', length, true, length, @@ -2832,10 +2841,10 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsIsEmpty() { + backupListOptionsIsEmpty() { return QueryBuilder.apply(this, (query) { return query.listLength( - r'backupFrequencyOptions', + r'backupListOptions', 0, true, 0, @@ -2845,10 +2854,10 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsIsNotEmpty() { + backupListOptionsIsNotEmpty() { return QueryBuilder.apply(this, (query) { return query.listLength( - r'backupFrequencyOptions', + r'backupListOptions', 0, false, 999999, @@ -2858,13 +2867,13 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsLengthLessThan( + backupListOptionsLengthLessThan( int length, { bool include = false, }) { return QueryBuilder.apply(this, (query) { return query.listLength( - r'backupFrequencyOptions', + r'backupListOptions', 0, true, length, @@ -2874,13 +2883,13 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsLengthGreaterThan( + backupListOptionsLengthGreaterThan( int length, { bool include = false, }) { return QueryBuilder.apply(this, (query) { return query.listLength( - r'backupFrequencyOptions', + r'backupListOptions', length, include, 999999, @@ -2890,7 +2899,7 @@ extension SettingsQueryFilter } QueryBuilder - backupFrequencyOptionsLengthBetween( + backupListOptionsLengthBetween( int lower, int upper, { bool includeLower = true, @@ -2898,7 +2907,7 @@ extension SettingsQueryFilter }) { return QueryBuilder.apply(this, (query) { return query.listLength( - r'backupFrequencyOptions', + r'backupListOptions', lower, includeLower, upper, @@ -3695,6 +3704,34 @@ extension SettingsQueryFilter }); } + QueryBuilder + clearChapterCacheOnAppLaunchIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'clearChapterCacheOnAppLaunch', + )); + }); + } + + QueryBuilder + clearChapterCacheOnAppLaunchIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'clearChapterCacheOnAppLaunch', + )); + }); + } + + QueryBuilder + clearChapterCacheOnAppLaunchEqualTo(bool? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'clearChapterCacheOnAppLaunch', + value: value, + )); + }); + } + QueryBuilder colorFilterBlendModeEqualTo(ColorFilterBlendMode value) { return QueryBuilder.apply(this, (query) { @@ -8311,6 +8348,20 @@ extension SettingsQuerySortBy on QueryBuilder { }); } + QueryBuilder + sortByClearChapterCacheOnAppLaunch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'clearChapterCacheOnAppLaunch', Sort.asc); + }); + } + + QueryBuilder + sortByClearChapterCacheOnAppLaunchDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'clearChapterCacheOnAppLaunch', Sort.desc); + }); + } + QueryBuilder sortByColorFilterBlendMode() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'colorFilterBlendMode', Sort.asc); @@ -9401,6 +9452,20 @@ extension SettingsQuerySortThenBy }); } + QueryBuilder + thenByClearChapterCacheOnAppLaunch() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'clearChapterCacheOnAppLaunch', Sort.asc); + }); + } + + QueryBuilder + thenByClearChapterCacheOnAppLaunchDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'clearChapterCacheOnAppLaunch', Sort.desc); + }); + } + QueryBuilder thenByColorFilterBlendMode() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'colorFilterBlendMode', Sort.asc); @@ -10368,10 +10433,9 @@ extension SettingsQueryWhereDistinct }); } - QueryBuilder - distinctByBackupFrequencyOptions() { + QueryBuilder distinctByBackupListOptions() { return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'backupFrequencyOptions'); + return query.addDistinctBy(r'backupListOptions'); }); } @@ -10396,6 +10460,13 @@ extension SettingsQueryWhereDistinct }); } + QueryBuilder + distinctByClearChapterCacheOnAppLaunch() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'clearChapterCacheOnAppLaunch'); + }); + } + QueryBuilder distinctByColorFilterBlendMode() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'colorFilterBlendMode'); @@ -10939,9 +11010,9 @@ extension SettingsQueryProperty } QueryBuilder?, QQueryOperations> - backupFrequencyOptionsProperty() { + backupListOptionsProperty() { return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'backupFrequencyOptions'); + return query.addPropertyName(r'backupListOptions'); }); } @@ -10999,6 +11070,13 @@ extension SettingsQueryProperty }); } + QueryBuilder + clearChapterCacheOnAppLaunchProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'clearChapterCacheOnAppLaunch'); + }); + } + QueryBuilder colorFilterBlendModeProperty() { return QueryBuilder.apply(this, (query) { diff --git a/lib/modules/main_view/main_screen.dart b/lib/modules/main_view/main_screen.dart index e771cf2..e0c9bfd 100644 --- a/lib/modules/main_view/main_screen.dart +++ b/lib/modules/main_view/main_screen.dart @@ -14,7 +14,7 @@ import 'package:mangayomi/services/fetch_anime_sources.dart'; import 'package:mangayomi/services/fetch_manga_sources.dart'; import 'package:mangayomi/modules/main_view/providers/migration.dart'; import 'package:mangayomi/modules/more/about/providers/check_for_update.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/providers/auto_backup.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/auto_backup.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/router/router.dart'; import 'package:mangayomi/services/fetch_novel_sources.dart'; diff --git a/lib/modules/more/backup_and_restore/backup_and_restore.dart b/lib/modules/more/backup_and_restore/backup_and_restore.dart deleted file mode 100644 index bebb75f..0000000 --- a/lib/modules/more/backup_and_restore/backup_and_restore.dart +++ /dev/null @@ -1,401 +0,0 @@ -import 'dart:io'; -import 'package:file_picker/file_picker.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:mangayomi/eval/model/m_bridge.dart'; -import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/providers/auto_backup.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/providers/backup.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/providers/restore.dart'; -import 'package:mangayomi/providers/l10n_providers.dart'; -import 'package:mangayomi/providers/storage_provider.dart'; -import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; - -class BackupAndRestore extends ConsumerWidget { - const BackupAndRestore({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final backupFrequency = ref.watch(backupFrequencyStateProvider); - final backupFrequencyOptions = - ref.watch(backupFrequencyOptionsStateProvider); - final autoBackupLocation = ref.watch(autoBackupLocationStateProvider); - ref.read(autoBackupLocationStateProvider.notifier).refresh(); - - final l10n = l10nLocalizations(context)!; - return Scaffold( - appBar: AppBar( - title: Text(l10n.backup_and_restore), - ), - body: SingleChildScrollView( - child: Column( - children: [ - ListTile( - onTap: () { - final list = _getList(context); - List indexList = []; - indexList.addAll(backupFrequencyOptions); - showDialog( - context: context, - builder: (context) { - return StatefulBuilder( - builder: (context, setState) { - return AlertDialog( - title: Text(l10n.create_backup_dialog_title), - content: SizedBox( - width: context.width(0.8), - child: ListView.builder( - shrinkWrap: true, - itemCount: list.length, - itemBuilder: (context, index) { - return ListTileChapterFilter( - label: list[index], - type: indexList.contains(index) ? 1 : 0, - onTap: () { - if (indexList.contains(index)) { - setState(() { - indexList.remove(index); - }); - } else { - setState(() { - indexList.add(index); - }); - } - }); - }, - )), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () async { - Navigator.pop(context); - }, - child: Text( - l10n.cancel, - style: TextStyle( - color: context.primaryColor), - )), - TextButton( - onPressed: () async { - String? result; - if (Platform.isIOS) { - result = (await StorageProvider() - .getIosBackupDirectory())! - .path; - } else { - result = await FilePicker.platform - .getDirectoryPath(); - } - - if (result != null && context.mounted) { - ref.watch(doBackUpProvider( - list: indexList, - path: result, - context: context)); - } - }, - child: Text( - l10n.ok, - style: TextStyle( - color: context.primaryColor), - )), - ], - ) - ], - ); - }, - ); - }); - }, - title: Text(l10n.create_backup), - subtitle: Text( - l10n.create_backup_subtitle, - style: TextStyle(fontSize: 11, color: context.secondaryColor), - ), - ), - ListTile( - onTap: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text(l10n.restore_backup), - content: SizedBox( - width: context.width(0.8), - child: ListView( - shrinkWrap: true, - children: [ - Row( - children: [ - Icon(Icons.info_outline_rounded, - color: context.secondaryColor), - ], - ), - Padding( - padding: - const EdgeInsets.symmetric(vertical: 5), - child: - Text(l10n.restore_backup_warning_title), - ), - ], - )), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () async { - Navigator.pop(context); - }, - child: Text( - l10n.cancel, - style: - TextStyle(color: context.primaryColor), - )), - TextButton( - onPressed: () async { - try { - FilePickerResult? result = - await FilePicker.platform - .pickFiles(allowMultiple: false); - - if (result != null && context.mounted) { - ref.watch(doRestoreProvider( - path: result.files.first.path!, - context: context)); - } - if (!context.mounted) return; - Navigator.pop(context); - } catch (_) { - botToast("Error"); - Navigator.pop(context); - } - }, - child: Text( - l10n.ok, - style: - TextStyle(color: context.primaryColor), - )), - ], - ) - ], - ); - }); - }, - title: Text(l10n.restore_backup), - subtitle: Text( - l10n.restore_backup_subtitle, - style: TextStyle(fontSize: 11, color: context.secondaryColor), - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20), - child: Row( - children: [ - Text(l10n.automatic_backups, - style: - TextStyle(fontSize: 13, color: context.primaryColor)), - ], - ), - ), - ListTile( - onTap: () { - showDialog( - context: context, - builder: (context) { - final list = _getBackupFrequencyList(context); - return AlertDialog( - title: Text(l10n.backup_frequency), - content: SizedBox( - width: context.width(0.8), - child: ListView.builder( - shrinkWrap: true, - itemCount: list.length, - itemBuilder: (context, index) { - return RadioListTile( - dense: true, - contentPadding: const EdgeInsets.all(0), - value: index, - groupValue: backupFrequency, - onChanged: (value) { - ref - .read(backupFrequencyStateProvider - .notifier) - .set(value!); - Navigator.pop(context); - }, - title: Row( - children: [Text(list[index])], - ), - ); - }, - )), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () async { - Navigator.pop(context); - }, - child: Text( - l10n.cancel, - style: - TextStyle(color: context.primaryColor), - )), - ], - ) - ], - ); - }); - }, - title: Text(l10n.backup_frequency), - subtitle: Text( - _getBackupFrequencyList(context)[backupFrequency], - style: TextStyle(fontSize: 11, color: context.secondaryColor), - ), - ), - if (!Platform.isIOS) - ListTile( - onTap: () async { - String? result = await FilePicker.platform.getDirectoryPath(); - - if (result != null) { - ref - .read(autoBackupLocationStateProvider.notifier) - .set(result); - } - }, - title: Text(l10n.backup_location), - subtitle: Text( - autoBackupLocation.$2.isEmpty - ? autoBackupLocation.$1 - : autoBackupLocation.$2, - style: TextStyle(fontSize: 11, color: context.secondaryColor), - ), - ), - ListTile( - onTap: () { - final list = _getList(context); - List indexList = []; - indexList.addAll(backupFrequencyOptions); - showDialog( - context: context, - builder: (context) { - return StatefulBuilder( - builder: (context, setState) { - return AlertDialog( - title: Text( - l10n.backup_options_subtitle, - ), - content: SizedBox( - width: context.width(0.8), - child: ListView.builder( - shrinkWrap: true, - itemCount: list.length, - itemBuilder: (context, index) { - return ListTileChapterFilter( - label: list[index], - type: indexList.contains(index) ? 1 : 0, - onTap: () { - if (indexList.contains(index)) { - setState(() { - indexList.remove(index); - }); - } else { - setState(() { - indexList.add(index); - }); - } - }); - }, - )), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () async { - Navigator.pop(context); - }, - child: Text( - l10n.cancel, - style: TextStyle( - color: context.primaryColor), - )), - TextButton( - onPressed: () async { - ref - .read( - backupFrequencyOptionsStateProvider - .notifier) - .set(indexList); - Navigator.pop(context); - }, - child: Text( - l10n.ok, - style: TextStyle( - color: context.primaryColor), - )), - ], - ) - ], - ); - }, - ); - }); - }, - title: Text(l10n.backup_options), - subtitle: Text( - l10n.backup_options_subtitle, - style: TextStyle(fontSize: 11, color: context.secondaryColor), - ), - ), - ListTile( - title: Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - children: [ - Icon(Icons.info_outline_rounded, - color: context.secondaryColor), - ], - ), - ), - subtitle: Text(l10n.backup_and_restore_warning_info, - style: - TextStyle(fontSize: 11, color: context.secondaryColor)), - ) - ], - ), - ), - ); - } -} - -List _getList(BuildContext context) { - final l10n = l10nLocalizations(context)!; - return [ - l10n.library_entries, - l10n.categories, - l10n.chapters_and_episode, - l10n.tracking, - l10n.history, - l10n.settings, - l10n.extensions, - l10n.updates - ]; -} - -List _getBackupFrequencyList(BuildContext context) { - final l10n = l10nLocalizations(context)!; - return [ - l10n.off, - l10n.every_6_hours, - l10n.every_12_hours, - l10n.daily, - l10n.every_2_days, - l10n.weekly - ]; -} diff --git a/lib/modules/more/data_and_storage/create_backup.dart b/lib/modules/more/data_and_storage/create_backup.dart new file mode 100644 index 0000000..3297227 --- /dev/null +++ b/lib/modules/more/data_and_storage/create_backup.dart @@ -0,0 +1,206 @@ +import 'dart:io'; + +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/auto_backup.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/backup.dart'; +import 'package:mangayomi/providers/l10n_providers.dart'; +import 'package:mangayomi/providers/storage_provider.dart'; +import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; + +class CreateBackup extends ConsumerStatefulWidget { + const CreateBackup({super.key}); + + @override + ConsumerState createState() => _CreateBackupState(); +} + +class _CreateBackupState extends ConsumerState { + late final List<(String, int)> _libraryList = _getLibraryList(context); + late final List<(String, int)> _settingsList = _getSettingsList(context); + late final List<(String, int)> _extensionList = _getExtensionsList(context); + + void _set(int index, List indexList) { + if (indexList.contains(index)) { + ref + .read(backupFrequencyOptionsStateProvider.notifier) + .set(indexList.where((e) => e != index).toList()); + } else { + ref + .read(backupFrequencyOptionsStateProvider.notifier) + .set([...indexList, index]); + } + } + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + final indexList = ref.watch(backupFrequencyOptionsStateProvider); + return Scaffold( + appBar: AppBar( + title: Text(l10n.create_backup), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Row( + children: [ + Text(l10n.library, + style: TextStyle(fontWeight: FontWeight.bold)), + ], + ), + ), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25)), + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 0, vertical: 15), + shrinkWrap: true, + primary: false, + itemCount: _libraryList.length, + itemBuilder: (context, index) { + final (label, idx) = _libraryList[index]; + return ListTileChapterFilter( + label: label, + type: indexList.contains(idx) ? 1 : 0, + onTap: () { + _set(idx, indexList); + }); + }, + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Row( + children: [ + Text(l10n.settings, + style: TextStyle(fontWeight: FontWeight.bold)), + ], + ), + ), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25)), + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 0, vertical: 15), + shrinkWrap: true, + primary: false, + itemCount: _settingsList.length, + itemBuilder: (context, index) { + final (label, idx) = _settingsList[index]; + return ListTileChapterFilter( + label: label, + type: indexList.contains(idx) ? 1 : 0, + onTap: () { + _set(idx, indexList); + }); + }, + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + child: Row( + children: [ + Text(l10n.extensions, + style: TextStyle(fontWeight: FontWeight.bold)), + ], + ), + ), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25)), + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 0, vertical: 15), + shrinkWrap: true, + primary: false, + itemCount: _extensionList.length, + itemBuilder: (context, index) { + final (label, idx) = _extensionList[index]; + return ListTileChapterFilter( + label: label, + type: indexList.contains(idx) ? 1 : 0, + onTap: () { + _set(idx, indexList); + }); + }, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Divider(color: context.primaryColor, height: 0.3), + ), + Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(bottom: 20), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: context.primaryColor), + onPressed: () async { + String? result; + if (Platform.isIOS) { + result = (await StorageProvider() + .getIosBackupDirectory())! + .path; + } else { + result = + await FilePicker.platform.getDirectoryPath(); + } + + if (result != null && context.mounted) { + ref.watch(doBackUpProvider( + list: indexList, + path: result, + context: context)); + } + }, + child: Text(l10n.create, + style: TextStyle( + color: context.dynamicBlackWhiteColor))), + ), + ), + ], + ) + ], + ), + ), + ), + ); + } +} + +List<(String, int)> _getLibraryList(BuildContext context) { + final l10n = context.l10n; + return [ + (l10n.library_entries, 0), + (l10n.categories, 1), + (l10n.chapters_and_episode, 2), + (l10n.tracking, 3), + (l10n.history, 4), + (l10n.updates, 5) + ]; +} + +List<(String, int)> _getSettingsList(BuildContext context) { + final l10n = context.l10n; + return [ + (l10n.app_settings, 6), + (l10n.sources_settings, 7), + (l10n.include_sensitive_settings, 8), + ]; +} + +List<(String, int)> _getExtensionsList(BuildContext context) { + final l10n = context.l10n; + return [(l10n.extensions, 9)]; +} diff --git a/lib/modules/more/data_and_storage/data_and_storage.dart b/lib/modules/more/data_and_storage/data_and_storage.dart new file mode 100644 index 0000000..5ec9f99 --- /dev/null +++ b/lib/modules/more/data_and_storage/data_and_storage.dart @@ -0,0 +1,379 @@ +import 'dart:io'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mangayomi/eval/model/m_bridge.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/auto_backup.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/restore.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/storage_usage.dart'; +import 'package:mangayomi/modules/more/settings/downloads/providers/downloads_state_provider.dart'; +import 'package:mangayomi/providers/l10n_providers.dart'; +import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; + +class DataAndStorage extends ConsumerWidget { + const DataAndStorage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final backupFrequency = ref.watch(backupFrequencyStateProvider); + final autoBackupLocation = ref.watch(autoBackupLocationStateProvider); + final downloadLocationState = ref.watch(downloadLocationStateProvider); + final totalChapterCacheSize = ref.watch(totalChapterCacheSizeStateProvider); + final clearChapterCacheOnAppLaunch = + ref.watch(clearChapterCacheOnAppLaunchStateProvider); + final l10n = l10nLocalizations(context)!; + return Scaffold( + appBar: AppBar( + title: Text(l10n.data_and_storage), + ), + body: SingleChildScrollView( + child: Column( + children: [ + ListTile( + onTap: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text(l10n.download_location), + content: SizedBox( + width: context.width(0.8), + child: ListView( + shrinkWrap: true, + children: [ + RadioListTile( + dense: true, + contentPadding: const EdgeInsets.all(0), + value: downloadLocationState.$2.isEmpty + ? downloadLocationState.$1 + : downloadLocationState.$2, + groupValue: downloadLocationState.$1, + onChanged: (value) { + ref + .read(downloadLocationStateProvider + .notifier) + .set(""); + Navigator.pop(context); + }, + title: Text(downloadLocationState.$1)), + RadioListTile( + dense: true, + contentPadding: const EdgeInsets.all(0), + value: downloadLocationState.$2.isEmpty + ? downloadLocationState.$1 + : downloadLocationState.$2, + groupValue: downloadLocationState.$2, + onChanged: (value) async { + String? result = await FilePicker.platform + .getDirectoryPath(); + + if (result != null) { + ref + .read(downloadLocationStateProvider + .notifier) + .set(result); + } else {} + if (!context.mounted) return; + Navigator.pop(context); + }, + title: Text(l10n.custom_location)), + ], + )), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () async { + Navigator.pop(context); + }, + child: Text( + l10n.cancel, + style: + TextStyle(color: context.primaryColor), + )), + ], + ) + ], + ); + }); + }, + title: Text(l10n.download_location), + subtitle: Text( + downloadLocationState.$2.isEmpty + ? downloadLocationState.$1 + : downloadLocationState.$2, + style: TextStyle(fontSize: 11, color: context.secondaryColor), + ), + ), + ListTile( + title: Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + Icon(Icons.info_outline_rounded, + color: context.secondaryColor), + ], + ), + ), + subtitle: Text(l10n.download_location_info, + style: + TextStyle(fontSize: 11, color: context.secondaryColor)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20), + child: Row( + children: [ + Text(l10n.backup_and_restore, + style: + TextStyle(fontSize: 13, color: context.primaryColor)), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: Row( + children: [ + Expanded( + child: SegmentedButton( + emptySelectionAllowed: true, + showSelectedIcon: false, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50))), + segments: [ + ButtonSegment( + value: 'create', + label: Padding( + padding: const EdgeInsets.all(12), + child: Text(l10n.create_backup), + ), + ), + ButtonSegment( + value: 'restore', + label: Padding( + padding: const EdgeInsets.all(12), + child: Text(l10n.restore_backup), + ), + ), + ], + selected: {}, + onSelectionChanged: (newSelection) { + if (newSelection.contains('create')) { + context.push('/createBackup'); + } else if (newSelection.contains('restore')) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text(l10n.restore_backup), + content: SizedBox( + width: context.width(0.8), + child: ListView( + shrinkWrap: true, + children: [ + Row( + children: [ + Icon(Icons.info_outline_rounded, + color: + context.secondaryColor), + ], + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 5), + child: Text(l10n + .restore_backup_warning_title), + ), + ], + )), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () async { + Navigator.pop(context); + }, + child: Text( + l10n.cancel, + style: TextStyle( + color: context.primaryColor), + )), + TextButton( + onPressed: () async { + try { + FilePickerResult? result = + await FilePicker.platform + .pickFiles( + allowMultiple: + false); + + if (result != null && + context.mounted) { + ref.watch(doRestoreProvider( + path: result + .files.first.path!, + context: context)); + } + if (!context.mounted) return; + Navigator.pop(context); + } catch (_) { + botToast("Error"); + Navigator.pop(context); + } + }, + child: Text( + l10n.ok, + style: TextStyle( + color: context.primaryColor), + )), + ], + ) + ], + ); + }); + } + }, + ), + ), + ], + ), + ), + ListTile( + onTap: () { + showDialog( + context: context, + builder: (context) { + final list = _getBackupFrequencyList(context); + return AlertDialog( + title: Text(l10n.backup_frequency), + content: SizedBox( + width: context.width(0.8), + child: ListView.builder( + shrinkWrap: true, + itemCount: list.length, + itemBuilder: (context, index) { + return RadioListTile( + dense: true, + contentPadding: const EdgeInsets.all(0), + value: index, + groupValue: backupFrequency, + onChanged: (value) { + ref + .read(backupFrequencyStateProvider + .notifier) + .set(value!); + Navigator.pop(context); + }, + title: Row( + children: [Text(list[index])], + ), + ); + }, + )), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () async { + Navigator.pop(context); + }, + child: Text( + l10n.cancel, + style: + TextStyle(color: context.primaryColor), + )), + ], + ) + ], + ); + }); + }, + title: Text(l10n.backup_frequency), + subtitle: Text( + _getBackupFrequencyList(context)[backupFrequency], + style: TextStyle(fontSize: 11, color: context.secondaryColor), + ), + ), + if (!Platform.isIOS) + ListTile( + onTap: () async { + String? result = await FilePicker.platform.getDirectoryPath(); + + if (result != null) { + ref + .read(autoBackupLocationStateProvider.notifier) + .set(result); + } + }, + title: Text(l10n.backup_location), + subtitle: Text( + autoBackupLocation.$2.isEmpty + ? autoBackupLocation.$1 + : autoBackupLocation.$2, + style: TextStyle(fontSize: 11, color: context.secondaryColor), + ), + ), + ListTile( + title: Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + Icon(Icons.info_outline_rounded, + color: context.secondaryColor), + ], + ), + ), + subtitle: Text(l10n.backup_and_restore_warning_info, + style: + TextStyle(fontSize: 11, color: context.secondaryColor)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20), + child: Row( + children: [ + Text(l10n.storage, + style: + TextStyle(fontSize: 13, color: context.primaryColor)), + ], + ), + ), + ListTile( + title: Text(l10n.clear_chapter_and_episode_cache), + onTap: () => ref + .read(totalChapterCacheSizeStateProvider.notifier) + .clearCache(), + subtitle: Text(totalChapterCacheSize, + style: + TextStyle(fontSize: 11, color: context.secondaryColor)), + ), + SwitchListTile( + value: clearChapterCacheOnAppLaunch, + title: Text( + context.l10n.clear_chapter_or_episode_cache_on_app_launch), + onChanged: (value) { + ref + .read(clearChapterCacheOnAppLaunchStateProvider.notifier) + .set(value); + }), + ], + ), + ), + ); + } +} + +List _getBackupFrequencyList(BuildContext context) { + final l10n = l10nLocalizations(context)!; + return [ + l10n.off, + l10n.every_6_hours, + l10n.every_12_hours, + l10n.daily, + l10n.every_2_days, + l10n.weekly + ]; +} diff --git a/lib/modules/more/backup_and_restore/providers/auto_backup.dart b/lib/modules/more/data_and_storage/providers/auto_backup.dart similarity index 92% rename from lib/modules/more/backup_and_restore/providers/auto_backup.dart rename to lib/modules/more/data_and_storage/providers/auto_backup.dart index f0d729a..f31f616 100644 --- a/lib/modules/more/backup_and_restore/providers/auto_backup.dart +++ b/lib/modules/more/data_and_storage/providers/auto_backup.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/settings.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/providers/backup.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/backup.dart'; import 'package:mangayomi/providers/storage_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -25,14 +25,15 @@ class BackupFrequencyState extends _$BackupFrequencyState { class BackupFrequencyOptionsState extends _$BackupFrequencyOptionsState { @override List build() { - return isar.settings.getSync(227)!.backupFrequencyOptions ?? [0, 1, 2, 3]; + return isar.settings.getSync(227)!.backupListOptions ?? + [0, 1, 2, 3, 4, 5, 6, 7]; } void set(List values) { final settings = isar.settings.getSync(227); state = values; - isar.writeTxnSync(() => - isar.settings.putSync(settings!..backupFrequencyOptions = values)); + isar.writeTxnSync( + () => isar.settings.putSync(settings!..backupListOptions = values)); } } @@ -40,6 +41,7 @@ class BackupFrequencyOptionsState extends _$BackupFrequencyOptionsState { class AutoBackupLocationState extends _$AutoBackupLocationState { @override (String, String) build() { + _refresh(); return ("", isar.settings.getSync(227)!.autoBackupLocation ?? ""); } @@ -52,7 +54,7 @@ class AutoBackupLocationState extends _$AutoBackupLocationState { Directory? _storageProvider; - Future refresh() async { + Future _refresh() async { _storageProvider = Platform.isIOS ? await StorageProvider().getIosBackupDirectory() : await StorageProvider().getDefaultDirectory(); diff --git a/lib/modules/more/backup_and_restore/providers/auto_backup.g.dart b/lib/modules/more/data_and_storage/providers/auto_backup.g.dart similarity index 98% rename from lib/modules/more/backup_and_restore/providers/auto_backup.g.dart rename to lib/modules/more/data_and_storage/providers/auto_backup.g.dart index c196d75..ed4d95b 100644 --- a/lib/modules/more/backup_and_restore/providers/auto_backup.g.dart +++ b/lib/modules/more/data_and_storage/providers/auto_backup.g.dart @@ -58,7 +58,7 @@ final backupFrequencyOptionsStateProvider = AutoDisposeNotifierProvider< typedef _$BackupFrequencyOptionsState = AutoDisposeNotifier>; String _$autoBackupLocationStateHash() => - r'80c41bb34c4ed4d07dce626dd03bb20f01672aec'; + r'be78346bb300287ae9b8581e27ee6814483400a7'; /// See also [AutoBackupLocationState]. @ProviderFor(AutoBackupLocationState) diff --git a/lib/modules/more/backup_and_restore/providers/backup.dart b/lib/modules/more/data_and_storage/providers/backup.dart similarity index 97% rename from lib/modules/more/backup_and_restore/providers/backup.dart rename to lib/modules/more/data_and_storage/providers/backup.dart index 6ccd71b..0fd43fe 100644 --- a/lib/modules/more/backup_and_restore/providers/backup.dart +++ b/lib/modules/more/data_and_storage/providers/backup.dart @@ -74,13 +74,6 @@ Future doBackUp(Ref ref, .map((e) => e.toJson()) .toList(); datas.addAll({"tracks": res}); - final res_ = isar.trackPreferences - .filter() - .syncIdIsNotNull() - .findAllSync() - .map((e) => e.toJson()) - .toList(); - datas.addAll({"trackPreferences": res_}); } if (list.contains(4)) { final res = isar.historys @@ -92,6 +85,15 @@ Future doBackUp(Ref ref, datas.addAll({"history": res}); } if (list.contains(5)) { + final res = isar.updates + .filter() + .idIsNotNull() + .findAllSync() + .map((e) => e.toJson()) + .toList(); + datas.addAll({"updates": res}); + } + if (list.contains(6)) { final res = isar.settings .filter() .idIsNotNull() @@ -100,7 +102,25 @@ Future doBackUp(Ref ref, .toList(); datas.addAll({"settings": res}); } - if (list.contains(6)) { + if (list.contains(7)) { + final res = isar.sourcePreferences + .filter() + .idIsNotNull() + .findAllSync() + .map((e) => e.toJson()) + .toList(); + datas.addAll({"extensions_preferences": res}); + } + if (list.contains(8)) { + final res_ = isar.trackPreferences + .filter() + .syncIdIsNotNull() + .findAllSync() + .map((e) => e.toJson()) + .toList(); + datas.addAll({"trackPreferences": res_}); + } + if (list.contains(9)) { final res = isar.sources .filter() .idIsNotNull() @@ -108,23 +128,6 @@ Future doBackUp(Ref ref, .map((e) => e.toJson()) .toList(); datas.addAll({"extensions": res}); - final resSourePref = isar.sourcePreferences - .filter() - .idIsNotNull() - .keyIsNotNull() - .findAllSync() - .map((e) => e.toJson()) - .toList(); - datas.addAll({"extensions_preferences": resSourePref}); - } - if (list.contains(7)) { - final res = isar.updates - .filter() - .idIsNotNull() - .findAllSync() - .map((e) => e.toJson()) - .toList(); - datas.addAll({"updates": res}); } final regExp = RegExp(r'[^a-zA-Z0-9 .()\-\s]'); final name = diff --git a/lib/modules/more/backup_and_restore/providers/backup.g.dart b/lib/modules/more/data_and_storage/providers/backup.g.dart similarity index 98% rename from lib/modules/more/backup_and_restore/providers/backup.g.dart rename to lib/modules/more/data_and_storage/providers/backup.g.dart index 08b5c32..aad8a8f 100644 --- a/lib/modules/more/backup_and_restore/providers/backup.g.dart +++ b/lib/modules/more/data_and_storage/providers/backup.g.dart @@ -6,7 +6,7 @@ part of 'backup.dart'; // RiverpodGenerator // ************************************************************************** -String _$doBackUpHash() => r'50189cb247f37cadd4d64ddc0377774987859681'; +String _$doBackUpHash() => r'71a9a1aca68f00d68fba134084edc82b7ec614db'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/modules/more/backup_and_restore/providers/restore.dart b/lib/modules/more/data_and_storage/providers/restore.dart similarity index 97% rename from lib/modules/more/backup_and_restore/providers/restore.dart rename to lib/modules/more/data_and_storage/providers/restore.dart index 6b87d1c..5e7749f 100644 --- a/lib/modules/more/backup_and_restore/providers/restore.dart +++ b/lib/modules/more/data_and_storage/providers/restore.dart @@ -84,7 +84,7 @@ void restoreBackup(Ref ref, Map backup) { final extensions = (backup["extensions"] as List?) ?.map((e) => Source.fromJson(e)..itemType = _convertToItemType(e)) .toList(); - final extensionsPref = (backup["extensions_preferences"] as List?) + final sourcesPrefs = (backup["extensions_preferences"] as List?) ?.map((e) => SourcePreference.fromJson(e)) .toList(); final updates = @@ -166,8 +166,8 @@ void restoreBackup(Ref ref, Map backup) { } isar.sourcePreferences.clearSync(); - if (extensionsPref != null) { - isar.sourcePreferences.putAllSync(extensionsPref); + if (sourcesPrefs != null) { + isar.sourcePreferences.putAllSync(sourcesPrefs); } isar.settings.clearSync(); if (settings != null) { diff --git a/lib/modules/more/backup_and_restore/providers/restore.g.dart b/lib/modules/more/data_and_storage/providers/restore.g.dart similarity index 99% rename from lib/modules/more/backup_and_restore/providers/restore.g.dart rename to lib/modules/more/data_and_storage/providers/restore.g.dart index adc0c76..648df8e 100644 --- a/lib/modules/more/backup_and_restore/providers/restore.g.dart +++ b/lib/modules/more/data_and_storage/providers/restore.g.dart @@ -173,7 +173,7 @@ class _DoRestoreProviderElement extends AutoDisposeProviderElement BuildContext get context => (origin as DoRestoreProvider).context; } -String _$restoreBackupHash() => r'834ba688f122cabe7969752ce8be06552c2e70c5'; +String _$restoreBackupHash() => r'8f55a7fa09ef293d558bf336e282ca1f4f44b8d4'; /// See also [restoreBackup]. @ProviderFor(restoreBackup) diff --git a/lib/modules/more/data_and_storage/providers/storage_usage.dart b/lib/modules/more/data_and_storage/providers/storage_usage.dart new file mode 100644 index 0000000..f052a8b --- /dev/null +++ b/lib/modules/more/data_and_storage/providers/storage_usage.dart @@ -0,0 +1,101 @@ +import 'dart:io'; +import 'package:mangayomi/eval/model/m_bridge.dart'; +import 'package:mangayomi/main.dart'; +import 'package:mangayomi/models/settings.dart'; +import 'package:mangayomi/providers/l10n_providers.dart'; +import 'package:mangayomi/router/router.dart'; +import 'package:path/path.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +part 'storage_usage.g.dart'; + +@riverpod +class TotalChapterCacheSizeState extends _$TotalChapterCacheSizeState { + @override + String build() { + _getTotalDiskSpace().then((value) => state = _formatBytes(value)); + return "0.00 B"; + } + + final String _cacheImageMangaPath = join('Mangayomi', 'cacheimagemanga'); + final String _cacheDownloadPath = join('Mangayomi', 'downloads'); + + Future clearCache({bool showToast = true}) async { + final tempPath = (await getTemporaryDirectory()).path; + String? msg; + try { + final dir = Directory(join(tempPath, _cacheImageMangaPath)); + if (dir.existsSync()) { + await dir.delete(recursive: true); + } + msg = "0.00 B"; + } catch (_) {} + try { + final dir = Directory(join(tempPath, _cacheDownloadPath)); + if (dir.existsSync()) { + await dir.delete(recursive: true); + } + msg = "0.00 B"; + } catch (_) {} + if (msg != null && showToast) { + state = msg; + botToast( + navigatorKey.currentContext?.l10n.cache_cleared ?? "Cache cleared"); + } + } + + Future _getTotalDiskSpace() async { + final tempPath = (await getTemporaryDirectory()).path; + try { + return await _getdirectorySize( + Directory(join(tempPath, _cacheImageMangaPath))) + + await _getdirectorySize( + Directory(join(tempPath, _cacheDownloadPath))); + } catch (_) {} + return 0; + } + + Future _getdirectorySize(Directory directory) async { + try { + if (await directory.exists()) { + return directory + .list(recursive: true, followLinks: false) + .where((entity) => entity is File) + .cast() + .fold(0, (total, file) { + return total + file.lengthSync(); + }); + } + } catch (_) {} + return 0; + } + + String _formatBytes(int bytes) { + const units = ['B', 'KB', 'MB', 'GB']; + int unitIndex = 0; + double size = bytes.toDouble(); + + while (size >= 1024 && unitIndex < units.length - 1) { + size /= 1024; + unitIndex++; + } + + return '${size.toStringAsFixed(2)} ${units[unitIndex]}'; + } +} + +@riverpod +class ClearChapterCacheOnAppLaunchState + extends _$ClearChapterCacheOnAppLaunchState { + @override + bool build() { + return isar.settings.getSync(227)!.clearChapterCacheOnAppLaunch ?? false; + } + + void set(bool value) { + final settings = isar.settings.getSync(227); + state = value; + isar.writeTxnSync(() => + isar.settings.putSync(settings!..clearChapterCacheOnAppLaunch = value)); + } +} diff --git a/lib/modules/more/data_and_storage/providers/storage_usage.g.dart b/lib/modules/more/data_and_storage/providers/storage_usage.g.dart new file mode 100644 index 0000000..fc12aad --- /dev/null +++ b/lib/modules/more/data_and_storage/providers/storage_usage.g.dart @@ -0,0 +1,44 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'storage_usage.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$totalChapterCacheSizeStateHash() => + r'798b873b0be804a09e0dfc4049e8f60a41f1a8e8'; + +/// See also [TotalChapterCacheSizeState]. +@ProviderFor(TotalChapterCacheSizeState) +final totalChapterCacheSizeStateProvider = + AutoDisposeNotifierProvider.internal( + TotalChapterCacheSizeState.new, + name: r'totalChapterCacheSizeStateProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$totalChapterCacheSizeStateHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$TotalChapterCacheSizeState = AutoDisposeNotifier; +String _$clearChapterCacheOnAppLaunchStateHash() => + r'6fdefd7a3bdc4309dd596dad43891c654ec2ba70'; + +/// See also [ClearChapterCacheOnAppLaunchState]. +@ProviderFor(ClearChapterCacheOnAppLaunchState) +final clearChapterCacheOnAppLaunchStateProvider = AutoDisposeNotifierProvider< + ClearChapterCacheOnAppLaunchState, bool>.internal( + ClearChapterCacheOnAppLaunchState.new, + name: r'clearChapterCacheOnAppLaunchStateProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$clearChapterCacheOnAppLaunchStateHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$ClearChapterCacheOnAppLaunchState = AutoDisposeNotifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/modules/more/more_screen.dart b/lib/modules/more/more_screen.dart index 1b35bf5..6895883 100644 --- a/lib/modules/more/more_screen.dart +++ b/lib/modules/more/more_screen.dart @@ -57,10 +57,10 @@ class MoreScreen extends StatelessWidget { ), ListTileWidget( onTap: () { - context.push('/backupAndRestore'); + context.push('/dataAndStorage'); }, - icon: Icons.settings_backup_restore_sharp, - title: l10n.backup_and_restore, + icon: Icons.storage, + title: l10n.data_and_storage, ), const Divider(), ListTileWidget( diff --git a/lib/modules/more/settings/downloads/downloads_screen.dart b/lib/modules/more/settings/downloads/downloads_screen.dart index e94887e..da6a6e4 100644 --- a/lib/modules/more/settings/downloads/downloads_screen.dart +++ b/lib/modules/more/settings/downloads/downloads_screen.dart @@ -1,9 +1,7 @@ -import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mangayomi/modules/more/settings/downloads/providers/downloads_state_provider.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; -import 'package:mangayomi/utils/extensions/build_context_extensions.dart'; class DownloadsScreen extends ConsumerStatefulWidget { const DownloadsScreen({super.key}); @@ -19,8 +17,6 @@ class _DownloadsScreenState extends ConsumerState { ) { final saveAsCBZArchiveState = ref.watch(saveAsCBZArchiveStateProvider); final onlyOnWifiState = ref.watch(onlyOnWifiStateProvider); - final downloadLocationState = ref.watch(downloadLocationStateProvider); - ref.read(downloadLocationStateProvider.notifier).refresh(); final l10n = l10nLocalizations(context); return Scaffold( appBar: AppBar( @@ -29,83 +25,6 @@ class _DownloadsScreenState extends ConsumerState { body: SingleChildScrollView( child: Column( children: [ - ListTile( - onTap: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text(l10n.download_location), - content: SizedBox( - width: context.width(0.8), - child: ListView( - shrinkWrap: true, - children: [ - RadioListTile( - dense: true, - contentPadding: const EdgeInsets.all(0), - value: downloadLocationState.$2.isEmpty - ? downloadLocationState.$1 - : downloadLocationState.$2, - groupValue: downloadLocationState.$1, - onChanged: (value) { - ref - .read(downloadLocationStateProvider - .notifier) - .set(""); - Navigator.pop(context); - }, - title: Text(downloadLocationState.$1)), - RadioListTile( - dense: true, - contentPadding: const EdgeInsets.all(0), - value: downloadLocationState.$2.isEmpty - ? downloadLocationState.$1 - : downloadLocationState.$2, - groupValue: downloadLocationState.$2, - onChanged: (value) async { - String? result = await FilePicker.platform - .getDirectoryPath(); - - if (result != null) { - ref - .read(downloadLocationStateProvider - .notifier) - .set(result); - } else {} - if (!context.mounted) return; - Navigator.pop(context); - }, - title: Text(l10n.custom_location)), - ], - )), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () async { - Navigator.pop(context); - }, - child: Text( - l10n.cancel, - style: - TextStyle(color: context.primaryColor), - )), - ], - ) - ], - ); - }); - }, - title: Text(l10n.download_location), - subtitle: Text( - downloadLocationState.$2.isEmpty - ? downloadLocationState.$1 - : downloadLocationState.$2, - style: TextStyle(fontSize: 11, color: context.secondaryColor), - ), - ), SwitchListTile( value: onlyOnWifiState, title: Text(l10n.only_on_wifi), diff --git a/lib/modules/more/settings/downloads/providers/downloads_state_provider.dart b/lib/modules/more/settings/downloads/providers/downloads_state_provider.dart index c376b76..a9ec6c6 100644 --- a/lib/modules/more/settings/downloads/providers/downloads_state_provider.dart +++ b/lib/modules/more/settings/downloads/providers/downloads_state_provider.dart @@ -40,6 +40,7 @@ class SaveAsCBZArchiveState extends _$SaveAsCBZArchiveState { class DownloadLocationState extends _$DownloadLocationState { @override (String, String) build() { + _refresh(); return ("", isar.settings.getSync(227)!.downloadLocation ?? ""); } @@ -52,7 +53,7 @@ class DownloadLocationState extends _$DownloadLocationState { Directory? _storageProvider; - Future refresh() async { + Future _refresh() async { _storageProvider = await StorageProvider().getDefaultDirectory(); final settings = isar.settings.getSync(227); state = ( diff --git a/lib/modules/more/settings/downloads/providers/downloads_state_provider.g.dart b/lib/modules/more/settings/downloads/providers/downloads_state_provider.g.dart index e3d592f..7c83d04 100644 --- a/lib/modules/more/settings/downloads/providers/downloads_state_provider.g.dart +++ b/lib/modules/more/settings/downloads/providers/downloads_state_provider.g.dart @@ -40,7 +40,7 @@ final saveAsCBZArchiveStateProvider = typedef _$SaveAsCBZArchiveState = AutoDisposeNotifier; String _$downloadLocationStateHash() => - r'e4c2215366c10f850b7d52c96c03545a9413b752'; + r'dba216dd8de1206c1c272d0f76684e016e10417f'; /// See also [DownloadLocationState]. @ProviderFor(DownloadLocationState) diff --git a/lib/router/router.dart b/lib/router/router.dart index 94c7c76..e2dda36 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -11,9 +11,10 @@ import 'package:mangayomi/modules/browse/extension/edit_code.dart'; import 'package:mangayomi/modules/browse/extension/extension_detail.dart'; import 'package:mangayomi/modules/browse/extension/widgets/create_extension.dart'; import 'package:mangayomi/modules/browse/sources/sources_filter_screen.dart'; +import 'package:mangayomi/modules/more/data_and_storage/create_backup.dart'; +import 'package:mangayomi/modules/more/data_and_storage/data_and_storage.dart'; import 'package:mangayomi/modules/novel/novel_reader_view.dart'; import 'package:mangayomi/modules/updates/updates_screen.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/backup_and_restore.dart'; import 'package:mangayomi/modules/more/categories/categories_screen.dart'; import 'package:mangayomi/modules/more/settings/downloads/downloads_screen.dart'; import 'package:mangayomi/modules/more/settings/player/player_screen.dart'; @@ -500,15 +501,15 @@ class RouterNotifier extends ChangeNotifier { }, ), GoRoute( - path: "/backupAndRestore", - name: "backupAndRestore", + path: "/dataAndStorage", + name: "dataAndStorage", builder: (context, state) { - return const BackupAndRestore(); + return const DataAndStorage(); }, pageBuilder: (context, state) { return transitionPage( key: state.pageKey, - child: const BackupAndRestore(), + child: const DataAndStorage(), ); }, ), @@ -581,6 +582,19 @@ class RouterNotifier extends ChangeNotifier { ); }, ), + GoRoute( + path: "/createBackup", + name: "createBackup", + builder: (context, state) { + return const CreateBackup(); + }, + pageBuilder: (context, state) { + return transitionPage( + key: state.pageKey, + child: const CreateBackup(), + ); + }, + ), ]; } diff --git a/lib/services/sync_server.dart b/lib/services/sync_server.dart index c6ef4f7..0d77c94 100644 --- a/lib/services/sync_server.dart +++ b/lib/services/sync_server.dart @@ -11,7 +11,7 @@ import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/history.dart'; import 'package:mangayomi/models/settings.dart'; import 'package:mangayomi/models/source.dart'; -import 'package:mangayomi/modules/more/backup_and_restore/providers/restore.dart'; +import 'package:mangayomi/modules/more/data_and_storage/providers/restore.dart'; import 'package:mangayomi/modules/more/settings/sync/models/jwt.dart'; import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart'; import 'dart:convert';