feature: crop borders (experimental)
This commit is contained in:
parent
c4346d8a06
commit
380310be55
14 changed files with 633 additions and 245 deletions
|
|
@ -83,6 +83,8 @@ class Settings {
|
|||
|
||||
List<FilterScanlator>? filterScanlatorList;
|
||||
|
||||
bool? cropBorders;
|
||||
|
||||
Settings(
|
||||
{this.id = 227,
|
||||
this.displayType = DisplayType.compactGrid,
|
||||
|
|
@ -118,7 +120,8 @@ class Settings {
|
|||
this.pureBlackDarkMode = false,
|
||||
this.downloadOnlyOnWifi = false,
|
||||
this.saveAsCBZArchive = false,
|
||||
this.downloadLocation = ""});
|
||||
this.downloadLocation = "",
|
||||
this.cropBorders = false});
|
||||
}
|
||||
|
||||
enum DisplayType {
|
||||
|
|
|
|||
|
|
@ -58,159 +58,164 @@ const SettingsSchema = CollectionSchema(
|
|||
type: IsarType.objectList,
|
||||
target: r'Cookie',
|
||||
),
|
||||
r'dateFormat': PropertySchema(
|
||||
r'cropBorders': PropertySchema(
|
||||
id: 7,
|
||||
name: r'cropBorders',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'dateFormat': PropertySchema(
|
||||
id: 8,
|
||||
name: r'dateFormat',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'defaultReaderMode': PropertySchema(
|
||||
id: 8,
|
||||
id: 9,
|
||||
name: r'defaultReaderMode',
|
||||
type: IsarType.byte,
|
||||
enumMap: _SettingsdefaultReaderModeEnumValueMap,
|
||||
),
|
||||
r'displayType': PropertySchema(
|
||||
id: 9,
|
||||
id: 10,
|
||||
name: r'displayType',
|
||||
type: IsarType.byte,
|
||||
enumMap: _SettingsdisplayTypeEnumValueMap,
|
||||
),
|
||||
r'doubleTapAnimationSpeed': PropertySchema(
|
||||
id: 10,
|
||||
id: 11,
|
||||
name: r'doubleTapAnimationSpeed',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'downloadLocation': PropertySchema(
|
||||
id: 11,
|
||||
id: 12,
|
||||
name: r'downloadLocation',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'downloadOnlyOnWifi': PropertySchema(
|
||||
id: 12,
|
||||
id: 13,
|
||||
name: r'downloadOnlyOnWifi',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'filterScanlatorList': PropertySchema(
|
||||
id: 13,
|
||||
id: 14,
|
||||
name: r'filterScanlatorList',
|
||||
type: IsarType.objectList,
|
||||
target: r'FilterScanlator',
|
||||
),
|
||||
r'flexColorSchemeBlendLevel': PropertySchema(
|
||||
id: 14,
|
||||
id: 15,
|
||||
name: r'flexColorSchemeBlendLevel',
|
||||
type: IsarType.double,
|
||||
),
|
||||
r'flexSchemeColorIndex': PropertySchema(
|
||||
id: 15,
|
||||
id: 16,
|
||||
name: r'flexSchemeColorIndex',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'incognitoMode': PropertySchema(
|
||||
id: 16,
|
||||
id: 17,
|
||||
name: r'incognitoMode',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'libraryDownloadedChapters': PropertySchema(
|
||||
id: 17,
|
||||
id: 18,
|
||||
name: r'libraryDownloadedChapters',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'libraryFilterMangasBookMarkedType': PropertySchema(
|
||||
id: 18,
|
||||
id: 19,
|
||||
name: r'libraryFilterMangasBookMarkedType',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'libraryFilterMangasDownloadType': PropertySchema(
|
||||
id: 19,
|
||||
id: 20,
|
||||
name: r'libraryFilterMangasDownloadType',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'libraryFilterMangasStartedType': PropertySchema(
|
||||
id: 20,
|
||||
id: 21,
|
||||
name: r'libraryFilterMangasStartedType',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'libraryFilterMangasUnreadType': PropertySchema(
|
||||
id: 21,
|
||||
id: 22,
|
||||
name: r'libraryFilterMangasUnreadType',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'libraryShowCategoryTabs': PropertySchema(
|
||||
id: 22,
|
||||
id: 23,
|
||||
name: r'libraryShowCategoryTabs',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'libraryShowContinueReadingButton': PropertySchema(
|
||||
id: 23,
|
||||
id: 24,
|
||||
name: r'libraryShowContinueReadingButton',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'libraryShowLanguage': PropertySchema(
|
||||
id: 24,
|
||||
id: 25,
|
||||
name: r'libraryShowLanguage',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'libraryShowNumbersOfItems': PropertySchema(
|
||||
id: 25,
|
||||
id: 26,
|
||||
name: r'libraryShowNumbersOfItems',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'onlyIncludePinnedSources': PropertySchema(
|
||||
id: 26,
|
||||
id: 27,
|
||||
name: r'onlyIncludePinnedSources',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'personalReaderModeList': PropertySchema(
|
||||
id: 27,
|
||||
id: 28,
|
||||
name: r'personalReaderModeList',
|
||||
type: IsarType.objectList,
|
||||
target: r'PersonalReaderMode',
|
||||
),
|
||||
r'pureBlackDarkMode': PropertySchema(
|
||||
id: 28,
|
||||
id: 29,
|
||||
name: r'pureBlackDarkMode',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'relativeTimesTamps': PropertySchema(
|
||||
id: 29,
|
||||
id: 30,
|
||||
name: r'relativeTimesTamps',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'saveAsCBZArchive': PropertySchema(
|
||||
id: 30,
|
||||
id: 31,
|
||||
name: r'saveAsCBZArchive',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'showNSFW': PropertySchema(
|
||||
id: 31,
|
||||
id: 32,
|
||||
name: r'showNSFW',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'showPagesNumber': PropertySchema(
|
||||
id: 32,
|
||||
id: 33,
|
||||
name: r'showPagesNumber',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'sortChapterList': PropertySchema(
|
||||
id: 33,
|
||||
id: 34,
|
||||
name: r'sortChapterList',
|
||||
type: IsarType.objectList,
|
||||
target: r'SortChapter',
|
||||
),
|
||||
r'sortLibraryManga': PropertySchema(
|
||||
id: 34,
|
||||
id: 35,
|
||||
name: r'sortLibraryManga',
|
||||
type: IsarType.object,
|
||||
target: r'SortLibraryManga',
|
||||
),
|
||||
r'themeIsDark': PropertySchema(
|
||||
id: 35,
|
||||
id: 36,
|
||||
name: r'themeIsDark',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'userAgent': PropertySchema(
|
||||
id: 36,
|
||||
id: 37,
|
||||
name: r'userAgent',
|
||||
type: IsarType.string,
|
||||
)
|
||||
|
|
@ -443,56 +448,57 @@ void _settingsSerialize(
|
|||
CookieSchema.serialize,
|
||||
object.cookiesList,
|
||||
);
|
||||
writer.writeString(offsets[7], object.dateFormat);
|
||||
writer.writeByte(offsets[8], object.defaultReaderMode.index);
|
||||
writer.writeByte(offsets[9], object.displayType.index);
|
||||
writer.writeLong(offsets[10], object.doubleTapAnimationSpeed);
|
||||
writer.writeString(offsets[11], object.downloadLocation);
|
||||
writer.writeBool(offsets[12], object.downloadOnlyOnWifi);
|
||||
writer.writeBool(offsets[7], object.cropBorders);
|
||||
writer.writeString(offsets[8], object.dateFormat);
|
||||
writer.writeByte(offsets[9], object.defaultReaderMode.index);
|
||||
writer.writeByte(offsets[10], object.displayType.index);
|
||||
writer.writeLong(offsets[11], object.doubleTapAnimationSpeed);
|
||||
writer.writeString(offsets[12], object.downloadLocation);
|
||||
writer.writeBool(offsets[13], object.downloadOnlyOnWifi);
|
||||
writer.writeObjectList<FilterScanlator>(
|
||||
offsets[13],
|
||||
offsets[14],
|
||||
allOffsets,
|
||||
FilterScanlatorSchema.serialize,
|
||||
object.filterScanlatorList,
|
||||
);
|
||||
writer.writeDouble(offsets[14], object.flexColorSchemeBlendLevel);
|
||||
writer.writeLong(offsets[15], object.flexSchemeColorIndex);
|
||||
writer.writeBool(offsets[16], object.incognitoMode);
|
||||
writer.writeBool(offsets[17], object.libraryDownloadedChapters);
|
||||
writer.writeLong(offsets[18], object.libraryFilterMangasBookMarkedType);
|
||||
writer.writeLong(offsets[19], object.libraryFilterMangasDownloadType);
|
||||
writer.writeLong(offsets[20], object.libraryFilterMangasStartedType);
|
||||
writer.writeLong(offsets[21], object.libraryFilterMangasUnreadType);
|
||||
writer.writeBool(offsets[22], object.libraryShowCategoryTabs);
|
||||
writer.writeBool(offsets[23], object.libraryShowContinueReadingButton);
|
||||
writer.writeBool(offsets[24], object.libraryShowLanguage);
|
||||
writer.writeBool(offsets[25], object.libraryShowNumbersOfItems);
|
||||
writer.writeBool(offsets[26], object.onlyIncludePinnedSources);
|
||||
writer.writeDouble(offsets[15], object.flexColorSchemeBlendLevel);
|
||||
writer.writeLong(offsets[16], object.flexSchemeColorIndex);
|
||||
writer.writeBool(offsets[17], object.incognitoMode);
|
||||
writer.writeBool(offsets[18], object.libraryDownloadedChapters);
|
||||
writer.writeLong(offsets[19], object.libraryFilterMangasBookMarkedType);
|
||||
writer.writeLong(offsets[20], object.libraryFilterMangasDownloadType);
|
||||
writer.writeLong(offsets[21], object.libraryFilterMangasStartedType);
|
||||
writer.writeLong(offsets[22], object.libraryFilterMangasUnreadType);
|
||||
writer.writeBool(offsets[23], object.libraryShowCategoryTabs);
|
||||
writer.writeBool(offsets[24], object.libraryShowContinueReadingButton);
|
||||
writer.writeBool(offsets[25], object.libraryShowLanguage);
|
||||
writer.writeBool(offsets[26], object.libraryShowNumbersOfItems);
|
||||
writer.writeBool(offsets[27], object.onlyIncludePinnedSources);
|
||||
writer.writeObjectList<PersonalReaderMode>(
|
||||
offsets[27],
|
||||
offsets[28],
|
||||
allOffsets,
|
||||
PersonalReaderModeSchema.serialize,
|
||||
object.personalReaderModeList,
|
||||
);
|
||||
writer.writeBool(offsets[28], object.pureBlackDarkMode);
|
||||
writer.writeLong(offsets[29], object.relativeTimesTamps);
|
||||
writer.writeBool(offsets[30], object.saveAsCBZArchive);
|
||||
writer.writeBool(offsets[31], object.showNSFW);
|
||||
writer.writeBool(offsets[32], object.showPagesNumber);
|
||||
writer.writeBool(offsets[29], object.pureBlackDarkMode);
|
||||
writer.writeLong(offsets[30], object.relativeTimesTamps);
|
||||
writer.writeBool(offsets[31], object.saveAsCBZArchive);
|
||||
writer.writeBool(offsets[32], object.showNSFW);
|
||||
writer.writeBool(offsets[33], object.showPagesNumber);
|
||||
writer.writeObjectList<SortChapter>(
|
||||
offsets[33],
|
||||
offsets[34],
|
||||
allOffsets,
|
||||
SortChapterSchema.serialize,
|
||||
object.sortChapterList,
|
||||
);
|
||||
writer.writeObject<SortLibraryManga>(
|
||||
offsets[34],
|
||||
offsets[35],
|
||||
allOffsets,
|
||||
SortLibraryMangaSchema.serialize,
|
||||
object.sortLibraryManga,
|
||||
);
|
||||
writer.writeBool(offsets[35], object.themeIsDark);
|
||||
writer.writeString(offsets[36], object.userAgent);
|
||||
writer.writeBool(offsets[36], object.themeIsDark);
|
||||
writer.writeString(offsets[37], object.userAgent);
|
||||
}
|
||||
|
||||
Settings _settingsDeserialize(
|
||||
|
|
@ -527,54 +533,55 @@ Settings _settingsDeserialize(
|
|||
allOffsets,
|
||||
Cookie(),
|
||||
),
|
||||
dateFormat: reader.readStringOrNull(offsets[7]),
|
||||
cropBorders: reader.readBoolOrNull(offsets[7]),
|
||||
dateFormat: reader.readStringOrNull(offsets[8]),
|
||||
defaultReaderMode: _SettingsdefaultReaderModeValueEnumMap[
|
||||
reader.readByteOrNull(offsets[8])] ??
|
||||
reader.readByteOrNull(offsets[9])] ??
|
||||
ReaderMode.vertical,
|
||||
displayType:
|
||||
_SettingsdisplayTypeValueEnumMap[reader.readByteOrNull(offsets[9])] ??
|
||||
_SettingsdisplayTypeValueEnumMap[reader.readByteOrNull(offsets[10])] ??
|
||||
DisplayType.compactGrid,
|
||||
doubleTapAnimationSpeed: reader.readLongOrNull(offsets[10]),
|
||||
downloadLocation: reader.readStringOrNull(offsets[11]),
|
||||
downloadOnlyOnWifi: reader.readBoolOrNull(offsets[12]),
|
||||
flexColorSchemeBlendLevel: reader.readDoubleOrNull(offsets[14]),
|
||||
flexSchemeColorIndex: reader.readLongOrNull(offsets[15]),
|
||||
doubleTapAnimationSpeed: reader.readLongOrNull(offsets[11]),
|
||||
downloadLocation: reader.readStringOrNull(offsets[12]),
|
||||
downloadOnlyOnWifi: reader.readBoolOrNull(offsets[13]),
|
||||
flexColorSchemeBlendLevel: reader.readDoubleOrNull(offsets[15]),
|
||||
flexSchemeColorIndex: reader.readLongOrNull(offsets[16]),
|
||||
id: id,
|
||||
incognitoMode: reader.readBoolOrNull(offsets[16]),
|
||||
libraryDownloadedChapters: reader.readBoolOrNull(offsets[17]),
|
||||
libraryFilterMangasBookMarkedType: reader.readLongOrNull(offsets[18]),
|
||||
libraryFilterMangasDownloadType: reader.readLongOrNull(offsets[19]),
|
||||
libraryFilterMangasStartedType: reader.readLongOrNull(offsets[20]),
|
||||
libraryFilterMangasUnreadType: reader.readLongOrNull(offsets[21]),
|
||||
libraryShowCategoryTabs: reader.readBoolOrNull(offsets[22]),
|
||||
libraryShowContinueReadingButton: reader.readBoolOrNull(offsets[23]),
|
||||
libraryShowLanguage: reader.readBoolOrNull(offsets[24]),
|
||||
libraryShowNumbersOfItems: reader.readBoolOrNull(offsets[25]),
|
||||
onlyIncludePinnedSources: reader.readBoolOrNull(offsets[26]),
|
||||
incognitoMode: reader.readBoolOrNull(offsets[17]),
|
||||
libraryDownloadedChapters: reader.readBoolOrNull(offsets[18]),
|
||||
libraryFilterMangasBookMarkedType: reader.readLongOrNull(offsets[19]),
|
||||
libraryFilterMangasDownloadType: reader.readLongOrNull(offsets[20]),
|
||||
libraryFilterMangasStartedType: reader.readLongOrNull(offsets[21]),
|
||||
libraryFilterMangasUnreadType: reader.readLongOrNull(offsets[22]),
|
||||
libraryShowCategoryTabs: reader.readBoolOrNull(offsets[23]),
|
||||
libraryShowContinueReadingButton: reader.readBoolOrNull(offsets[24]),
|
||||
libraryShowLanguage: reader.readBoolOrNull(offsets[25]),
|
||||
libraryShowNumbersOfItems: reader.readBoolOrNull(offsets[26]),
|
||||
onlyIncludePinnedSources: reader.readBoolOrNull(offsets[27]),
|
||||
personalReaderModeList: reader.readObjectList<PersonalReaderMode>(
|
||||
offsets[27],
|
||||
offsets[28],
|
||||
PersonalReaderModeSchema.deserialize,
|
||||
allOffsets,
|
||||
PersonalReaderMode(),
|
||||
),
|
||||
pureBlackDarkMode: reader.readBoolOrNull(offsets[28]),
|
||||
relativeTimesTamps: reader.readLongOrNull(offsets[29]),
|
||||
saveAsCBZArchive: reader.readBoolOrNull(offsets[30]),
|
||||
showNSFW: reader.readBoolOrNull(offsets[31]),
|
||||
showPagesNumber: reader.readBoolOrNull(offsets[32]),
|
||||
pureBlackDarkMode: reader.readBoolOrNull(offsets[29]),
|
||||
relativeTimesTamps: reader.readLongOrNull(offsets[30]),
|
||||
saveAsCBZArchive: reader.readBoolOrNull(offsets[31]),
|
||||
showNSFW: reader.readBoolOrNull(offsets[32]),
|
||||
showPagesNumber: reader.readBoolOrNull(offsets[33]),
|
||||
sortChapterList: reader.readObjectList<SortChapter>(
|
||||
offsets[33],
|
||||
offsets[34],
|
||||
SortChapterSchema.deserialize,
|
||||
allOffsets,
|
||||
SortChapter(),
|
||||
),
|
||||
sortLibraryManga: reader.readObjectOrNull<SortLibraryManga>(
|
||||
offsets[34],
|
||||
offsets[35],
|
||||
SortLibraryMangaSchema.deserialize,
|
||||
allOffsets,
|
||||
),
|
||||
themeIsDark: reader.readBoolOrNull(offsets[35]),
|
||||
userAgent: reader.readStringOrNull(offsets[36]),
|
||||
themeIsDark: reader.readBoolOrNull(offsets[36]),
|
||||
userAgent: reader.readStringOrNull(offsets[37]),
|
||||
);
|
||||
object.chapterFilterBookmarkedList =
|
||||
reader.readObjectList<ChapterFilterBookmarked>(
|
||||
|
|
@ -590,7 +597,7 @@ Settings _settingsDeserialize(
|
|||
ChapterFilterUnread(),
|
||||
);
|
||||
object.filterScanlatorList = reader.readObjectList<FilterScanlator>(
|
||||
offsets[13],
|
||||
offsets[14],
|
||||
FilterScanlatorSchema.deserialize,
|
||||
allOffsets,
|
||||
FilterScanlator(),
|
||||
|
|
@ -650,37 +657,37 @@ P _settingsDeserializeProp<P>(
|
|||
Cookie(),
|
||||
)) as P;
|
||||
case 7:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 8:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 9:
|
||||
return (_SettingsdefaultReaderModeValueEnumMap[
|
||||
reader.readByteOrNull(offset)] ??
|
||||
ReaderMode.vertical) as P;
|
||||
case 9:
|
||||
case 10:
|
||||
return (_SettingsdisplayTypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
DisplayType.compactGrid) as P;
|
||||
case 10:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 11:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 12:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 13:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 14:
|
||||
return (reader.readObjectList<FilterScanlator>(
|
||||
offset,
|
||||
FilterScanlatorSchema.deserialize,
|
||||
allOffsets,
|
||||
FilterScanlator(),
|
||||
)) as P;
|
||||
case 14:
|
||||
return (reader.readDoubleOrNull(offset)) as P;
|
||||
case 15:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
return (reader.readDoubleOrNull(offset)) as P;
|
||||
case 16:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 17:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 18:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 19:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 20:
|
||||
|
|
@ -688,7 +695,7 @@ P _settingsDeserializeProp<P>(
|
|||
case 21:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 22:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 23:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 24:
|
||||
|
|
@ -698,38 +705,40 @@ P _settingsDeserializeProp<P>(
|
|||
case 26:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 27:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 28:
|
||||
return (reader.readObjectList<PersonalReaderMode>(
|
||||
offset,
|
||||
PersonalReaderModeSchema.deserialize,
|
||||
allOffsets,
|
||||
PersonalReaderMode(),
|
||||
)) as P;
|
||||
case 28:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 29:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 30:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 30:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 31:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 32:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 33:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 34:
|
||||
return (reader.readObjectList<SortChapter>(
|
||||
offset,
|
||||
SortChapterSchema.deserialize,
|
||||
allOffsets,
|
||||
SortChapter(),
|
||||
)) as P;
|
||||
case 34:
|
||||
case 35:
|
||||
return (reader.readObjectOrNull<SortLibraryManga>(
|
||||
offset,
|
||||
SortLibraryMangaSchema.deserialize,
|
||||
allOffsets,
|
||||
)) as P;
|
||||
case 35:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 36:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 37:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
|
@ -1520,6 +1529,33 @@ extension SettingsQueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition> cropBordersIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'cropBorders',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition>
|
||||
cropBordersIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'cropBorders',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition> cropBordersEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'cropBorders',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterFilterCondition> dateFormatIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
|
|
@ -3543,6 +3579,18 @@ extension SettingsQuerySortBy on QueryBuilder<Settings, Settings, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> sortByCropBorders() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'cropBorders', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> sortByCropBordersDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'cropBorders', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> sortByDateFormat() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'dateFormat', Sort.asc);
|
||||
|
|
@ -3898,6 +3946,18 @@ extension SettingsQuerySortThenBy
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> thenByCropBorders() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'cropBorders', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> thenByCropBordersDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'cropBorders', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QAfterSortBy> thenByDateFormat() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'dateFormat', Sort.asc);
|
||||
|
|
@ -4258,6 +4318,12 @@ extension SettingsQueryWhereDistinct
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QDistinct> distinctByCropBorders() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'cropBorders');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, Settings, QDistinct> distinctByDateFormat(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
|
@ -4487,6 +4553,12 @@ extension SettingsQueryProperty
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, bool?, QQueryOperations> cropBordersProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'cropBorders');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Settings, String?, QQueryOperations> dateFormatProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'dateFormat');
|
||||
|
|
|
|||
|
|
@ -57,70 +57,75 @@ Future<List<String>> downloadChapter(
|
|||
});
|
||||
|
||||
if (pageUrls.isNotEmpty) {
|
||||
for (var index = 0; index < pageUrls.length; index++) {
|
||||
final path2 = Directory("${path1.path}downloads/");
|
||||
final path4 = Directory(
|
||||
"${path2.path}${manga.source} (${manga.lang!.toUpperCase()})/");
|
||||
final path3 =
|
||||
Directory("${path4.path}${manga.name!.replaceAll(regExp, '_')}/");
|
||||
|
||||
if (!(await path1.exists())) {
|
||||
path1.create();
|
||||
}
|
||||
if (Platform.isAndroid) {
|
||||
if (!(await File("${path1.path}" ".nomedia").exists())) {
|
||||
File("${path1.path}" ".nomedia").create();
|
||||
}
|
||||
}
|
||||
if (!(await path2.exists())) {
|
||||
path2.create();
|
||||
}
|
||||
if (!(await path4.exists())) {
|
||||
path4.create();
|
||||
}
|
||||
if (!(await path3.exists())) {
|
||||
path3.create();
|
||||
}
|
||||
|
||||
if ((await path.exists())) {
|
||||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg").exists()) {
|
||||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isAndroid
|
||||
? BaseDirectory.temporary
|
||||
: BaseDirectory.applicationDocuments,
|
||||
directory: 'Mangayomi/$finalPath',
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
requiresWiFi: onlyOnWifi));
|
||||
}
|
||||
} else {
|
||||
path.create();
|
||||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg").exists()) {
|
||||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isAndroid
|
||||
? BaseDirectory.temporary
|
||||
: BaseDirectory.applicationDocuments,
|
||||
directory: 'Mangayomi/$finalPath',
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
requiresWiFi: onlyOnWifi));
|
||||
}
|
||||
}
|
||||
}
|
||||
bool cbzFileExist =
|
||||
await File("${mangaDir!.path}${chapter.name}.cbz").exists() &&
|
||||
ref.watch(saveAsCBZArchiveStateProvider);
|
||||
if (tasks.isEmpty && pageUrls.isNotEmpty || cbzFileExist) {
|
||||
if (!cbzFileExist) {
|
||||
for (var index = 0; index < pageUrls.length; index++) {
|
||||
final path2 = Directory("${path1.path}downloads/");
|
||||
final path4 = Directory(
|
||||
"${path2.path}${manga.source} (${manga.lang!.toUpperCase()})/");
|
||||
final path3 =
|
||||
Directory("${path4.path}${manga.name!.replaceAll(regExp, '_')}/");
|
||||
|
||||
if (!(await path1.exists())) {
|
||||
path1.create();
|
||||
}
|
||||
if (Platform.isAndroid) {
|
||||
if (!(await File("${path1.path}" ".nomedia").exists())) {
|
||||
File("${path1.path}" ".nomedia").create();
|
||||
}
|
||||
}
|
||||
if (!(await path2.exists())) {
|
||||
path2.create();
|
||||
}
|
||||
if (!(await path4.exists())) {
|
||||
path4.create();
|
||||
}
|
||||
if (!(await path3.exists())) {
|
||||
path3.create();
|
||||
}
|
||||
|
||||
if ((await path.exists())) {
|
||||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
|
||||
.exists()) {
|
||||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isAndroid
|
||||
? BaseDirectory.temporary
|
||||
: BaseDirectory.applicationDocuments,
|
||||
directory: 'Mangayomi/$finalPath',
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
requiresWiFi: onlyOnWifi));
|
||||
}
|
||||
} else {
|
||||
path.create();
|
||||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
|
||||
.exists()) {
|
||||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isAndroid
|
||||
? BaseDirectory.temporary
|
||||
: BaseDirectory.applicationDocuments,
|
||||
directory: 'Mangayomi/$finalPath',
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
requiresWiFi: onlyOnWifi));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tasks.isEmpty && pageUrls.isNotEmpty) {
|
||||
final model = Download(
|
||||
succeeded: 0,
|
||||
failed: 0,
|
||||
|
|
@ -130,12 +135,6 @@ Future<List<String>> downloadChapter(
|
|||
isStartDownload: false,
|
||||
chapterId: chapter.id);
|
||||
|
||||
if (!cbzFileExist) {
|
||||
await ref.watch(convertToCBZProvider(
|
||||
path.path, mangaDir.path, chapter.name!, pageUrls)
|
||||
.future);
|
||||
}
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
isar.downloads.putSync(model..chapter.value = chapter);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'download_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$downloadChapterHash() => r'daa033b273e622db5caa983be08beae1b2fc6082';
|
||||
String _$downloadChapterHash() => r'1ddc8d7c1d9b1f3fdea4ba1b4e8252a61597a616';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -39,25 +39,18 @@ class ImageViewCenter extends ConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return isLocale
|
||||
? archiveImage != null
|
||||
? ExtendedImage.memory(
|
||||
archiveImage!,
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
initGestureConfigHandler: initGestureConfigHandler,
|
||||
onDoubleTap: onDoubleTap,
|
||||
loadStateChanged: loadStateChanged,
|
||||
)
|
||||
: ExtendedImage.file(
|
||||
File("${path.path}" "${padIndex(index + 1)}.jpg"),
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
initGestureConfigHandler: initGestureConfigHandler,
|
||||
onDoubleTap: onDoubleTap,
|
||||
loadStateChanged: loadStateChanged,
|
||||
)
|
||||
? ExtendedImage.memory(
|
||||
archiveImage != null
|
||||
? archiveImage!
|
||||
: File("${path.path}" "${padIndex(index + 1)}.jpg")
|
||||
.readAsBytesSync(),
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
initGestureConfigHandler: initGestureConfigHandler,
|
||||
onDoubleTap: onDoubleTap,
|
||||
loadStateChanged: loadStateChanged,
|
||||
)
|
||||
: ExtendedImage.network(
|
||||
url,
|
||||
headers: ref.watch(headersProvider(source: source)),
|
||||
|
|
|
|||
|
|
@ -45,18 +45,15 @@ class ImageViewVertical extends ConsumerWidget {
|
|||
height: MediaQuery.of(context).padding.top,
|
||||
),
|
||||
isLocale
|
||||
? archiveImage != null
|
||||
? ExtendedImage.memory(
|
||||
archiveImage!,
|
||||
fit: BoxFit.contain,
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
)
|
||||
: ExtendedImage.file(
|
||||
fit: BoxFit.contain,
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
File('${path.path}${padIndex(index + 1)}.jpg'))
|
||||
? ExtendedImage.memory(
|
||||
archiveImage != null
|
||||
? archiveImage!
|
||||
: File('${path.path}${padIndex(index + 1)}.jpg')
|
||||
.readAsBytesSync(),
|
||||
fit: BoxFit.contain,
|
||||
clearMemoryCacheWhenDispose: true,
|
||||
enableMemoryCache: false,
|
||||
)
|
||||
: ExtendedImage.network(url,
|
||||
headers: ref.watch(headersProvider(source: source)),
|
||||
handleLoadingProgress: true,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import 'package:mangayomi/models/chapter.dart';
|
|||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/modules/manga/reader/providers/auto_crop_image_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/sources/utils/utils.dart';
|
||||
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
||||
|
|
@ -27,6 +29,7 @@ import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provi
|
|||
import 'package:mangayomi/modules/manga/reader/widgets/circular_progress_indicator_animate_rotate.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/reader_screen.dart';
|
||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photo_view/photo_view_gallery.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
|
|
@ -319,6 +322,48 @@ class _MangaChapterPageGalleryState
|
|||
}
|
||||
}
|
||||
|
||||
Future _cropImageFuture(Uint8List? image, String? url) async {
|
||||
final cropImage = await ref.watch(autoCropImageProvider(
|
||||
url,
|
||||
image,
|
||||
).future);
|
||||
if (cropImage != null) {
|
||||
cropImagesList.add(cropImage);
|
||||
} else {
|
||||
cropImagesList.add(null);
|
||||
}
|
||||
}
|
||||
|
||||
List<Uint8List?> cropImagesList = [];
|
||||
bool isOk = false;
|
||||
_cropImage() async {
|
||||
List<Future> futures = [];
|
||||
if (!isOk) {
|
||||
isOk = true;
|
||||
if (widget.archiveImages.isNotEmpty) {
|
||||
for (var image in widget.archiveImages) {
|
||||
futures.add(_cropImageFuture(image, null));
|
||||
}
|
||||
} else if (widget.isLocaleList.contains(true)) {
|
||||
for (var i = 0; i < widget.isLocaleList.length; i++) {
|
||||
if (widget.isLocaleList[i] == true) {
|
||||
Uint8List? image = File('${widget.path.path}${padIndex(i + 1)}.jpg')
|
||||
.readAsBytesSync();
|
||||
futures.add(_cropImageFuture(image, null));
|
||||
} else {
|
||||
futures.add(_cropImageFuture(null, null));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var url in widget.url) {
|
||||
futures.add(_cropImageFuture(null, url));
|
||||
}
|
||||
}
|
||||
await Future.wait(futures);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
ReaderMode? _selectedValue;
|
||||
bool _isView = false;
|
||||
Alignment _scalePosition = Alignment.center;
|
||||
|
|
@ -427,7 +472,7 @@ class _MangaChapterPageGalleryState
|
|||
Color _backgroundColor(BuildContext context) =>
|
||||
Theme.of(context).scaffoldBackgroundColor.withOpacity(0.9);
|
||||
|
||||
Widget _showMore() {
|
||||
Widget _showMore(bool cropBorders) {
|
||||
bool isNotFirstChapter = widget.readerController.getChapterIndex() + 1 !=
|
||||
widget.readerController.getChaptersLength();
|
||||
bool isNotLastChapter = widget.readerController.getChapterIndex() != 0;
|
||||
|
|
@ -707,7 +752,11 @@ class _MangaChapterPageGalleryState
|
|||
],
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(cropBordersStateProvider.notifier)
|
||||
.set(!cropBorders);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.screen_rotation,
|
||||
),
|
||||
|
|
@ -906,6 +955,8 @@ class _MangaChapterPageGalleryState
|
|||
double _imageDetailY = 0;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cropBorders = ref.watch(cropBordersStateProvider);
|
||||
_cropImage();
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||
|
|
@ -971,9 +1022,7 @@ class _MangaChapterPageGalleryState
|
|||
scrollDirection: _scrollDirection,
|
||||
reverse: _isReversHorizontal,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
preloadPagesCount: _isZoom
|
||||
? 0
|
||||
: widget.readerController.getPageLength(widget.url),
|
||||
preloadPagesCount: _isZoom ? 0 : 6,
|
||||
canScrollPage: (GestureDetails? gestureDetails) {
|
||||
return gestureDetails != null
|
||||
? !(gestureDetails.totalScale! > 1.0)
|
||||
|
|
@ -981,9 +1030,12 @@ class _MangaChapterPageGalleryState
|
|||
},
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ImageViewCenter(
|
||||
archiveImage: widget.archiveImages.isNotEmpty
|
||||
? widget.archiveImages[index]
|
||||
: null,
|
||||
archiveImage:
|
||||
cropImagesList.isNotEmpty && cropBorders == true
|
||||
? cropImagesList[index]
|
||||
: widget.archiveImages.isNotEmpty
|
||||
? widget.archiveImages[index]
|
||||
: null,
|
||||
titleManga: widget.readerController.getMangaName(),
|
||||
source: widget.readerController
|
||||
.getSourceName()
|
||||
|
|
@ -1129,9 +1181,12 @@ class _MangaChapterPageGalleryState
|
|||
|
||||
_doubleClickAnimationController.forward();
|
||||
},
|
||||
isLocale: _isReversHorizontal
|
||||
? widget.isLocaleList.reversed.toList()[index]
|
||||
: widget.isLocaleList[index],
|
||||
isLocale: cropImagesList.isNotEmpty &&
|
||||
cropBorders == true
|
||||
? true
|
||||
: _isReversHorizontal
|
||||
? widget.isLocaleList.reversed.toList()[index]
|
||||
: widget.isLocaleList[index],
|
||||
);
|
||||
},
|
||||
itemCount:
|
||||
|
|
@ -1139,7 +1194,7 @@ class _MangaChapterPageGalleryState
|
|||
onPageChanged: _onPageChanged)),
|
||||
_gestureRightLeft(),
|
||||
_gestureTopBottom(),
|
||||
_showMore(),
|
||||
_showMore(cropBorders),
|
||||
_showPage(),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
115
lib/modules/manga/reader/providers/auto_crop_image_provider.dart
Normal file
115
lib/modules/manga/reader/providers/auto_crop_image_provider.dart
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import 'dart:io';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:image/image.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'auto_crop_image_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<Uint8List?> autoCropImage(
|
||||
AutoCropImageRef ref, String? url, Uint8List? data) async {
|
||||
Uint8List? oldImage;
|
||||
Uint8List? newImage;
|
||||
String path = "";
|
||||
File? cachedImage;
|
||||
if (url != null) {
|
||||
cachedImage = await getCachedImageFile(url);
|
||||
}
|
||||
if (cachedImage != null) {
|
||||
path = cachedImage.path;
|
||||
}
|
||||
if (path.isNotEmpty) {
|
||||
oldImage = File(path).readAsBytesSync();
|
||||
} else if (data != null) {
|
||||
oldImage = data;
|
||||
}
|
||||
if (oldImage != null) {
|
||||
newImage = await compute(autocropImageIsolate, oldImage);
|
||||
}
|
||||
return newImage;
|
||||
}
|
||||
|
||||
Future<Uint8List?> autocropImageIsolate(List<int> data) async {
|
||||
Image? croppedImage;
|
||||
Image? image = decodeImage(data);
|
||||
final old = image;
|
||||
image = copyCrop(image!, 0, 0, image.width, image.height);
|
||||
|
||||
int left = 0;
|
||||
int top = 0;
|
||||
int right = image.width - 1;
|
||||
int bottom = image.height - 1;
|
||||
|
||||
// Find left coordinate
|
||||
for (int x = 0; x < image.width; x++) {
|
||||
bool stop = false;
|
||||
for (int y = 0; y < image.height; y++) {
|
||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stop) {
|
||||
left = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find top coordinate
|
||||
for (int y = 0; y < image.height; y++) {
|
||||
bool stop = false;
|
||||
for (int x = 0; x < image.width; x++) {
|
||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stop) {
|
||||
top = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find right coordinate
|
||||
for (int x = image.width - 1; x >= 0; x--) {
|
||||
bool stop = false;
|
||||
for (int y = 0; y < image.height; y++) {
|
||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stop) {
|
||||
right = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find bottom coordinate
|
||||
for (int y = image.height - 1; y >= 0; y--) {
|
||||
bool stop = false;
|
||||
for (int x = 0; x < image.width; x++) {
|
||||
if (image.getPixel(x, y) != getColor(255, 255, 255, 255)) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stop) {
|
||||
bottom = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Crop the image
|
||||
croppedImage = copyCrop(
|
||||
image,
|
||||
left,
|
||||
top,
|
||||
right - left + 1,
|
||||
bottom - top + 1,
|
||||
);
|
||||
if (old != croppedImage) {
|
||||
return encodeJpg(croppedImage) as Uint8List;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'auto_crop_image_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$autoCropImageHash() => r'aae86e74203def1027400fa81e06e8e10344487d';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
typedef AutoCropImageRef = AutoDisposeFutureProviderRef<Uint8List?>;
|
||||
|
||||
/// See also [autoCropImage].
|
||||
@ProviderFor(autoCropImage)
|
||||
const autoCropImageProvider = AutoCropImageFamily();
|
||||
|
||||
/// See also [autoCropImage].
|
||||
class AutoCropImageFamily extends Family<AsyncValue<Uint8List?>> {
|
||||
/// See also [autoCropImage].
|
||||
const AutoCropImageFamily();
|
||||
|
||||
/// See also [autoCropImage].
|
||||
AutoCropImageProvider call(
|
||||
String? url,
|
||||
Uint8List? data,
|
||||
) {
|
||||
return AutoCropImageProvider(
|
||||
url,
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoCropImageProvider getProviderOverride(
|
||||
covariant AutoCropImageProvider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.url,
|
||||
provider.data,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'autoCropImageProvider';
|
||||
}
|
||||
|
||||
/// See also [autoCropImage].
|
||||
class AutoCropImageProvider extends AutoDisposeFutureProvider<Uint8List?> {
|
||||
/// See also [autoCropImage].
|
||||
AutoCropImageProvider(
|
||||
this.url,
|
||||
this.data,
|
||||
) : super.internal(
|
||||
(ref) => autoCropImage(
|
||||
ref,
|
||||
url,
|
||||
data,
|
||||
),
|
||||
from: autoCropImageProvider,
|
||||
name: r'autoCropImageProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$autoCropImageHash,
|
||||
dependencies: AutoCropImageFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
AutoCropImageFamily._allTransitiveDependencies,
|
||||
);
|
||||
|
||||
final String? url;
|
||||
final Uint8List? data;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is AutoCropImageProvider &&
|
||||
other.url == url &&
|
||||
other.data == data;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, url.hashCode);
|
||||
hash = _SystemHash.combine(hash, data.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
@ -47,3 +47,18 @@ class DoubleTapAnimationSpeedState extends _$DoubleTapAnimationSpeedState {
|
|||
isar.settings.putSync(settings!..doubleTapAnimationSpeed = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class CropBordersState extends _$CropBordersState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.cropBorders ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..cropBorders = value));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,4 +57,20 @@ final doubleTapAnimationSpeedStateProvider =
|
|||
);
|
||||
|
||||
typedef _$DoubleTapAnimationSpeedState = AutoDisposeNotifier<int>;
|
||||
String _$cropBordersStateHash() => r'65d636df7bebd9fb15b3915c1044c61f3479e806';
|
||||
|
||||
/// See also [CropBordersState].
|
||||
@ProviderFor(CropBordersState)
|
||||
final cropBordersStateProvider =
|
||||
AutoDisposeNotifierProvider<CropBordersState, bool>.internal(
|
||||
CropBordersState.new,
|
||||
name: r'cropBordersStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$cropBordersStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$CropBordersState = AutoDisposeNotifier<bool>;
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class ReaderScreen extends ConsumerWidget {
|
|||
final defaultReadingMode = ref.watch(defaultReadingModeStateProvider);
|
||||
final animatePageTransitions =
|
||||
ref.watch(animatePageTransitionsStateProvider);
|
||||
final cropBorders = ref.watch(cropBordersStateProvider);
|
||||
final doubleTapAnimationSpeed =
|
||||
ref.watch(doubleTapAnimationSpeedStateProvider);
|
||||
return Scaffold(
|
||||
|
|
@ -150,6 +151,14 @@ class ReaderScreen extends ConsumerWidget {
|
|||
.read(animatePageTransitionsStateProvider.notifier)
|
||||
.set(value);
|
||||
}),
|
||||
SwitchListTile(
|
||||
value: cropBorders,
|
||||
title: const Text("Crop borders"),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(cropBordersStateProvider.notifier)
|
||||
.set(value);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
14
pubspec.lock
14
pubspec.lock
|
|
@ -438,14 +438,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
|
@ -590,13 +582,13 @@ packages:
|
|||
source: hosted
|
||||
version: "4.0.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image
|
||||
sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227"
|
||||
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.15"
|
||||
version: "3.3.0"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
27
pubspec.yaml
27
pubspec.yaml
|
|
@ -63,6 +63,7 @@ dependencies:
|
|||
archive: ^3.3.7
|
||||
file_picker: ^5.3.0
|
||||
path_provider: ^2.0.15
|
||||
image: ^3.3.0
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
|
@ -74,22 +75,22 @@ dev_dependencies:
|
|||
sdk: flutter
|
||||
build_runner: ^2.4.5
|
||||
riverpod_generator: ^2.2.3
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
# flutter_launcher_icons: ^0.13.1
|
||||
isar_generator: 3.1.0+1
|
||||
flutter_lints: ^2.0.1
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: "launcher_icon"
|
||||
ios: true
|
||||
remove_alpha_ios: true
|
||||
image_path: "assets/mangayomi_logo.png"
|
||||
min_sdk_android: 24
|
||||
windows:
|
||||
generate: true
|
||||
image_path: "assets/mangayomi_logo.png"
|
||||
macos:
|
||||
generate: true
|
||||
image_path: "assets/mangayomi_logo.png"
|
||||
# flutter_launcher_icons:
|
||||
# android: "launcher_icon"
|
||||
# ios: true
|
||||
# remove_alpha_ios: true
|
||||
# image_path: "assets/mangayomi_logo.png"
|
||||
# min_sdk_android: 24
|
||||
# windows:
|
||||
# generate: true
|
||||
# image_path: "assets/mangayomi_logo.png"
|
||||
# macos:
|
||||
# generate: true
|
||||
# image_path: "assets/mangayomi_logo.png"
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
|
|
|
|||
Loading…
Reference in a new issue