added display type feature

This commit is contained in:
kodjomoustapha 2024-02-23 19:18:03 +01:00
parent ce45b2a1f6
commit 48c6c83355
13 changed files with 606 additions and 200 deletions

View file

@ -174,6 +174,9 @@ class Settings {
late PlayerSubtitleSettings? playerSubtitleSettings;
@enumerated
late DisplayType mangaHomeDisplayType;
Settings(
{this.id = 227,
this.displayType = DisplayType.compactGrid,
@ -250,7 +253,8 @@ class Settings {
this.enableCustomColorFilter = false,
this.customColorFilter,
this.colorFilterBlendMode = ColorFilterBlendMode.none,
this.playerSubtitleSettings});
this.playerSubtitleSettings,
this.mangaHomeDisplayType = DisplayType.comfortableGrid});
Settings.fromJson(Map<String, dynamic> json) {
animatePageTransitions = json['animatePageTransitions'];
@ -389,6 +393,7 @@ class Settings {
playerSubtitleSettings = json['playerSubtitleSettings'] != null
? PlayerSubtitleSettings.fromJson(json['customColorFilter'])
: null;
mangaHomeDisplayType = DisplayType.values[json['mangaHomeDisplayType']];
}
Map<String, dynamic> toJson() => {
@ -492,6 +497,7 @@ class Settings {
'colorFilterBlendMode': colorFilterBlendMode.index,
if (playerSubtitleSettings != null)
'playerSubtitleSettings': playerSubtitleSettings!.toJson(),
'mangaHomeDisplayType': mangaHomeDisplayType.index,
};
}

View file

@ -327,110 +327,116 @@ const SettingsSchema = CollectionSchema(
type: IsarType.object,
target: r'L10nLocale',
),
r'markEpisodeAsSeenType': PropertySchema(
r'mangaHomeDisplayType': PropertySchema(
id: 59,
name: r'mangaHomeDisplayType',
type: IsarType.byte,
enumMap: _SettingsmangaHomeDisplayTypeEnumValueMap,
),
r'markEpisodeAsSeenType': PropertySchema(
id: 60,
name: r'markEpisodeAsSeenType',
type: IsarType.long,
),
r'onlyIncludePinnedSources': PropertySchema(
id: 60,
id: 61,
name: r'onlyIncludePinnedSources',
type: IsarType.bool,
),
r'pagePreloadAmount': PropertySchema(
id: 61,
id: 62,
name: r'pagePreloadAmount',
type: IsarType.long,
),
r'personalPageModeList': PropertySchema(
id: 62,
id: 63,
name: r'personalPageModeList',
type: IsarType.objectList,
target: r'PersonalPageMode',
),
r'personalReaderModeList': PropertySchema(
id: 63,
id: 64,
name: r'personalReaderModeList',
type: IsarType.objectList,
target: r'PersonalReaderMode',
),
r'playerSubtitleSettings': PropertySchema(
id: 64,
id: 65,
name: r'playerSubtitleSettings',
type: IsarType.object,
target: r'PlayerSubtitleSettings',
),
r'pureBlackDarkMode': PropertySchema(
id: 65,
id: 66,
name: r'pureBlackDarkMode',
type: IsarType.bool,
),
r'relativeTimesTamps': PropertySchema(
id: 66,
id: 67,
name: r'relativeTimesTamps',
type: IsarType.long,
),
r'saveAsCBZArchive': PropertySchema(
id: 67,
id: 68,
name: r'saveAsCBZArchive',
type: IsarType.bool,
),
r'scaleType': PropertySchema(
id: 68,
id: 69,
name: r'scaleType',
type: IsarType.byte,
enumMap: _SettingsscaleTypeEnumValueMap,
),
r'showNSFW': PropertySchema(
id: 69,
id: 70,
name: r'showNSFW',
type: IsarType.bool,
),
r'showPagesNumber': PropertySchema(
id: 70,
id: 71,
name: r'showPagesNumber',
type: IsarType.bool,
),
r'sortChapterList': PropertySchema(
id: 71,
id: 72,
name: r'sortChapterList',
type: IsarType.objectList,
target: r'SortChapter',
),
r'sortLibraryAnime': PropertySchema(
id: 72,
id: 73,
name: r'sortLibraryAnime',
type: IsarType.object,
target: r'SortLibraryManga',
),
r'sortLibraryManga': PropertySchema(
id: 73,
id: 74,
name: r'sortLibraryManga',
type: IsarType.object,
target: r'SortLibraryManga',
),
r'startDatebackup': PropertySchema(
id: 74,
id: 75,
name: r'startDatebackup',
type: IsarType.long,
),
r'themeIsDark': PropertySchema(
id: 75,
id: 76,
name: r'themeIsDark',
type: IsarType.bool,
),
r'updateProgressAfterReading': PropertySchema(
id: 76,
id: 77,
name: r'updateProgressAfterReading',
type: IsarType.bool,
),
r'usePageTapZones': PropertySchema(
id: 77,
id: 78,
name: r'usePageTapZones',
type: IsarType.bool,
),
r'userAgent': PropertySchema(
id: 78,
id: 79,
name: r'userAgent',
type: IsarType.string,
)
@ -825,56 +831,57 @@ void _settingsSerialize(
L10nLocaleSchema.serialize,
object.locale,
);
writer.writeLong(offsets[59], object.markEpisodeAsSeenType);
writer.writeBool(offsets[60], object.onlyIncludePinnedSources);
writer.writeLong(offsets[61], object.pagePreloadAmount);
writer.writeByte(offsets[59], object.mangaHomeDisplayType.index);
writer.writeLong(offsets[60], object.markEpisodeAsSeenType);
writer.writeBool(offsets[61], object.onlyIncludePinnedSources);
writer.writeLong(offsets[62], object.pagePreloadAmount);
writer.writeObjectList<PersonalPageMode>(
offsets[62],
offsets[63],
allOffsets,
PersonalPageModeSchema.serialize,
object.personalPageModeList,
);
writer.writeObjectList<PersonalReaderMode>(
offsets[63],
offsets[64],
allOffsets,
PersonalReaderModeSchema.serialize,
object.personalReaderModeList,
);
writer.writeObject<PlayerSubtitleSettings>(
offsets[64],
offsets[65],
allOffsets,
PlayerSubtitleSettingsSchema.serialize,
object.playerSubtitleSettings,
);
writer.writeBool(offsets[65], object.pureBlackDarkMode);
writer.writeLong(offsets[66], object.relativeTimesTamps);
writer.writeBool(offsets[67], object.saveAsCBZArchive);
writer.writeByte(offsets[68], object.scaleType.index);
writer.writeBool(offsets[69], object.showNSFW);
writer.writeBool(offsets[70], object.showPagesNumber);
writer.writeBool(offsets[66], object.pureBlackDarkMode);
writer.writeLong(offsets[67], object.relativeTimesTamps);
writer.writeBool(offsets[68], object.saveAsCBZArchive);
writer.writeByte(offsets[69], object.scaleType.index);
writer.writeBool(offsets[70], object.showNSFW);
writer.writeBool(offsets[71], object.showPagesNumber);
writer.writeObjectList<SortChapter>(
offsets[71],
offsets[72],
allOffsets,
SortChapterSchema.serialize,
object.sortChapterList,
);
writer.writeObject<SortLibraryManga>(
offsets[72],
offsets[73],
allOffsets,
SortLibraryMangaSchema.serialize,
object.sortLibraryAnime,
);
writer.writeObject<SortLibraryManga>(
offsets[73],
offsets[74],
allOffsets,
SortLibraryMangaSchema.serialize,
object.sortLibraryManga,
);
writer.writeLong(offsets[74], object.startDatebackup);
writer.writeBool(offsets[75], object.themeIsDark);
writer.writeBool(offsets[76], object.updateProgressAfterReading);
writer.writeBool(offsets[77], object.usePageTapZones);
writer.writeString(offsets[78], object.userAgent);
writer.writeLong(offsets[75], object.startDatebackup);
writer.writeBool(offsets[76], object.themeIsDark);
writer.writeBool(offsets[77], object.updateProgressAfterReading);
writer.writeBool(offsets[78], object.usePageTapZones);
writer.writeString(offsets[79], object.userAgent);
}
Settings _settingsDeserialize(
@ -979,55 +986,58 @@ Settings _settingsDeserialize(
libraryShowContinueReadingButton: reader.readBoolOrNull(offsets[55]),
libraryShowLanguage: reader.readBoolOrNull(offsets[56]),
libraryShowNumbersOfItems: reader.readBoolOrNull(offsets[57]),
markEpisodeAsSeenType: reader.readLongOrNull(offsets[59]),
onlyIncludePinnedSources: reader.readBoolOrNull(offsets[60]),
pagePreloadAmount: reader.readLongOrNull(offsets[61]),
mangaHomeDisplayType: _SettingsmangaHomeDisplayTypeValueEnumMap[
reader.readByteOrNull(offsets[59])] ??
DisplayType.comfortableGrid,
markEpisodeAsSeenType: reader.readLongOrNull(offsets[60]),
onlyIncludePinnedSources: reader.readBoolOrNull(offsets[61]),
pagePreloadAmount: reader.readLongOrNull(offsets[62]),
personalPageModeList: reader.readObjectList<PersonalPageMode>(
offsets[62],
offsets[63],
PersonalPageModeSchema.deserialize,
allOffsets,
PersonalPageMode(),
),
personalReaderModeList: reader.readObjectList<PersonalReaderMode>(
offsets[63],
offsets[64],
PersonalReaderModeSchema.deserialize,
allOffsets,
PersonalReaderMode(),
),
playerSubtitleSettings: reader.readObjectOrNull<PlayerSubtitleSettings>(
offsets[64],
offsets[65],
PlayerSubtitleSettingsSchema.deserialize,
allOffsets,
),
pureBlackDarkMode: reader.readBoolOrNull(offsets[65]),
relativeTimesTamps: reader.readLongOrNull(offsets[66]),
saveAsCBZArchive: reader.readBoolOrNull(offsets[67]),
pureBlackDarkMode: reader.readBoolOrNull(offsets[66]),
relativeTimesTamps: reader.readLongOrNull(offsets[67]),
saveAsCBZArchive: reader.readBoolOrNull(offsets[68]),
scaleType:
_SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offsets[68])] ??
_SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offsets[69])] ??
ScaleType.fitScreen,
showNSFW: reader.readBoolOrNull(offsets[69]),
showPagesNumber: reader.readBoolOrNull(offsets[70]),
showNSFW: reader.readBoolOrNull(offsets[70]),
showPagesNumber: reader.readBoolOrNull(offsets[71]),
sortChapterList: reader.readObjectList<SortChapter>(
offsets[71],
offsets[72],
SortChapterSchema.deserialize,
allOffsets,
SortChapter(),
),
sortLibraryAnime: reader.readObjectOrNull<SortLibraryManga>(
offsets[72],
SortLibraryMangaSchema.deserialize,
allOffsets,
),
sortLibraryManga: reader.readObjectOrNull<SortLibraryManga>(
offsets[73],
SortLibraryMangaSchema.deserialize,
allOffsets,
),
startDatebackup: reader.readLongOrNull(offsets[74]),
themeIsDark: reader.readBoolOrNull(offsets[75]),
updateProgressAfterReading: reader.readBoolOrNull(offsets[76]),
usePageTapZones: reader.readBoolOrNull(offsets[77]),
userAgent: reader.readStringOrNull(offsets[78]),
sortLibraryManga: reader.readObjectOrNull<SortLibraryManga>(
offsets[74],
SortLibraryMangaSchema.deserialize,
allOffsets,
),
startDatebackup: reader.readLongOrNull(offsets[75]),
themeIsDark: reader.readBoolOrNull(offsets[76]),
updateProgressAfterReading: reader.readBoolOrNull(offsets[77]),
usePageTapZones: reader.readBoolOrNull(offsets[78]),
userAgent: reader.readStringOrNull(offsets[79]),
);
object.chapterFilterBookmarkedList =
reader.readObjectList<ChapterFilterBookmarked>(
@ -1239,57 +1249,55 @@ P _settingsDeserializeProp<P>(
allOffsets,
)) as P;
case 59:
return (reader.readLongOrNull(offset)) as P;
return (_SettingsmangaHomeDisplayTypeValueEnumMap[
reader.readByteOrNull(offset)] ??
DisplayType.comfortableGrid) as P;
case 60:
return (reader.readBoolOrNull(offset)) as P;
case 61:
return (reader.readLongOrNull(offset)) as P;
case 61:
return (reader.readBoolOrNull(offset)) as P;
case 62:
return (reader.readLongOrNull(offset)) as P;
case 63:
return (reader.readObjectList<PersonalPageMode>(
offset,
PersonalPageModeSchema.deserialize,
allOffsets,
PersonalPageMode(),
)) as P;
case 63:
case 64:
return (reader.readObjectList<PersonalReaderMode>(
offset,
PersonalReaderModeSchema.deserialize,
allOffsets,
PersonalReaderMode(),
)) as P;
case 64:
case 65:
return (reader.readObjectOrNull<PlayerSubtitleSettings>(
offset,
PlayerSubtitleSettingsSchema.deserialize,
allOffsets,
)) as P;
case 65:
return (reader.readBoolOrNull(offset)) as P;
case 66:
return (reader.readLongOrNull(offset)) as P;
case 67:
return (reader.readBoolOrNull(offset)) as P;
case 67:
return (reader.readLongOrNull(offset)) as P;
case 68:
return (reader.readBoolOrNull(offset)) as P;
case 69:
return (_SettingsscaleTypeValueEnumMap[reader.readByteOrNull(offset)] ??
ScaleType.fitScreen) as P;
case 69:
return (reader.readBoolOrNull(offset)) as P;
case 70:
return (reader.readBoolOrNull(offset)) as P;
case 71:
return (reader.readBoolOrNull(offset)) as P;
case 72:
return (reader.readObjectList<SortChapter>(
offset,
SortChapterSchema.deserialize,
allOffsets,
SortChapter(),
)) as P;
case 72:
return (reader.readObjectOrNull<SortLibraryManga>(
offset,
SortLibraryMangaSchema.deserialize,
allOffsets,
)) as P;
case 73:
return (reader.readObjectOrNull<SortLibraryManga>(
offset,
@ -1297,14 +1305,20 @@ P _settingsDeserializeProp<P>(
allOffsets,
)) as P;
case 74:
return (reader.readLongOrNull(offset)) as P;
return (reader.readObjectOrNull<SortLibraryManga>(
offset,
SortLibraryMangaSchema.deserialize,
allOffsets,
)) as P;
case 75:
return (reader.readBoolOrNull(offset)) as P;
return (reader.readLongOrNull(offset)) as P;
case 76:
return (reader.readBoolOrNull(offset)) as P;
case 77:
return (reader.readBoolOrNull(offset)) as P;
case 78:
return (reader.readBoolOrNull(offset)) as P;
case 79:
return (reader.readStringOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
@ -1391,6 +1405,18 @@ const _SettingsdisplayTypeValueEnumMap = {
2: DisplayType.coverOnlyGrid,
3: DisplayType.list,
};
const _SettingsmangaHomeDisplayTypeEnumValueMap = {
'compactGrid': 0,
'comfortableGrid': 1,
'coverOnlyGrid': 2,
'list': 3,
};
const _SettingsmangaHomeDisplayTypeValueEnumMap = {
0: DisplayType.compactGrid,
1: DisplayType.comfortableGrid,
2: DisplayType.coverOnlyGrid,
3: DisplayType.list,
};
const _SettingsscaleTypeEnumValueMap = {
'fitScreen': 0,
'stretch': 1,
@ -5395,6 +5421,62 @@ extension SettingsQueryFilter
});
}
QueryBuilder<Settings, Settings, QAfterFilterCondition>
mangaHomeDisplayTypeEqualTo(DisplayType value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'mangaHomeDisplayType',
value: value,
));
});
}
QueryBuilder<Settings, Settings, QAfterFilterCondition>
mangaHomeDisplayTypeGreaterThan(
DisplayType value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'mangaHomeDisplayType',
value: value,
));
});
}
QueryBuilder<Settings, Settings, QAfterFilterCondition>
mangaHomeDisplayTypeLessThan(
DisplayType value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'mangaHomeDisplayType',
value: value,
));
});
}
QueryBuilder<Settings, Settings, QAfterFilterCondition>
mangaHomeDisplayTypeBetween(
DisplayType lower,
DisplayType upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.between(
property: r'mangaHomeDisplayType',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
));
});
}
QueryBuilder<Settings, Settings, QAfterFilterCondition>
markEpisodeAsSeenTypeIsNull() {
return QueryBuilder.apply(this, (query) {
@ -7303,6 +7385,19 @@ extension SettingsQuerySortBy on QueryBuilder<Settings, Settings, QSortBy> {
});
}
QueryBuilder<Settings, Settings, QAfterSortBy> sortByMangaHomeDisplayType() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'mangaHomeDisplayType', Sort.asc);
});
}
QueryBuilder<Settings, Settings, QAfterSortBy>
sortByMangaHomeDisplayTypeDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'mangaHomeDisplayType', Sort.desc);
});
}
QueryBuilder<Settings, Settings, QAfterSortBy> sortByMarkEpisodeAsSeenType() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'markEpisodeAsSeenType', Sort.asc);
@ -8129,6 +8224,19 @@ extension SettingsQuerySortThenBy
});
}
QueryBuilder<Settings, Settings, QAfterSortBy> thenByMangaHomeDisplayType() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'mangaHomeDisplayType', Sort.asc);
});
}
QueryBuilder<Settings, Settings, QAfterSortBy>
thenByMangaHomeDisplayTypeDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'mangaHomeDisplayType', Sort.desc);
});
}
QueryBuilder<Settings, Settings, QAfterSortBy> thenByMarkEpisodeAsSeenType() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'markEpisodeAsSeenType', Sort.asc);
@ -8634,6 +8742,12 @@ extension SettingsQueryWhereDistinct
});
}
QueryBuilder<Settings, Settings, QDistinct> distinctByMangaHomeDisplayType() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'mangaHomeDisplayType');
});
}
QueryBuilder<Settings, Settings, QDistinct>
distinctByMarkEpisodeAsSeenType() {
return QueryBuilder.apply(this, (query) {
@ -9130,6 +9244,13 @@ extension SettingsQueryProperty
});
}
QueryBuilder<Settings, DisplayType, QQueryOperations>
mangaHomeDisplayTypeProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'mangaHomeDisplayType');
});
}
QueryBuilder<Settings, int?, QQueryOperations>
markEpisodeAsSeenTypeProperty() {
return QueryBuilder.apply(this, (query) {

View file

@ -131,15 +131,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
final language = ref.watch(
libraryLanguageStateProvider(
isManga: widget.isManga, settings: settings));
final displayType = ref
.read(libraryDisplayTypeStateProvider(
isManga: widget.isManga,
settings: settings)
.notifier)
.getLibraryDisplayTypeValue(ref.watch(
libraryDisplayTypeStateProvider(
isManga: widget.isManga,
settings: settings)));
final displayType = ref.watch(
libraryDisplayTypeStateProvider(
isManga: widget.isManga, settings: settings));
final isNotFiltering = ref.watch(
mangasFilterResultStateProvider(
isManga: widget.isManga,
@ -386,14 +380,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
isManga: widget.isManga, settings: settings));
final language = ref.watch(libraryLanguageStateProvider(
isManga: widget.isManga, settings: settings));
final displayType = ref
.read(libraryDisplayTypeStateProvider(
isManga: widget.isManga, settings: settings)
.notifier)
.getLibraryDisplayTypeValue(ref.watch(
libraryDisplayTypeStateProvider(
isManga: widget.isManga,
settings: settings)));
final displayType = ref.watch(
libraryDisplayTypeStateProvider(
isManga: widget.isManga, settings: settings));
final isNotFiltering = ref.watch(
mangasFilterResultStateProvider(
isManga: widget.isManga,
@ -1368,8 +1357,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
child: Wrap(
children: DisplayType.values.map((e) {
final selected =
e == displayV.getLibraryDisplayTypeValue(display);
final selected = e == display;
return Padding(
padding: const EdgeInsets.only(right: 5),
child: ElevatedButton(
@ -1394,7 +1382,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
displayV.setLibraryDisplayType(e);
},
child: Text(
displayV.getLibraryDisplayTypeName(e.name, context),
displayV.getLibraryDisplayTypeName(e, context),
style: TextStyle(
color:
Theme.of(context).textTheme.bodyLarge!.color,

View file

@ -11,35 +11,25 @@ part 'library_state_provider.g.dart';
@riverpod
class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
@override
String build({required bool isManga, required Settings settings}) {
return isManga ? settings.displayType.name : settings.animeDisplayType.name;
DisplayType build({required bool isManga, required Settings settings}) {
return isManga ? settings.displayType : settings.animeDisplayType;
}
DisplayType getLibraryDisplayTypeValue(String value) {
return value == DisplayType.compactGrid.name
? DisplayType.compactGrid
: value == DisplayType.list.name
? DisplayType.list
: value == DisplayType.comfortableGrid.name
? DisplayType.comfortableGrid
: DisplayType.coverOnlyGrid;
}
String getLibraryDisplayTypeName(String displayType, BuildContext context) {
final l10n = l10nLocalizations(context)!;
return displayType == DisplayType.compactGrid.name
? l10n.compact_grid
: displayType == DisplayType.list.name
? l10n.list
: displayType == DisplayType.comfortableGrid.name
? l10n.comfortable_grid
: l10n.cover_only_grid;
String getLibraryDisplayTypeName(
DisplayType displayType, BuildContext context) {
final l10n = context.l10n;
return switch (displayType) {
DisplayType.compactGrid => l10n.compact_grid,
DisplayType.comfortableGrid => l10n.comfortable_grid,
DisplayType.coverOnlyGrid => l10n.cover_only_grid,
_ => l10n.list,
};
}
void setLibraryDisplayType(DisplayType displayType) {
Settings appSettings = Settings();
state = displayType.name;
state = displayType;
if (isManga) {
appSettings = settings..displayType = displayType;
} else {

View file

@ -7,7 +7,7 @@ part of 'library_state_provider.dart';
// **************************************************************************
String _$libraryDisplayTypeStateHash() =>
r'8a7669eb2d0961135bc1a9469d8fbcc7dda0ca3c';
r'6a18446eb49bc55d64fabfb0aa35ff1f2dd52d88';
/// Copied from Dart SDK
class _SystemHash {
@ -31,11 +31,11 @@ class _SystemHash {
}
abstract class _$LibraryDisplayTypeState
extends BuildlessAutoDisposeNotifier<String> {
extends BuildlessAutoDisposeNotifier<DisplayType> {
late final bool isManga;
late final Settings settings;
String build({
DisplayType build({
required bool isManga,
required Settings settings,
});
@ -46,7 +46,7 @@ abstract class _$LibraryDisplayTypeState
const libraryDisplayTypeStateProvider = LibraryDisplayTypeStateFamily();
/// See also [LibraryDisplayTypeState].
class LibraryDisplayTypeStateFamily extends Family<String> {
class LibraryDisplayTypeStateFamily extends Family<DisplayType> {
/// See also [LibraryDisplayTypeState].
const LibraryDisplayTypeStateFamily();
@ -87,8 +87,8 @@ class LibraryDisplayTypeStateFamily extends Family<String> {
}
/// See also [LibraryDisplayTypeState].
class LibraryDisplayTypeStateProvider
extends AutoDisposeNotifierProviderImpl<LibraryDisplayTypeState, String> {
class LibraryDisplayTypeStateProvider extends AutoDisposeNotifierProviderImpl<
LibraryDisplayTypeState, DisplayType> {
/// See also [LibraryDisplayTypeState].
LibraryDisplayTypeStateProvider({
required bool isManga,
@ -125,7 +125,7 @@ class LibraryDisplayTypeStateProvider
final Settings settings;
@override
String runNotifierBuild(
DisplayType runNotifierBuild(
covariant LibraryDisplayTypeState notifier,
) {
return notifier.build(
@ -154,7 +154,7 @@ class LibraryDisplayTypeStateProvider
}
@override
AutoDisposeNotifierProviderElement<LibraryDisplayTypeState, String>
AutoDisposeNotifierProviderElement<LibraryDisplayTypeState, DisplayType>
createElement() {
return _LibraryDisplayTypeStateProviderElement(this);
}
@ -176,7 +176,8 @@ class LibraryDisplayTypeStateProvider
}
}
mixin LibraryDisplayTypeStateRef on AutoDisposeNotifierProviderRef<String> {
mixin LibraryDisplayTypeStateRef
on AutoDisposeNotifierProviderRef<DisplayType> {
/// The parameter `isManga` of this provider.
bool get isManga;
@ -185,8 +186,8 @@ mixin LibraryDisplayTypeStateRef on AutoDisposeNotifierProviderRef<String> {
}
class _LibraryDisplayTypeStateProviderElement
extends AutoDisposeNotifierProviderElement<LibraryDisplayTypeState, String>
with LibraryDisplayTypeStateRef {
extends AutoDisposeNotifierProviderElement<LibraryDisplayTypeState,
DisplayType> with LibraryDisplayTypeStateRef {
_LibraryDisplayTypeStateProviderElement(super.provider);
@override

View file

@ -1498,8 +1498,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
Map<String, dynamic> data = {
'url': url,
'sourceId': source.id.toString(),
'title': manga.name!,
"hasCloudFlare": source.hasCloudflare ?? false,
'title': manga.name!
};
context.push("/mangawebview", extra: data);
},

View file

@ -4,8 +4,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/eval/model/m_manga.dart';
import 'package:mangayomi/eval/model/m_pages.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/modules/manga/home/providers/state_provider.dart';
import 'package:mangayomi/modules/manga/home/widget/filter_widget.dart';
import 'package:mangayomi/modules/widgets/listview_widget.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/get_filter_list.dart';
@ -19,6 +22,7 @@ import 'package:mangayomi/modules/library/widgets/search_text_form_field.dart';
import 'package:mangayomi/modules/manga/home/widget/mangas_card_selector.dart';
import 'package:mangayomi/modules/widgets/gridview_widget.dart';
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
import 'package:mangayomi/utils/global_style.dart';
class MangaHomeScreen extends ConsumerStatefulWidget {
final Source source;
@ -128,7 +132,14 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
} else if (_selectedIndex == 0 && !_isSearch && _query.isEmpty) {
_getManga = ref.watch(getPopularProvider(source: widget.source, page: 1));
}
final l10n = l10nLocalizations(context)!;
final l10n = context.l10n;
final displayType = ref.watch(mangaHomeDisplayTypeStateProvider);
final displayTypeIcon = switch (displayType) {
DisplayType.comfortableGrid ||
DisplayType.compactGrid =>
Icons.view_module,
_ => Icons.view_list,
};
return Scaffold(
appBar: AppBar(
title: _isSearch ? null : Text('${widget.source.name}'),
@ -182,24 +193,82 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
},
icon:
Icon(Icons.search, color: Theme.of(context).hintColor)),
IconButton(
onPressed: () {
final baseUrl =
ref.watch(sourceBaseUrlProvider(source: widget.source));
Map<String, dynamic> data = {
'url': baseUrl,
'sourceId': widget.source.id.toString(),
'title': '',
"hasCloudFlare": widget.source.hasCloudflare ?? false
};
context.push("/mangawebview", extra: data);
},
icon: Icon(
Icons.public,
size: 22,
color: context.secondaryColor,
),
)
PopupMenuButton(
popUpAnimationStyle: popupAnimationStyle,
icon: Icon(displayTypeIcon),
itemBuilder: (context) {
final displayType =
ref.watch(mangaHomeDisplayTypeStateProvider);
final displayTypeNotifier =
ref.read(mangaHomeDisplayTypeStateProvider.notifier);
return [
PopupMenuItem<int>(
value: 0,
child: RadioListTile(
title: Text(context.l10n.comfortable_grid),
value: DisplayType.comfortableGrid,
groupValue: displayType,
onChanged: (a) {
context.pop();
displayTypeNotifier.setMangaHomeDisplayType(a!);
},
),
),
PopupMenuItem<int>(
value: 1,
child: RadioListTile(
title: Text(context.l10n.compact_grid),
value: DisplayType.compactGrid,
groupValue: displayType,
onChanged: (a) {
context.pop();
displayTypeNotifier.setMangaHomeDisplayType(a!);
},
),
),
PopupMenuItem<int>(
value: 2,
child: RadioListTile(
title: Text(context.l10n.list),
value: DisplayType.list,
groupValue: displayType,
onChanged: (a) {
context.pop();
displayTypeNotifier.setMangaHomeDisplayType(a!);
},
),
),
];
},
onSelected: (value) {}),
PopupMenuButton(
popUpAnimationStyle: popupAnimationStyle,
itemBuilder: (context) {
return [
PopupMenuItem<int>(
value: 0,
child: Text(context.l10n.open_in_browser),
),
PopupMenuItem<int>(
value: 1,
child: Text(context.l10n.settings),
),
];
},
onSelected: (value) {
if (value == 0) {
final baseUrl =
ref.watch(sourceBaseUrlProvider(source: widget.source));
Map<String, dynamic> data = {
'url': baseUrl,
'sourceId': widget.source.id.toString(),
'title': ''
};
context.push("/mangawebview", extra: data);
} else {
context.push('/extension_detail', extra: widget.source);
}
}),
],
bottom: PreferredSize(
preferredSize: Size.fromHeight(AppBar().preferredSize.height * 0.8),
@ -297,11 +366,13 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
page: 1,
filterList: filters));
}
} else if (index != 2) {
} else {
setState(() {
_selectedIndex = index;
_isFiltering = false;
_isSearch = false;
_query = "";
_textEditingController.clear();
_page = 1;
_isLoading = false;
});
@ -341,7 +412,9 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
),
),
)
: context.isTablet
: context.isTablet ||
context.isMobile &&
displayType == DisplayType.list
? Padding(
padding: const EdgeInsets.all(4),
child: ElevatedButton(
@ -411,25 +484,43 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
widget.source.isFullData! ? _fullDataLength : _mangaList.length;
_length =
(_mangaList.length < _length ? _mangaList.length : _length);
final isComfortableGrid =
displayType == DisplayType.comfortableGrid;
return Padding(
padding: const EdgeInsets.only(top: 10),
child: Column(
children: [
Flexible(
child: GridViewWidget(
controller: _scrollController,
itemCount: _length + 1,
itemBuilder: (context, index) {
if (index == _length) {
return buildProgressIndicator();
}
return MangaHomeImageCard(
isManga: widget.source.isManga ?? true,
manga: _mangaList[index],
source: widget.source,
);
},
)),
child: displayType == DisplayType.list
? ListViewWidget(
controller: _scrollController,
itemCount: _length + 1,
itemBuilder: (context, index) {
if (index == _length) {
return buildProgressIndicator();
}
return MangaHomeImageCardListTile(
isManga: widget.source.isManga ?? true,
manga: _mangaList[index],
source: widget.source);
})
: GridViewWidget(
controller: _scrollController,
itemCount: _length + 1,
childAspectRatio:
isComfortableGrid ? 0.642 : 0.69,
itemBuilder: (context, index) {
if (index == _length) {
return buildProgressIndicator();
}
return MangaHomeImageCard(
isManga: widget.source.isManga ?? true,
manga: _mangaList[index],
source: widget.source,
isComfortableGrid: isComfortableGrid,
);
},
)),
],
),
);
@ -523,12 +614,13 @@ class MangaHomeImageCard extends ConsumerStatefulWidget {
final MManga manga;
final bool isManga;
final Source source;
const MangaHomeImageCard({
super.key,
required this.manga,
required this.source,
required this.isManga,
});
final bool isComfortableGrid;
const MangaHomeImageCard(
{super.key,
required this.manga,
required this.source,
required this.isManga,
required this.isComfortableGrid});
@override
ConsumerState<MangaHomeImageCard> createState() => _MangaHomeImageCardState();
@ -541,10 +633,42 @@ class _MangaHomeImageCardState extends ConsumerState<MangaHomeImageCard>
super.build(context);
return MangaImageCardWidget(
getMangaDetail: widget.manga,
source: widget.source,
isManga: widget.isManga,
);
getMangaDetail: widget.manga,
source: widget.source,
isManga: widget.isManga,
isComfortableGrid: widget.isComfortableGrid);
}
@override
bool get wantKeepAlive => true;
}
class MangaHomeImageCardListTile extends ConsumerStatefulWidget {
final MManga manga;
final bool isManga;
final Source source;
const MangaHomeImageCardListTile(
{super.key,
required this.manga,
required this.source,
required this.isManga});
@override
ConsumerState<MangaHomeImageCardListTile> createState() =>
_MangaHomeImageCardListTileState();
}
class _MangaHomeImageCardListTileState
extends ConsumerState<MangaHomeImageCardListTile>
with AutomaticKeepAliveClientMixin<MangaHomeImageCardListTile> {
@override
Widget build(BuildContext context) {
super.build(context);
return MangaImageCardListTileWidget(
getMangaDetail: widget.manga,
source: widget.source,
isManga: widget.isManga);
}
@override

View file

@ -0,0 +1,23 @@
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'state_provider.g.dart';
@riverpod
class MangaHomeDisplayTypeState extends _$MangaHomeDisplayTypeState {
@override
DisplayType build() {
final settings = isar.settings.getSync(227)!;
return settings.mangaHomeDisplayType;
}
void setMangaHomeDisplayType(DisplayType displayType) {
final settings = isar.settings.getSync(227)!;
state = displayType;
isar.writeTxnSync(() {
isar.settings.putSync(settings..mangaHomeDisplayType = displayType);
});
}
}

View file

@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'state_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$mangaHomeDisplayTypeStateHash() =>
r'd59cd15db8c2884a77c72f5af9d659e0b07c0556';
/// See also [MangaHomeDisplayTypeState].
@ProviderFor(MangaHomeDisplayTypeState)
final mangaHomeDisplayTypeStateProvider = AutoDisposeNotifierProvider<
MangaHomeDisplayTypeState, DisplayType>.internal(
MangaHomeDisplayTypeState.new,
name: r'mangaHomeDisplayTypeStateProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$mangaHomeDisplayTypeStateHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$MangaHomeDisplayTypeState = AutoDisposeNotifier<DisplayType>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View file

@ -32,7 +32,7 @@ class BottomTextWidget extends StatelessWidget {
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.w600,
color: textColor ?? context.primaryColor,
color: textColor ?? context.textColor,
),
maxLines: isTorrent! ? 8 : maxLines,
overflow: TextOverflow.ellipsis,

View file

@ -20,13 +20,14 @@ import 'package:mangayomi/modules/widgets/cover_view_widget.dart';
class MangaImageCardWidget extends ConsumerWidget {
final Source source;
final bool isManga;
final bool isComfortableGrid;
final MManga? getMangaDetail;
const MangaImageCardWidget(
{required this.source,
super.key,
required this.getMangaDetail,
required this.isComfortableGrid,
required this.isManga});
@override
@ -41,6 +42,12 @@ class MangaImageCardWidget extends ConsumerWidget {
builder: (context, snapshot) {
final hasData = snapshot.hasData && snapshot.data!.isNotEmpty;
return CoverViewWidget(
bottomTextWidget: BottomTextWidget(
maxLines: 1,
text: getMangaDetail!.name!,
isComfortableGrid: isComfortableGrid,
),
isComfortableGrid: isComfortableGrid,
image: hasData && snapshot.data!.first.customCoverImage != null
? MemoryImage(
snapshot.data!.first.customCoverImage as Uint8List)
@ -64,26 +71,145 @@ class MangaImageCardWidget extends ConsumerWidget {
},
children: [
Container(
color: hasData && snapshot.data!.first.favorite!
? Colors.black.withOpacity(0.6)
: null,
),
color: hasData && snapshot.data!.first.favorite!
? Colors.black.withOpacity(0.5)
: null),
if (hasData && snapshot.data!.first.favorite!)
Positioned(
top: 0,
left: 0,
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(Icons.collections_bookmark,
color: context.primaryColor),
)),
BottomTextWidget(
isTorrent: source.isTorrent, text: getMangaDetail!.name!)
top: 0,
left: 0,
child: Padding(
padding: const EdgeInsets.all(4),
child: Container(
decoration: BoxDecoration(
color: context.primaryColor,
borderRadius: BorderRadius.circular(5)),
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(Icons.collections_bookmark_outlined,
size: 16, color: context.dynamicWhiteBlackColor),
),
),
),
),
if (!isComfortableGrid)
BottomTextWidget(
isTorrent: source.isTorrent, text: getMangaDetail!.name!)
]);
});
}
}
class MangaImageCardListTileWidget extends ConsumerWidget {
final Source source;
final bool isManga;
final MManga? getMangaDetail;
const MangaImageCardListTileWidget(
{required this.source,
super.key,
required this.isManga,
required this.getMangaDetail});
@override
Widget build(BuildContext context, WidgetRef ref) {
return StreamBuilder(
stream: isar.mangas
.filter()
.langEqualTo(source.lang)
.nameEqualTo(getMangaDetail!.name)
.sourceEqualTo(source.name)
.watch(fireImmediately: true),
builder: (context, snapshot) {
final hasData = snapshot.hasData && snapshot.data!.isNotEmpty;
final image = hasData && snapshot.data!.first.customCoverImage != null
? MemoryImage(snapshot.data!.first.customCoverImage as Uint8List)
as ImageProvider
: CachedNetworkImageProvider(
toImgUrl(hasData
? snapshot.data!.first.customCoverFromTracker ??
snapshot.data!.first.imageUrl ??
""
: getMangaDetail!.imageUrl!),
headers: ref.watch(headersProvider(
source: source.name!, lang: source.lang!)),
);
return Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(0),
surfaceTintColor: Colors.transparent,
backgroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5)),
elevation: 0,
shadowColor: Colors.transparent),
onPressed: () {
pushToMangaReaderDetail(
context: context,
getManga: getMangaDetail!,
lang: source.lang!,
source: source.name!,
isManga: isManga);
},
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Stack(
children: [
Material(
borderRadius: BorderRadius.circular(5),
color: Colors.transparent,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Image(
height: 55,
width: 40,
fit: BoxFit.cover,
image: image),
),
Container(
height: 55,
width: 40,
color: hasData && snapshot.data!.first.favorite!
? Colors.black.withOpacity(0.5)
: null,
),
],
),
),
Expanded(
child: Text(
getMangaDetail!.name!,
maxLines: 2,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: context.textColor),
),
),
if (hasData && snapshot.data!.first.favorite!)
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: context.primaryColor,
borderRadius: BorderRadius.circular(5)),
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(Icons.collections_bookmark_outlined,
size: 16, color: context.dynamicWhiteBlackColor),
),
),
),
],
),
),
);
});
}
}
void pushToMangaReaderDetail(
{MManga? getManga,
required String lang,

View file

@ -1,5 +1,6 @@
import 'dart:io';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/foundation.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/source.dart';
@ -44,7 +45,7 @@ GoRouter router(RouterRef ref) {
return GoRouter(
observers: [BotToastNavigatorObserver()],
initialLocation: '/MangaLibrary',
debugLogDiagnostics: true,
debugLogDiagnostics: kDebugMode,
refreshListenable: router,
routes: router._routes,
);

View file

@ -23,7 +23,7 @@ extension BuildContextExtensions on BuildContext {
return Platform.isMacOS || Platform.isLinux || Platform.isWindows;
}
bool get isMbile {
bool get isMobile {
return Platform.isIOS || Platform.isAndroid;
}