From c28ab14e74c57c3278450f1bed2617776bd82cf3 Mon Sep 17 00:00:00 2001 From: Moustapha Kodjo Amadou <107993382+kodjodevf@users.noreply.github.com> Date: Sat, 8 Nov 2025 19:47:23 +0100 Subject: [PATCH] Refactor auto-scroll functionality in novel reader - Removed the NovelAutoScrollState provider and its associated logic. - Introduced autoScrollValues and setAutoScroll methods in NovelReaderController to manage auto-scroll settings. - Updated NovelReaderView to handle auto-scroll state and page offset dynamically. - Added UI elements in GeneralSettingsTab to control auto-scroll settings with a slider for page offset. - Enhanced the auto-scroll feature to allow for play/pause functionality within the novel reader view. --- lib/models/settings.dart | 5 - lib/models/settings.g.dart | 404 ++++++------- .../providers/reader_state_provider.dart | 20 - .../providers/reader_state_provider.g.dart | 54 -- .../novel_reader_controller_provider.dart | 36 ++ .../novel_reader_controller_provider.g.dart | 2 +- lib/modules/novel/novel_reader_view.dart | 560 ++++++++++-------- .../widgets/novel_reader_settings_sheet.dart | 80 ++- lib/services/get_html_content.g.dart | 2 +- 9 files changed, 592 insertions(+), 571 deletions(-) diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 80d736dd..25b4228e 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -254,8 +254,6 @@ class Settings { bool? novelShowScrollPercentage; - bool? novelAutoScroll; - bool? novelRemoveExtraParagraphSpacing; bool? novelTapToScroll; @@ -413,7 +411,6 @@ class Settings { this.novelReaderPadding = 16, this.novelReaderLineHeight = 1.5, this.novelShowScrollPercentage = true, - this.novelAutoScroll = false, this.novelRemoveExtraParagraphSpacing = false, this.novelTapToScroll = false, this.navigationOrder, @@ -642,7 +639,6 @@ class Settings { novelReaderLineHeight = json['novelReaderLineHeight']; } novelShowScrollPercentage = json['novelShowScrollPercentage']; - novelAutoScroll = json['novelAutoScroll']; novelRemoveExtraParagraphSpacing = json['novelRemoveExtraParagraphSpacing']; novelTapToScroll = json['novelTapToScroll']; if (json['navigationOrder'] != null) { @@ -828,7 +824,6 @@ class Settings { 'novelReaderPadding': novelReaderPadding, 'novelReaderLineHeight': novelReaderLineHeight, 'novelShowScrollPercentage': novelShowScrollPercentage, - 'novelAutoScroll': novelAutoScroll, 'novelRemoveExtraParagraphSpacing': novelRemoveExtraParagraphSpacing, 'novelTapToScroll': novelTapToScroll, 'navigationOrder': navigationOrder, diff --git a/lib/models/settings.g.dart b/lib/models/settings.g.dart index 5de72b6c..a486b9c1 100644 --- a/lib/models/settings.g.dart +++ b/lib/models/settings.g.dart @@ -529,252 +529,247 @@ const SettingsSchema = CollectionSchema( name: r'navigationOrder', type: IsarType.stringList, ), - r'novelAutoScroll': PropertySchema( - id: 95, - name: r'novelAutoScroll', - type: IsarType.bool, - ), r'novelDisplayType': PropertySchema( - id: 96, + id: 95, name: r'novelDisplayType', type: IsarType.byte, enumMap: _SettingsnovelDisplayTypeEnumValueMap, ), r'novelExtensionsRepo': PropertySchema( - id: 97, + id: 96, name: r'novelExtensionsRepo', type: IsarType.objectList, target: r'Repo', ), r'novelFontSize': PropertySchema( - id: 98, + id: 97, name: r'novelFontSize', type: IsarType.long, ), r'novelGridSize': PropertySchema( - id: 99, + id: 98, name: r'novelGridSize', type: IsarType.long, ), r'novelLibraryDownloadedChapters': PropertySchema( - id: 100, + id: 99, name: r'novelLibraryDownloadedChapters', type: IsarType.bool, ), r'novelLibraryLocalSource': PropertySchema( - id: 101, + id: 100, name: r'novelLibraryLocalSource', type: IsarType.bool, ), r'novelLibraryShowCategoryTabs': PropertySchema( - id: 102, + id: 101, name: r'novelLibraryShowCategoryTabs', type: IsarType.bool, ), r'novelLibraryShowContinueReadingButton': PropertySchema( - id: 103, + id: 102, name: r'novelLibraryShowContinueReadingButton', type: IsarType.bool, ), r'novelLibraryShowLanguage': PropertySchema( - id: 104, + id: 103, name: r'novelLibraryShowLanguage', type: IsarType.bool, ), r'novelLibraryShowNumbersOfItems': PropertySchema( - id: 105, + id: 104, name: r'novelLibraryShowNumbersOfItems', type: IsarType.bool, ), r'novelReaderLineHeight': PropertySchema( - id: 106, + id: 105, name: r'novelReaderLineHeight', type: IsarType.double, ), r'novelReaderPadding': PropertySchema( - id: 107, + id: 106, name: r'novelReaderPadding', type: IsarType.long, ), r'novelReaderTextColor': PropertySchema( - id: 108, + id: 107, name: r'novelReaderTextColor', type: IsarType.string, ), r'novelReaderTheme': PropertySchema( - id: 109, + id: 108, name: r'novelReaderTheme', type: IsarType.string, ), r'novelRemoveExtraParagraphSpacing': PropertySchema( - id: 110, + id: 109, name: r'novelRemoveExtraParagraphSpacing', type: IsarType.bool, ), r'novelShowScrollPercentage': PropertySchema( - id: 111, + id: 110, name: r'novelShowScrollPercentage', type: IsarType.bool, ), r'novelTapToScroll': PropertySchema( - id: 112, + id: 111, name: r'novelTapToScroll', type: IsarType.bool, ), r'novelTextAlign': PropertySchema( - id: 113, + id: 112, name: r'novelTextAlign', type: IsarType.byte, enumMap: _SettingsnovelTextAlignEnumValueMap, ), r'onlyIncludePinnedSources': PropertySchema( - id: 114, + id: 113, name: r'onlyIncludePinnedSources', type: IsarType.bool, ), r'pagePreloadAmount': PropertySchema( - id: 115, + id: 114, name: r'pagePreloadAmount', type: IsarType.long, ), r'personalPageModeList': PropertySchema( - id: 116, + id: 115, name: r'personalPageModeList', type: IsarType.objectList, target: r'PersonalPageMode', ), r'personalReaderModeList': PropertySchema( - id: 117, + id: 116, name: r'personalReaderModeList', type: IsarType.objectList, target: r'PersonalReaderMode', ), r'playerSubtitleSettings': PropertySchema( - id: 118, + id: 117, name: r'playerSubtitleSettings', type: IsarType.object, target: r'PlayerSubtitleSettings', ), r'pureBlackDarkMode': PropertySchema( - id: 119, + id: 118, name: r'pureBlackDarkMode', type: IsarType.bool, ), r'relativeTimesTamps': PropertySchema( - id: 120, + id: 119, name: r'relativeTimesTamps', type: IsarType.long, ), r'rpcShowCoverImage': PropertySchema( - id: 121, + id: 120, name: r'rpcShowCoverImage', type: IsarType.bool, ), r'rpcShowReadingWatchingProgress': PropertySchema( - id: 122, + id: 121, name: r'rpcShowReadingWatchingProgress', type: IsarType.bool, ), r'rpcShowTitle': PropertySchema( - id: 123, + id: 122, name: r'rpcShowTitle', type: IsarType.bool, ), r'saveAsCBZArchive': PropertySchema( - id: 124, + id: 123, name: r'saveAsCBZArchive', type: IsarType.bool, ), r'scaleType': PropertySchema( - id: 125, + id: 124, name: r'scaleType', type: IsarType.byte, enumMap: _SettingsscaleTypeEnumValueMap, ), r'showPagesNumber': PropertySchema( - id: 126, + id: 125, name: r'showPagesNumber', type: IsarType.bool, ), r'sortChapterList': PropertySchema( - id: 127, + id: 126, name: r'sortChapterList', type: IsarType.objectList, target: r'SortChapter', ), r'sortLibraryAnime': PropertySchema( - id: 128, + id: 127, name: r'sortLibraryAnime', type: IsarType.object, target: r'SortLibraryManga', ), r'sortLibraryManga': PropertySchema( - id: 129, + id: 128, name: r'sortLibraryManga', type: IsarType.object, target: r'SortLibraryManga', ), r'sortLibraryNovel': PropertySchema( - id: 130, + id: 129, name: r'sortLibraryNovel', type: IsarType.object, target: r'SortLibraryManga', ), r'startDatebackup': PropertySchema( - id: 131, + id: 130, name: r'startDatebackup', type: IsarType.long, ), r'themeIsDark': PropertySchema( - id: 132, + id: 131, name: r'themeIsDark', type: IsarType.bool, ), r'updateProgressAfterReading': PropertySchema( - id: 133, + id: 132, name: r'updateProgressAfterReading', type: IsarType.bool, ), r'updatedAt': PropertySchema( - id: 134, + id: 133, name: r'updatedAt', type: IsarType.long, ), r'useLibass': PropertySchema( - id: 135, + id: 134, name: r'useLibass', type: IsarType.bool, ), r'useMpvConfig': PropertySchema( - id: 136, + id: 135, name: r'useMpvConfig', type: IsarType.bool, ), r'usePageTapZones': PropertySchema( - id: 137, + id: 136, name: r'usePageTapZones', type: IsarType.bool, ), r'useYUV420P': PropertySchema( - id: 138, + id: 137, name: r'useYUV420P', type: IsarType.bool, ), r'userAgent': PropertySchema( - id: 139, + id: 138, name: r'userAgent', type: IsarType.string, ), r'volumeBoostCap': PropertySchema( - id: 140, + id: 139, name: r'volumeBoostCap', type: IsarType.long, ), @@ -1438,92 +1433,91 @@ void _settingsSerialize( writer.writeLong(offsets[92], object.markEpisodeAsSeenType); writer.writeBool(offsets[93], object.mergeLibraryNavMobile); writer.writeStringList(offsets[94], object.navigationOrder); - writer.writeBool(offsets[95], object.novelAutoScroll); - writer.writeByte(offsets[96], object.novelDisplayType.index); + writer.writeByte(offsets[95], object.novelDisplayType.index); writer.writeObjectList( - offsets[97], + offsets[96], allOffsets, RepoSchema.serialize, object.novelExtensionsRepo, ); - writer.writeLong(offsets[98], object.novelFontSize); - writer.writeLong(offsets[99], object.novelGridSize); - writer.writeBool(offsets[100], object.novelLibraryDownloadedChapters); - writer.writeBool(offsets[101], object.novelLibraryLocalSource); - writer.writeBool(offsets[102], object.novelLibraryShowCategoryTabs); - writer.writeBool(offsets[103], object.novelLibraryShowContinueReadingButton); - writer.writeBool(offsets[104], object.novelLibraryShowLanguage); - writer.writeBool(offsets[105], object.novelLibraryShowNumbersOfItems); - writer.writeDouble(offsets[106], object.novelReaderLineHeight); - writer.writeLong(offsets[107], object.novelReaderPadding); - writer.writeString(offsets[108], object.novelReaderTextColor); - writer.writeString(offsets[109], object.novelReaderTheme); - writer.writeBool(offsets[110], object.novelRemoveExtraParagraphSpacing); - writer.writeBool(offsets[111], object.novelShowScrollPercentage); - writer.writeBool(offsets[112], object.novelTapToScroll); - writer.writeByte(offsets[113], object.novelTextAlign.index); - writer.writeBool(offsets[114], object.onlyIncludePinnedSources); - writer.writeLong(offsets[115], object.pagePreloadAmount); + writer.writeLong(offsets[97], object.novelFontSize); + writer.writeLong(offsets[98], object.novelGridSize); + writer.writeBool(offsets[99], object.novelLibraryDownloadedChapters); + writer.writeBool(offsets[100], object.novelLibraryLocalSource); + writer.writeBool(offsets[101], object.novelLibraryShowCategoryTabs); + writer.writeBool(offsets[102], object.novelLibraryShowContinueReadingButton); + writer.writeBool(offsets[103], object.novelLibraryShowLanguage); + writer.writeBool(offsets[104], object.novelLibraryShowNumbersOfItems); + writer.writeDouble(offsets[105], object.novelReaderLineHeight); + writer.writeLong(offsets[106], object.novelReaderPadding); + writer.writeString(offsets[107], object.novelReaderTextColor); + writer.writeString(offsets[108], object.novelReaderTheme); + writer.writeBool(offsets[109], object.novelRemoveExtraParagraphSpacing); + writer.writeBool(offsets[110], object.novelShowScrollPercentage); + writer.writeBool(offsets[111], object.novelTapToScroll); + writer.writeByte(offsets[112], object.novelTextAlign.index); + writer.writeBool(offsets[113], object.onlyIncludePinnedSources); + writer.writeLong(offsets[114], object.pagePreloadAmount); writer.writeObjectList( - offsets[116], + offsets[115], allOffsets, PersonalPageModeSchema.serialize, object.personalPageModeList, ); writer.writeObjectList( - offsets[117], + offsets[116], allOffsets, PersonalReaderModeSchema.serialize, object.personalReaderModeList, ); writer.writeObject( - offsets[118], + offsets[117], allOffsets, PlayerSubtitleSettingsSchema.serialize, object.playerSubtitleSettings, ); - writer.writeBool(offsets[119], object.pureBlackDarkMode); - writer.writeLong(offsets[120], object.relativeTimesTamps); - writer.writeBool(offsets[121], object.rpcShowCoverImage); - writer.writeBool(offsets[122], object.rpcShowReadingWatchingProgress); - writer.writeBool(offsets[123], object.rpcShowTitle); - writer.writeBool(offsets[124], object.saveAsCBZArchive); - writer.writeByte(offsets[125], object.scaleType.index); - writer.writeBool(offsets[126], object.showPagesNumber); + writer.writeBool(offsets[118], object.pureBlackDarkMode); + writer.writeLong(offsets[119], object.relativeTimesTamps); + writer.writeBool(offsets[120], object.rpcShowCoverImage); + writer.writeBool(offsets[121], object.rpcShowReadingWatchingProgress); + writer.writeBool(offsets[122], object.rpcShowTitle); + writer.writeBool(offsets[123], object.saveAsCBZArchive); + writer.writeByte(offsets[124], object.scaleType.index); + writer.writeBool(offsets[125], object.showPagesNumber); writer.writeObjectList( - offsets[127], + offsets[126], allOffsets, SortChapterSchema.serialize, object.sortChapterList, ); writer.writeObject( - offsets[128], + offsets[127], allOffsets, SortLibraryMangaSchema.serialize, object.sortLibraryAnime, ); writer.writeObject( - offsets[129], + offsets[128], allOffsets, SortLibraryMangaSchema.serialize, object.sortLibraryManga, ); writer.writeObject( - offsets[130], + offsets[129], allOffsets, SortLibraryMangaSchema.serialize, object.sortLibraryNovel, ); - writer.writeLong(offsets[131], object.startDatebackup); - writer.writeBool(offsets[132], object.themeIsDark); - writer.writeBool(offsets[133], object.updateProgressAfterReading); - writer.writeLong(offsets[134], object.updatedAt); - writer.writeBool(offsets[135], object.useLibass); - writer.writeBool(offsets[136], object.useMpvConfig); - writer.writeBool(offsets[137], object.usePageTapZones); - writer.writeBool(offsets[138], object.useYUV420P); - writer.writeString(offsets[139], object.userAgent); - writer.writeLong(offsets[140], object.volumeBoostCap); + writer.writeLong(offsets[130], object.startDatebackup); + writer.writeBool(offsets[131], object.themeIsDark); + writer.writeBool(offsets[132], object.updateProgressAfterReading); + writer.writeLong(offsets[133], object.updatedAt); + writer.writeBool(offsets[134], object.useLibass); + writer.writeBool(offsets[135], object.useMpvConfig); + writer.writeBool(offsets[136], object.usePageTapZones); + writer.writeBool(offsets[137], object.useYUV420P); + writer.writeString(offsets[138], object.userAgent); + writer.writeLong(offsets[139], object.volumeBoostCap); } Settings _settingsDeserialize( @@ -1701,97 +1695,96 @@ Settings _settingsDeserialize( markEpisodeAsSeenType: reader.readLongOrNull(offsets[92]), mergeLibraryNavMobile: reader.readBoolOrNull(offsets[93]), navigationOrder: reader.readStringList(offsets[94]), - novelAutoScroll: reader.readBoolOrNull(offsets[95]), novelDisplayType: _SettingsnovelDisplayTypeValueEnumMap[reader.readByteOrNull( - offsets[96], + offsets[95], )] ?? DisplayType.comfortableGrid, novelExtensionsRepo: reader.readObjectList( - offsets[97], + offsets[96], RepoSchema.deserialize, allOffsets, Repo(), ), - novelFontSize: reader.readLongOrNull(offsets[98]), - novelLibraryDownloadedChapters: reader.readBoolOrNull(offsets[100]), - novelLibraryLocalSource: reader.readBoolOrNull(offsets[101]), - novelLibraryShowCategoryTabs: reader.readBoolOrNull(offsets[102]), - novelLibraryShowContinueReadingButton: reader.readBoolOrNull(offsets[103]), - novelLibraryShowLanguage: reader.readBoolOrNull(offsets[104]), - novelLibraryShowNumbersOfItems: reader.readBoolOrNull(offsets[105]), - novelReaderLineHeight: reader.readDoubleOrNull(offsets[106]), - novelReaderPadding: reader.readLongOrNull(offsets[107]), - novelReaderTextColor: reader.readStringOrNull(offsets[108]), - novelReaderTheme: reader.readStringOrNull(offsets[109]), - novelRemoveExtraParagraphSpacing: reader.readBoolOrNull(offsets[110]), - novelShowScrollPercentage: reader.readBoolOrNull(offsets[111]), - novelTapToScroll: reader.readBoolOrNull(offsets[112]), + novelFontSize: reader.readLongOrNull(offsets[97]), + novelLibraryDownloadedChapters: reader.readBoolOrNull(offsets[99]), + novelLibraryLocalSource: reader.readBoolOrNull(offsets[100]), + novelLibraryShowCategoryTabs: reader.readBoolOrNull(offsets[101]), + novelLibraryShowContinueReadingButton: reader.readBoolOrNull(offsets[102]), + novelLibraryShowLanguage: reader.readBoolOrNull(offsets[103]), + novelLibraryShowNumbersOfItems: reader.readBoolOrNull(offsets[104]), + novelReaderLineHeight: reader.readDoubleOrNull(offsets[105]), + novelReaderPadding: reader.readLongOrNull(offsets[106]), + novelReaderTextColor: reader.readStringOrNull(offsets[107]), + novelReaderTheme: reader.readStringOrNull(offsets[108]), + novelRemoveExtraParagraphSpacing: reader.readBoolOrNull(offsets[109]), + novelShowScrollPercentage: reader.readBoolOrNull(offsets[110]), + novelTapToScroll: reader.readBoolOrNull(offsets[111]), novelTextAlign: _SettingsnovelTextAlignValueEnumMap[reader.readByteOrNull( - offsets[113], + offsets[112], )] ?? NovelTextAlign.left, - onlyIncludePinnedSources: reader.readBoolOrNull(offsets[114]), - pagePreloadAmount: reader.readLongOrNull(offsets[115]), + onlyIncludePinnedSources: reader.readBoolOrNull(offsets[113]), + pagePreloadAmount: reader.readLongOrNull(offsets[114]), personalPageModeList: reader.readObjectList( - offsets[116], + offsets[115], PersonalPageModeSchema.deserialize, allOffsets, PersonalPageMode(), ), personalReaderModeList: reader.readObjectList( - offsets[117], + offsets[116], PersonalReaderModeSchema.deserialize, allOffsets, PersonalReaderMode(), ), playerSubtitleSettings: reader.readObjectOrNull( - offsets[118], + offsets[117], PlayerSubtitleSettingsSchema.deserialize, allOffsets, ), - pureBlackDarkMode: reader.readBoolOrNull(offsets[119]), - relativeTimesTamps: reader.readLongOrNull(offsets[120]), - rpcShowCoverImage: reader.readBoolOrNull(offsets[121]), - rpcShowReadingWatchingProgress: reader.readBoolOrNull(offsets[122]), - rpcShowTitle: reader.readBoolOrNull(offsets[123]), - saveAsCBZArchive: reader.readBoolOrNull(offsets[124]), + pureBlackDarkMode: reader.readBoolOrNull(offsets[118]), + relativeTimesTamps: reader.readLongOrNull(offsets[119]), + rpcShowCoverImage: reader.readBoolOrNull(offsets[120]), + rpcShowReadingWatchingProgress: reader.readBoolOrNull(offsets[121]), + rpcShowTitle: reader.readBoolOrNull(offsets[122]), + saveAsCBZArchive: reader.readBoolOrNull(offsets[123]), scaleType: - _SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offsets[125])] ?? + _SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offsets[124])] ?? ScaleType.fitScreen, - showPagesNumber: reader.readBoolOrNull(offsets[126]), + showPagesNumber: reader.readBoolOrNull(offsets[125]), sortChapterList: reader.readObjectList( - offsets[127], + offsets[126], SortChapterSchema.deserialize, allOffsets, SortChapter(), ), sortLibraryAnime: reader.readObjectOrNull( - offsets[128], + offsets[127], SortLibraryMangaSchema.deserialize, allOffsets, ), sortLibraryManga: reader.readObjectOrNull( - offsets[129], + offsets[128], SortLibraryMangaSchema.deserialize, allOffsets, ), sortLibraryNovel: reader.readObjectOrNull( - offsets[130], + offsets[129], SortLibraryMangaSchema.deserialize, allOffsets, ), - startDatebackup: reader.readLongOrNull(offsets[131]), - themeIsDark: reader.readBoolOrNull(offsets[132]), - updateProgressAfterReading: reader.readBoolOrNull(offsets[133]), - updatedAt: reader.readLongOrNull(offsets[134]), - useLibass: reader.readBoolOrNull(offsets[135]), - useMpvConfig: reader.readBoolOrNull(offsets[136]), - usePageTapZones: reader.readBoolOrNull(offsets[137]), - useYUV420P: reader.readBoolOrNull(offsets[138]), - userAgent: reader.readStringOrNull(offsets[139]), - volumeBoostCap: reader.readLongOrNull(offsets[140]), + startDatebackup: reader.readLongOrNull(offsets[130]), + themeIsDark: reader.readBoolOrNull(offsets[131]), + updateProgressAfterReading: reader.readBoolOrNull(offsets[132]), + updatedAt: reader.readLongOrNull(offsets[133]), + useLibass: reader.readBoolOrNull(offsets[134]), + useMpvConfig: reader.readBoolOrNull(offsets[135]), + usePageTapZones: reader.readBoolOrNull(offsets[136]), + useYUV420P: reader.readBoolOrNull(offsets[137]), + userAgent: reader.readStringOrNull(offsets[138]), + volumeBoostCap: reader.readLongOrNull(offsets[139]), ); object.chapterFilterBookmarkedList = reader .readObjectList( @@ -1822,7 +1815,7 @@ Settings _settingsDeserialize( L10nLocaleSchema.deserialize, allOffsets, ); - object.novelGridSize = reader.readLongOrNull(offsets[99]); + object.novelGridSize = reader.readLongOrNull(offsets[98]); return object; } @@ -2138,14 +2131,12 @@ P _settingsDeserializeProp

( case 94: return (reader.readStringList(offset)) as P; case 95: - return (reader.readBoolOrNull(offset)) as P; - case 96: return (_SettingsnovelDisplayTypeValueEnumMap[reader.readByteOrNull( offset, )] ?? DisplayType.comfortableGrid) as P; - case 97: + case 96: return (reader.readObjectList( offset, RepoSchema.deserialize, @@ -2153,10 +2144,12 @@ P _settingsDeserializeProp

( Repo(), )) as P; + case 97: + return (reader.readLongOrNull(offset)) as P; case 98: return (reader.readLongOrNull(offset)) as P; case 99: - return (reader.readLongOrNull(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 100: return (reader.readBoolOrNull(offset)) as P; case 101: @@ -2168,32 +2161,30 @@ P _settingsDeserializeProp

( case 104: return (reader.readBoolOrNull(offset)) as P; case 105: - return (reader.readBoolOrNull(offset)) as P; - case 106: return (reader.readDoubleOrNull(offset)) as P; - case 107: + case 106: return (reader.readLongOrNull(offset)) as P; + case 107: + return (reader.readStringOrNull(offset)) as P; case 108: return (reader.readStringOrNull(offset)) as P; case 109: - return (reader.readStringOrNull(offset)) as P; + return (reader.readBoolOrNull(offset)) as P; case 110: return (reader.readBoolOrNull(offset)) as P; case 111: return (reader.readBoolOrNull(offset)) as P; case 112: - return (reader.readBoolOrNull(offset)) as P; - case 113: return (_SettingsnovelTextAlignValueEnumMap[reader.readByteOrNull( offset, )] ?? NovelTextAlign.left) as P; - case 114: + case 113: return (reader.readBoolOrNull(offset)) as P; - case 115: + case 114: return (reader.readLongOrNull(offset)) as P; - case 116: + case 115: return (reader.readObjectList( offset, PersonalPageModeSchema.deserialize, @@ -2201,7 +2192,7 @@ P _settingsDeserializeProp

( PersonalPageMode(), )) as P; - case 117: + case 116: return (reader.readObjectList( offset, PersonalReaderModeSchema.deserialize, @@ -2209,17 +2200,19 @@ P _settingsDeserializeProp

( PersonalReaderMode(), )) as P; - case 118: + case 117: return (reader.readObjectOrNull( offset, PlayerSubtitleSettingsSchema.deserialize, allOffsets, )) as P; - case 119: + case 118: return (reader.readBoolOrNull(offset)) as P; - case 120: + case 119: return (reader.readLongOrNull(offset)) as P; + case 120: + return (reader.readBoolOrNull(offset)) as P; case 121: return (reader.readBoolOrNull(offset)) as P; case 122: @@ -2227,14 +2220,12 @@ P _settingsDeserializeProp

( case 123: return (reader.readBoolOrNull(offset)) as P; case 124: - return (reader.readBoolOrNull(offset)) as P; - case 125: return (_SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offset)] ?? ScaleType.fitScreen) as P; - case 126: + case 125: return (reader.readBoolOrNull(offset)) as P; - case 127: + case 126: return (reader.readObjectList( offset, SortChapterSchema.deserialize, @@ -2242,6 +2233,13 @@ P _settingsDeserializeProp

( SortChapter(), )) as P; + case 127: + return (reader.readObjectOrNull( + offset, + SortLibraryMangaSchema.deserialize, + allOffsets, + )) + as P; case 128: return (reader.readObjectOrNull( offset, @@ -2257,20 +2255,15 @@ P _settingsDeserializeProp

( )) as P; case 130: - return (reader.readObjectOrNull( - offset, - SortLibraryMangaSchema.deserialize, - allOffsets, - )) - as P; - case 131: return (reader.readLongOrNull(offset)) as P; + case 131: + return (reader.readBoolOrNull(offset)) as P; case 132: return (reader.readBoolOrNull(offset)) as P; case 133: - return (reader.readBoolOrNull(offset)) as P; - case 134: return (reader.readLongOrNull(offset)) as P; + case 134: + return (reader.readBoolOrNull(offset)) as P; case 135: return (reader.readBoolOrNull(offset)) as P; case 136: @@ -2278,10 +2271,8 @@ P _settingsDeserializeProp

( case 137: return (reader.readBoolOrNull(offset)) as P; case 138: - return (reader.readBoolOrNull(offset)) as P; - case 139: return (reader.readStringOrNull(offset)) as P; - case 140: + case 139: return (reader.readLongOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); @@ -9451,33 +9442,6 @@ extension SettingsQueryFilter }); } - QueryBuilder - novelAutoScrollIsNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition( - const FilterCondition.isNull(property: r'novelAutoScroll'), - ); - }); - } - - QueryBuilder - novelAutoScrollIsNotNull() { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition( - const FilterCondition.isNotNull(property: r'novelAutoScroll'), - ); - }); - } - - QueryBuilder - novelAutoScrollEqualTo(bool? value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition( - FilterCondition.equalTo(property: r'novelAutoScroll', value: value), - ); - }); - } - QueryBuilder novelDisplayTypeEqualTo(DisplayType value) { return QueryBuilder.apply(this, (query) { @@ -13131,18 +13095,6 @@ extension SettingsQuerySortBy on QueryBuilder { }); } - QueryBuilder sortByNovelAutoScroll() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'novelAutoScroll', Sort.asc); - }); - } - - QueryBuilder sortByNovelAutoScrollDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'novelAutoScroll', Sort.desc); - }); - } - QueryBuilder sortByNovelDisplayType() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'novelDisplayType', Sort.asc); @@ -14651,18 +14603,6 @@ extension SettingsQuerySortThenBy }); } - QueryBuilder thenByNovelAutoScroll() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'novelAutoScroll', Sort.asc); - }); - } - - QueryBuilder thenByNovelAutoScrollDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'novelAutoScroll', Sort.desc); - }); - } - QueryBuilder thenByNovelDisplayType() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'novelDisplayType', Sort.asc); @@ -15703,12 +15643,6 @@ extension SettingsQueryWhereDistinct }); } - QueryBuilder distinctByNovelAutoScroll() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'novelAutoScroll'); - }); - } - QueryBuilder distinctByNovelDisplayType() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'novelDisplayType'); @@ -16602,12 +16536,6 @@ extension SettingsQueryProperty }); } - QueryBuilder novelAutoScrollProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'novelAutoScroll'); - }); - } - QueryBuilder novelDisplayTypeProperty() { return QueryBuilder.apply(this, (query) { diff --git a/lib/modules/more/settings/reader/providers/reader_state_provider.dart b/lib/modules/more/settings/reader/providers/reader_state_provider.dart index 32fcf84c..1f931b53 100644 --- a/lib/modules/more/settings/reader/providers/reader_state_provider.dart +++ b/lib/modules/more/settings/reader/providers/reader_state_provider.dart @@ -403,26 +403,6 @@ class NovelShowScrollPercentageState extends _$NovelShowScrollPercentageState { } } -@riverpod -class NovelAutoScrollState extends _$NovelAutoScrollState { - @override - bool build() { - return isar.settings.getSync(227)!.novelAutoScroll ?? false; - } - - void set(bool value) { - final settings = isar.settings.getSync(227); - state = value; - isar.writeTxnSync( - () => isar.settings.putSync( - settings! - ..novelAutoScroll = value - ..updatedAt = DateTime.now().millisecondsSinceEpoch, - ), - ); - } -} - @riverpod class NovelRemoveExtraParagraphSpacingState extends _$NovelRemoveExtraParagraphSpacingState { diff --git a/lib/modules/more/settings/reader/providers/reader_state_provider.g.dart b/lib/modules/more/settings/reader/providers/reader_state_provider.g.dart index 38fe44d5..ef777662 100644 --- a/lib/modules/more/settings/reader/providers/reader_state_provider.g.dart +++ b/lib/modules/more/settings/reader/providers/reader_state_provider.g.dart @@ -1037,60 +1037,6 @@ abstract class _$NovelShowScrollPercentageState extends $Notifier { } } -@ProviderFor(NovelAutoScrollState) -const novelAutoScrollStateProvider = NovelAutoScrollStateProvider._(); - -final class NovelAutoScrollStateProvider - extends $NotifierProvider { - const NovelAutoScrollStateProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'novelAutoScrollStateProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$novelAutoScrollStateHash(); - - @$internal - @override - NovelAutoScrollState create() => NovelAutoScrollState(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(bool value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } -} - -String _$novelAutoScrollStateHash() => - r'80f717515844fa97396dffc6f45ee0b7b9e6f96d'; - -abstract class _$NovelAutoScrollState extends $Notifier { - bool build(); - @$mustCallSuper - @override - void runBuild() { - final created = build(); - final ref = this.ref as $Ref; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, - bool, - Object?, - Object? - >; - element.handleValue(ref, created); - } -} - @ProviderFor(NovelRemoveExtraParagraphSpacingState) const novelRemoveExtraParagraphSpacingStateProvider = NovelRemoveExtraParagraphSpacingStateProvider._(); diff --git a/lib/modules/novel/novel_reader_controller_provider.dart b/lib/modules/novel/novel_reader_controller_provider.dart index 4e4fc13e..e93cca8d 100644 --- a/lib/modules/novel/novel_reader_controller_provider.dart +++ b/lib/modules/novel/novel_reader_controller_provider.dart @@ -27,6 +27,42 @@ class NovelReaderController extends _$NovelReaderController { return isar.settings.getSync(227)!; } + (bool, double) autoScrollValues() { + final autoScrollPagesList = getIsarSetting().autoScrollPages ?? []; + final autoScrollPages = autoScrollPagesList.where( + (element) => element.mangaId == getManga().id, + ); + if (autoScrollPages.isNotEmpty) { + return ( + autoScrollPages.first.autoScroll ?? false, + autoScrollPages.first.pageOffset ?? 10, + ); + } + return (false, 10); + } + + void setAutoScroll(bool value, double offset) { + List? autoScrollPagesList = []; + for (var autoScrollPages in getIsarSetting().autoScrollPages ?? []) { + if (autoScrollPages.mangaId != getManga().id) { + autoScrollPagesList.add(autoScrollPages); + } + } + autoScrollPagesList.add( + AutoScrollPages() + ..mangaId = getManga().id + ..pageOffset = offset + ..autoScroll = value, + ); + isar.writeTxnSync( + () => isar.settings.putSync( + getIsarSetting() + ..autoScrollPages = autoScrollPagesList + ..updatedAt = DateTime.now().millisecondsSinceEpoch, + ), + ); + } + void setMangaHistoryUpdate() { if (incognitoMode) return; isar.writeTxnSync(() { diff --git a/lib/modules/novel/novel_reader_controller_provider.g.dart b/lib/modules/novel/novel_reader_controller_provider.g.dart index f152961c..7a8d0ff3 100644 --- a/lib/modules/novel/novel_reader_controller_provider.g.dart +++ b/lib/modules/novel/novel_reader_controller_provider.g.dart @@ -59,7 +59,7 @@ final class NovelReaderControllerProvider } String _$novelReaderControllerHash() => - r'47354aa64609d94a875d58569b5c95257b736b76'; + r'6ed6441112a356af8530219a6017e640fda388f2'; final class NovelReaderControllerFamily extends $Family with diff --git a/lib/modules/novel/novel_reader_view.dart b/lib/modules/novel/novel_reader_view.dart index ab419f8a..cbe713f9 100644 --- a/lib/modules/novel/novel_reader_view.dart +++ b/lib/modules/novel/novel_reader_view.dart @@ -136,6 +136,36 @@ class _NovelWebViewState extends ConsumerState ref.read(fullScreenReaderStateProvider.notifier).set(!value!); } + late final _autoScroll = ValueNotifier( + _readerController.autoScrollValues().$1, + ); + late final _pageOffset = ValueNotifier( + _readerController.autoScrollValues().$2, + ); + late final _autoScrollPage = ValueNotifier(_autoScroll.value); + void _autoPagescroll() async { + for (int i = 0; i < 1; i++) { + await Future.delayed(const Duration(milliseconds: 100)); + if (!_autoScroll.value) { + return; + } + if (_scrollController.hasClients) { + final currentOffset = _scrollController.offset; + final maxScroll = _scrollController.position.maxScrollExtent; + + if (!(currentOffset >= maxScroll)) { + final newOffset = currentOffset + _pageOffset.value; + _scrollController.animateTo( + min(newOffset, maxScroll), + duration: Duration(milliseconds: 100), + curve: Curves.linear, + ); + } + } + } + _autoPagescroll(); + } + @override Widget build(BuildContext context) { final backgroundColor = ref.watch(backgroundColorStateProvider); @@ -204,260 +234,282 @@ class _NovelWebViewState extends ConsumerState child: SafeArea( top: !fullScreenReader, bottom: false, - child: Stack( - children: [ - Column( + child: widget.result.when( + data: (data) { + return Stack( children: [ - Flexible( - child: widget.result.when( - data: (data) { - epubBook = data.$2; + Column( + children: [ + Flexible( + child: Builder( + builder: (context) { + epubBook = data.$2; - final padding = ref.watch( - novelReaderPaddingStateProvider, - ); - final lineHeight = ref.watch( - novelReaderLineHeightStateProvider, - ); - final textAlign = ref.watch( - novelTextAlignStateProvider, - ); - final removeExtraSpacing = ref.watch( - novelRemoveExtraParagraphSpacingStateProvider, - ); - final customBackgroundColor = ref.watch( - novelReaderThemeStateProvider, - ); - final customTextColor = ref.watch( - novelReaderTextColorStateProvider, - ); - - Color parseColor(String hex) { - final hexColor = hex.replaceAll('#', ''); - return Color(int.parse('FF$hexColor', radix: 16)); - } - - TextAlign getTextAlign() { - switch (textAlign) { - case NovelTextAlign.left: - return TextAlign.left; - case NovelTextAlign.center: - return TextAlign.center; - case NovelTextAlign.right: - return TextAlign.right; - case NovelTextAlign.block: - return TextAlign.justify; - } - } - - Future.delayed(const Duration(milliseconds: 10), () { - if (!scrolled && _scrollController.hasClients) { - _scrollController.animateTo( - _scrollController.position.maxScrollExtent * - (double.tryParse(chapter.lastPageRead!) ?? - 0), - duration: Duration(seconds: 2), - curve: Curves.fastOutSlowIn, + final padding = ref.watch( + novelReaderPaddingStateProvider, ); - scrolled = true; - } - }); - return Consumer( - builder: (context, ref, _) { - final fontSize = ref.read( - novelFontSizeStateProvider, + final lineHeight = ref.watch( + novelReaderLineHeightStateProvider, ); - return Scrollbar( - controller: _scrollController, - interactive: true, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - _isViewFunction(); - }, - child: CustomScrollView( - controller: _scrollController, - physics: const BouncingScrollPhysics(), - slivers: [ - SliverToBoxAdapter( - child: Html( - data: data.$1, - style: { - "body": Style( - fontSize: FontSize( - fontSize.toDouble(), - ), - color: parseColor( - customTextColor, - ), - backgroundColor: parseColor( - customBackgroundColor, - ), - margin: Margins.zero, - padding: HtmlPaddings.all( - padding.toDouble(), - ), - lineHeight: LineHeight( - lineHeight, - ), - textAlign: getTextAlign(), - ), - "p": Style( - margin: removeExtraSpacing - ? Margins.only(bottom: 4) - : Margins.only(bottom: 8), - fontSize: FontSize( - fontSize.toDouble(), - ), - lineHeight: LineHeight( - lineHeight, - ), - textAlign: getTextAlign(), - ), - "div": Style( - fontSize: FontSize( - fontSize.toDouble(), - ), - lineHeight: LineHeight( - lineHeight, - ), - textAlign: getTextAlign(), - ), - "span": Style( - fontSize: FontSize( - fontSize.toDouble(), - ), - lineHeight: LineHeight( - lineHeight, - ), - ), - "h1, h2, h3, h4, h5, h6": Style( - color: parseColor( - customTextColor, - ), - lineHeight: LineHeight( - lineHeight, - ), - textAlign: getTextAlign(), - ), - "a": Style( - color: Colors.blue, - textDecoration: - TextDecoration.underline, - ), - "img": Style( - width: Width(100, Unit.percent), - height: Height.auto(), - ), - }, - extensions: [ - TagExtension( - tagsToExtend: {"img"}, - builder: (extensionContext) { - final element = - extensionContext.node - as dom.Element; - final customWidget = - _buildCustomWidgets( - element, - ); - if (customWidget != null) { - return customWidget; - } - - return const SizedBox.shrink(); - }, - ), - ], - onLinkTap: - (url, attributes, element) { - if (url != null) { - context.push( - "/mangawebview", - extra: { - 'url': url, - 'title': url, - }, - ); - } - }, - ), - ), - ], - ), - ), + final textAlign = ref.watch( + novelTextAlignStateProvider, + ); + final removeExtraSpacing = ref.watch( + novelRemoveExtraParagraphSpacingStateProvider, ); - }, - ); - }, - loading: () => scaffoldWith( - context, - Center(child: CircularProgressIndicator()), - ), - error: (err, stack) => scaffoldWith( - context, - Center(child: Text(err.toString())), - ), - ), - ), - if (ref.watch(novelShowScrollPercentageStateProvider)) - StreamBuilder( - stream: _rebuildDetail.stream, - builder: (context, asyncSnapshot) { - return Consumer( - builder: (context, ref, child) { final customBackgroundColor = ref.watch( novelReaderThemeStateProvider, ); final customTextColor = ref.watch( novelReaderTextColorStateProvider, ); - final scrollPercentage = maxOffset > 0 - ? ((offset / maxOffset) * 100) - .clamp(0, 100) - .toInt() - : 0; - return Row( - children: [ - Expanded( - child: Container( - color: Color( - int.parse( - 'FF${customBackgroundColor.replaceAll('#', '')}', - radix: 16, - ), + + Color parseColor(String hex) { + final hexColor = hex.replaceAll('#', ''); + return Color( + int.parse('FF$hexColor', radix: 16), + ); + } + + TextAlign getTextAlign() { + switch (textAlign) { + case NovelTextAlign.left: + return TextAlign.left; + case NovelTextAlign.center: + return TextAlign.center; + case NovelTextAlign.right: + return TextAlign.right; + case NovelTextAlign.block: + return TextAlign.justify; + } + } + + Future.delayed( + const Duration(milliseconds: 10), + () { + if (!scrolled && + _scrollController.hasClients) { + _scrollController + .animateTo( + _scrollController + .position + .maxScrollExtent * + (double.tryParse( + chapter.lastPageRead!, + ) ?? + 0), + duration: Duration(seconds: 2), + curve: Curves.fastOutSlowIn, + ) + .then((value) { + _autoPagescroll(); + scrolled = true; + }); + } + }, + ); + return Consumer( + builder: (context, ref, _) { + final fontSize = ref.read( + novelFontSizeStateProvider, + ); + return Scrollbar( + controller: _scrollController, + interactive: true, + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + _isViewFunction(); + }, + child: CustomScrollView( + controller: _scrollController, + physics: const BouncingScrollPhysics(), + slivers: [ + SliverToBoxAdapter( + child: Html( + data: data.$1, + style: { + "body": Style( + fontSize: FontSize( + fontSize.toDouble(), + ), + color: parseColor( + customTextColor, + ), + backgroundColor: parseColor( + customBackgroundColor, + ), + margin: Margins.zero, + padding: HtmlPaddings.all( + padding.toDouble(), + ), + lineHeight: LineHeight( + lineHeight, + ), + textAlign: getTextAlign(), + ), + "p": Style( + margin: removeExtraSpacing + ? Margins.only(bottom: 4) + : Margins.only(bottom: 8), + fontSize: FontSize( + fontSize.toDouble(), + ), + lineHeight: LineHeight( + lineHeight, + ), + textAlign: getTextAlign(), + ), + "div": Style( + fontSize: FontSize( + fontSize.toDouble(), + ), + lineHeight: LineHeight( + lineHeight, + ), + textAlign: getTextAlign(), + ), + "span": Style( + fontSize: FontSize( + fontSize.toDouble(), + ), + lineHeight: LineHeight( + lineHeight, + ), + ), + "h1, h2, h3, h4, h5, h6": Style( + color: parseColor( + customTextColor, + ), + lineHeight: LineHeight( + lineHeight, + ), + textAlign: getTextAlign(), + ), + "a": Style( + color: Colors.blue, + textDecoration: + TextDecoration.underline, + ), + "img": Style( + width: Width( + 100, + Unit.percent, + ), + height: Height.auto(), + ), + }, + extensions: [ + TagExtension( + tagsToExtend: {"img"}, + builder: (extensionContext) { + final element = + extensionContext.node + as dom.Element; + final customWidget = + _buildCustomWidgets( + element, + ); + if (customWidget != null) { + return customWidget; + } + + return const SizedBox.shrink(); + }, + ), + ], + onLinkTap: + (url, attributes, element) { + if (url != null) { + context.push( + "/mangawebview", + extra: { + 'url': url, + 'title': url, + }, + ); + } + }, + ), + ), + ], ), - child: Center( - child: Padding( - padding: const EdgeInsets.all(4.0), - child: Text( - '$scrollPercentage %', - style: TextStyle( - color: Color( - int.parse( - 'FF${customTextColor.replaceAll('#', '')}', - radix: 16, + ), + ); + }, + ); + }, + ), + ), + if (ref.watch(novelShowScrollPercentageStateProvider)) + StreamBuilder( + stream: _rebuildDetail.stream, + builder: (context, asyncSnapshot) { + return Consumer( + builder: (context, ref, child) { + final customBackgroundColor = ref.watch( + novelReaderThemeStateProvider, + ); + final customTextColor = ref.watch( + novelReaderTextColorStateProvider, + ); + final scrollPercentage = maxOffset > 0 + ? ((offset / maxOffset) * 100) + .clamp(0, 100) + .toInt() + : 0; + return Row( + children: [ + Expanded( + child: Container( + color: Color( + int.parse( + 'FF${customBackgroundColor.replaceAll('#', '')}', + radix: 16, + ), + ), + child: Center( + child: Padding( + padding: const EdgeInsets.all( + 4.0, + ), + child: Text( + '$scrollPercentage %', + style: TextStyle( + color: Color( + int.parse( + 'FF${customTextColor.replaceAll('#', '')}', + radix: 16, + ), + ), + fontSize: 14, + fontWeight: FontWeight.bold, ), ), - fontSize: 14, - fontWeight: FontWeight.bold, ), ), ), ), - ), - ), - ], + ], + ); + }, ); }, - ); - }, - ), + ), + ], + ), + _appBar(), + _bottomBar(backgroundColor), + _autoScrollPlayPauseBtn(), ], - ), - _appBar(), - _bottomBar(backgroundColor), - ], + ); + }, + loading: () => scaffoldWith( + context, + Center(child: CircularProgressIndicator()), + ), + error: (err, stack) => + scaffoldWith(context, Center(child: Text(err.toString()))), ), ), ), @@ -465,6 +517,32 @@ class _NovelWebViewState extends ConsumerState ); } + Widget _autoScrollPlayPauseBtn() { + return Positioned( + bottom: 0, + right: 0, + child: !_isView + ? ValueListenableBuilder( + valueListenable: _autoScrollPage, + builder: (context, valueT, child) => valueT + ? ValueListenableBuilder( + valueListenable: _autoScroll, + builder: (context, value, child) => IconButton( + onPressed: () { + _autoPagescroll(); + _autoScroll.value = !value; + }, + icon: Icon( + value ? Icons.pause_circle : Icons.play_circle, + ), + ), + ) + : const SizedBox.shrink(), + ) + : const SizedBox.shrink(), + ); + } + Widget scaffoldWith( BuildContext context, Widget body, { @@ -892,19 +970,29 @@ class _NovelWebViewState extends ConsumerState ), IconButton( - onPressed: () { - customDraggableTabBar( + onPressed: () async { + _autoScroll.value = false; + await customDraggableTabBar( tabs: [ Tab(text: context.l10n.reader), Tab(text: context.l10n.general), ], children: [ ReaderSettingsTab(), - GeneralSettingsTab(), + GeneralSettingsTab( + autoScrollPage: _autoScrollPage, + autoScroll: _autoScroll, + readerController: _readerController, + pageOffset: _pageOffset, + ), ], context: context, vsync: this, ); + if (_autoScrollPage.value) { + _autoPagescroll(); + _autoScroll.value = true; + } }, icon: const Icon(Icons.settings), ), diff --git a/lib/modules/novel/widgets/novel_reader_settings_sheet.dart b/lib/modules/novel/widgets/novel_reader_settings_sheet.dart index 9bccae4c..9f861102 100644 --- a/lib/modules/novel/widgets/novel_reader_settings_sheet.dart +++ b/lib/modules/novel/widgets/novel_reader_settings_sheet.dart @@ -1,7 +1,10 @@ +import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mangayomi/models/settings.dart'; import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart'; +import 'package:mangayomi/modules/novel/novel_reader_controller_provider.dart'; +import 'package:mangayomi/providers/l10n_providers.dart'; class ReaderSettingsTab extends ConsumerWidget { const ReaderSettingsTab({super.key}); @@ -227,7 +230,17 @@ class ReaderSettingsTab extends ConsumerWidget { } class GeneralSettingsTab extends ConsumerWidget { - const GeneralSettingsTab({super.key}); + final ValueNotifier autoScrollPage; + final ValueNotifier autoScroll; + final NovelReaderController readerController; + final ValueNotifier pageOffset; + const GeneralSettingsTab({ + required this.autoScrollPage, + required this.autoScroll, + required this.readerController, + required this.pageOffset, + super.key, + }); @override Widget build(BuildContext context, WidgetRef ref) { @@ -237,7 +250,6 @@ class GeneralSettingsTab extends ConsumerWidget { children: [ _SwitchListTileSetting( title: 'Show Scroll Percentage', - subtitle: 'Display reading progress percentage', value: ref.watch(novelShowScrollPercentageStateProvider), onChanged: (value) { ref @@ -245,18 +257,45 @@ class GeneralSettingsTab extends ConsumerWidget { .set(value); }, ), - - // _SwitchListTileSetting( - // title: 'Auto Scroll', - // subtitle: 'Automatically scroll through pages', - // value: ref.watch(novelAutoScrollStateProvider), - // onChanged: (value) { - // ref.read(novelAutoScrollStateProvider.notifier).set(value); - // }, - // ), + ValueListenableBuilder( + valueListenable: autoScrollPage, + builder: (context, valueT, child) { + return Column( + children: [ + _SwitchListTileSetting( + secondary: Icon( + valueT ? Icons.timer : Icons.timer_outlined, + ), + value: valueT, + title: context.l10n.auto_scroll, + onChanged: (val) { + readerController.setAutoScroll(val, pageOffset.value); + autoScrollPage.value = val; + autoScroll.value = val; + }, + ), + if (valueT) + ValueListenableBuilder( + valueListenable: pageOffset, + builder: (context, value, child) => Slider( + min: 2.0, + max: 30.0, + divisions: max(28, 3), + value: value, + onChanged: (val) { + pageOffset.value = val; + }, + onChangeEnd: (val) { + readerController.setAutoScroll(valueT, val); + }, + ), + ), + ], + ); + }, + ), _SwitchListTileSetting( title: 'Remove Extra Paragraph Spacing', - subtitle: 'Reduce spacing between paragraphs', value: ref.watch(novelRemoveExtraParagraphSpacingStateProvider), onChanged: (value) { ref @@ -311,22 +350,31 @@ class _SettingSection extends StatelessWidget { class _SwitchListTileSetting extends StatelessWidget { final String title; - final String subtitle; final bool value; + final Widget? secondary; final ValueChanged onChanged; const _SwitchListTileSetting({ required this.title, - required this.subtitle, required this.value, required this.onChanged, + this.secondary, }); @override Widget build(BuildContext context) { return SwitchListTile( - title: Text(title), - subtitle: Text(subtitle, style: Theme.of(context).textTheme.bodySmall), + secondary: secondary, + title: Text( + title, + style: TextStyle( + color: Theme.of( + context, + ).textTheme.bodyLarge!.color!.withValues(alpha: 0.9), + fontSize: 14, + ), + ), + value: value, onChanged: onChanged, ); diff --git a/lib/services/get_html_content.g.dart b/lib/services/get_html_content.g.dart index 4eeb6664..664e72d7 100644 --- a/lib/services/get_html_content.g.dart +++ b/lib/services/get_html_content.g.dart @@ -66,7 +66,7 @@ final class GetHtmlContentProvider } } -String _$getHtmlContentHash() => r'a5763e11960bfe0dbd38ce2b2a3f4b51fefc976e'; +String _$getHtmlContentHash() => r'f1f734a95f8dfcd7197712eee61609589d76de1f'; final class GetHtmlContentFamily extends $Family with $FunctionalFamilyOverride, Chapter> {