mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-21 03:32:06 +00:00
option to hide certain UI elements + new backup version
This commit is contained in:
parent
84c82ba1ee
commit
478c0ba45c
25 changed files with 1743 additions and 703 deletions
|
|
@ -215,6 +215,9 @@
|
|||
"sync_confirm_download": "A full download will completely replace your current data with the remote one!",
|
||||
"dialog_confirm": "Confirm",
|
||||
"description": "Description",
|
||||
"hide_manga": "Hide some elements related to mangas.",
|
||||
"hide_anime": "Hide some elements related to animes.",
|
||||
"hide_novel": "Hide some elements related to (light) novels.",
|
||||
"full_screen_player": "Use Fullscreen",
|
||||
"full_screen_player_info": "Automatically use fullscreen when playing a video.",
|
||||
"episode_progress": "Progress: {n}",
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ part 'category.g.dart';
|
|||
class Category {
|
||||
Id? id;
|
||||
String? name;
|
||||
bool? forManga;
|
||||
@enumerated
|
||||
late ItemType forItemType;
|
||||
Category(
|
||||
{this.id = Isar.autoIncrement,
|
||||
required this.name,
|
||||
this.forManga = true,
|
||||
required this.forItemType});
|
||||
|
||||
Category.fromJson(Map<String, dynamic> json) {
|
||||
|
|
@ -20,6 +22,16 @@ class Category {
|
|||
forItemType = json['forItemType'];
|
||||
}
|
||||
|
||||
Category.fromJsonV1(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
name = json['name'];
|
||||
forItemType = json['forManga'] is bool
|
||||
? json['forManga'] == true
|
||||
? ItemType.manga
|
||||
: ItemType.anime
|
||||
: ItemType.manga;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'id': id, 'name': name, 'forItemType': forItemType};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,13 @@ const CategorySchema = CollectionSchema(
|
|||
type: IsarType.byte,
|
||||
enumMap: _CategoryforItemTypeEnumValueMap,
|
||||
),
|
||||
r'name': PropertySchema(
|
||||
r'forManga': PropertySchema(
|
||||
id: 1,
|
||||
name: r'forManga',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'name': PropertySchema(
|
||||
id: 2,
|
||||
name: r'name',
|
||||
type: IsarType.string,
|
||||
)
|
||||
|
|
@ -65,7 +70,8 @@ void _categorySerialize(
|
|||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
writer.writeByte(offsets[0], object.forItemType.index);
|
||||
writer.writeString(offsets[1], object.name);
|
||||
writer.writeBool(offsets[1], object.forManga);
|
||||
writer.writeString(offsets[2], object.name);
|
||||
}
|
||||
|
||||
Category _categoryDeserialize(
|
||||
|
|
@ -78,8 +84,9 @@ Category _categoryDeserialize(
|
|||
forItemType:
|
||||
_CategoryforItemTypeValueEnumMap[reader.readByteOrNull(offsets[0])] ??
|
||||
ItemType.manga,
|
||||
forManga: reader.readBoolOrNull(offsets[1]),
|
||||
id: id,
|
||||
name: reader.readStringOrNull(offsets[1]),
|
||||
name: reader.readStringOrNull(offsets[2]),
|
||||
);
|
||||
return object;
|
||||
}
|
||||
|
|
@ -95,6 +102,8 @@ P _categoryDeserializeProp<P>(
|
|||
return (_CategoryforItemTypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
ItemType.manga) as P;
|
||||
case 1:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 2:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
|
@ -255,6 +264,32 @@ extension CategoryQueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterFilterCondition> forMangaIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'forManga',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterFilterCondition> forMangaIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'forManga',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterFilterCondition> forMangaEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'forManga',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterFilterCondition> idIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
|
|
@ -489,6 +524,18 @@ extension CategoryQuerySortBy on QueryBuilder<Category, Category, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterSortBy> sortByForManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'forManga', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterSortBy> sortByForMangaDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'forManga', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterSortBy> sortByName() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'name', Sort.asc);
|
||||
|
|
@ -516,6 +563,18 @@ extension CategoryQuerySortThenBy
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterSortBy> thenByForManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'forManga', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterSortBy> thenByForMangaDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'forManga', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QAfterSortBy> thenById() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'id', Sort.asc);
|
||||
|
|
@ -549,6 +608,12 @@ extension CategoryQueryWhereDistinct
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QDistinct> distinctByForManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'forManga');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, Category, QDistinct> distinctByName(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
|
@ -571,6 +636,12 @@ extension CategoryQueryProperty
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, bool?, QQueryOperations> forMangaProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'forManga');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Category, String?, QQueryOperations> nameProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'name');
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ class History {
|
|||
|
||||
int? chapterId;
|
||||
|
||||
bool? isManga;
|
||||
|
||||
@enumerated
|
||||
late ItemType itemType;
|
||||
|
||||
|
|
@ -21,6 +23,7 @@ class History {
|
|||
|
||||
History({
|
||||
this.id = Isar.autoIncrement,
|
||||
this.isManga = true,
|
||||
required this.itemType,
|
||||
required this.chapterId,
|
||||
required this.mangaId,
|
||||
|
|
@ -35,6 +38,18 @@ class History {
|
|||
mangaId = json['mangaId'];
|
||||
}
|
||||
|
||||
History.fromJsonV1(Map<String, dynamic> json) {
|
||||
chapterId = json['chapterId'];
|
||||
date = json['date'];
|
||||
id = json['id'];
|
||||
itemType = json['isManga'] is bool
|
||||
? json['isManga'] == true
|
||||
? ItemType.manga
|
||||
: ItemType.anime
|
||||
: ItemType.manga;
|
||||
mangaId = json['mangaId'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'chapterId': chapterId,
|
||||
'date': date,
|
||||
|
|
|
|||
|
|
@ -27,14 +27,19 @@ const HistorySchema = CollectionSchema(
|
|||
name: r'date',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'itemType': PropertySchema(
|
||||
r'isManga': PropertySchema(
|
||||
id: 2,
|
||||
name: r'isManga',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'itemType': PropertySchema(
|
||||
id: 3,
|
||||
name: r'itemType',
|
||||
type: IsarType.byte,
|
||||
enumMap: _HistoryitemTypeEnumValueMap,
|
||||
),
|
||||
r'mangaId': PropertySchema(
|
||||
id: 3,
|
||||
id: 4,
|
||||
name: r'mangaId',
|
||||
type: IsarType.long,
|
||||
)
|
||||
|
|
@ -83,8 +88,9 @@ void _historySerialize(
|
|||
) {
|
||||
writer.writeLong(offsets[0], object.chapterId);
|
||||
writer.writeString(offsets[1], object.date);
|
||||
writer.writeByte(offsets[2], object.itemType.index);
|
||||
writer.writeLong(offsets[3], object.mangaId);
|
||||
writer.writeBool(offsets[2], object.isManga);
|
||||
writer.writeByte(offsets[3], object.itemType.index);
|
||||
writer.writeLong(offsets[4], object.mangaId);
|
||||
}
|
||||
|
||||
History _historyDeserialize(
|
||||
|
|
@ -97,9 +103,10 @@ History _historyDeserialize(
|
|||
chapterId: reader.readLongOrNull(offsets[0]),
|
||||
date: reader.readStringOrNull(offsets[1]),
|
||||
id: id,
|
||||
itemType: _HistoryitemTypeValueEnumMap[reader.readByteOrNull(offsets[2])] ??
|
||||
isManga: reader.readBoolOrNull(offsets[2]),
|
||||
itemType: _HistoryitemTypeValueEnumMap[reader.readByteOrNull(offsets[3])] ??
|
||||
ItemType.manga,
|
||||
mangaId: reader.readLongOrNull(offsets[3]),
|
||||
mangaId: reader.readLongOrNull(offsets[4]),
|
||||
);
|
||||
return object;
|
||||
}
|
||||
|
|
@ -116,9 +123,11 @@ P _historyDeserializeProp<P>(
|
|||
case 1:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 2:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 3:
|
||||
return (_HistoryitemTypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
ItemType.manga) as P;
|
||||
case 3:
|
||||
case 4:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
|
@ -509,6 +518,32 @@ extension HistoryQueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterFilterCondition> isMangaIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'isManga',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterFilterCondition> isMangaIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'isManga',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterFilterCondition> isMangaEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'isManga',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterFilterCondition> itemTypeEqualTo(
|
||||
ItemType value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
|
@ -676,6 +711,18 @@ extension HistoryQuerySortBy on QueryBuilder<History, History, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterSortBy> sortByIsManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterSortBy> sortByIsMangaDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterSortBy> sortByItemType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'itemType', Sort.asc);
|
||||
|
|
@ -739,6 +786,18 @@ extension HistoryQuerySortThenBy
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterSortBy> thenByIsManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterSortBy> thenByIsMangaDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QAfterSortBy> thenByItemType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'itemType', Sort.asc);
|
||||
|
|
@ -779,6 +838,12 @@ extension HistoryQueryWhereDistinct
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QDistinct> distinctByIsManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'isManga');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, History, QDistinct> distinctByItemType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'itemType');
|
||||
|
|
@ -812,6 +877,12 @@ extension HistoryQueryProperty
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, bool?, QQueryOperations> isMangaProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'isManga');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<History, ItemType, QQueryOperations> itemTypeProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'itemType');
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ class Manga {
|
|||
@enumerated
|
||||
late Status status;
|
||||
|
||||
bool? isManga;
|
||||
|
||||
@enumerated
|
||||
late ItemType itemType;
|
||||
|
||||
|
|
@ -63,6 +65,7 @@ class Manga {
|
|||
required this.name,
|
||||
required this.status,
|
||||
required this.description,
|
||||
this.isManga = true,
|
||||
this.itemType = ItemType.manga,
|
||||
this.dateAdded,
|
||||
this.lastUpdate,
|
||||
|
|
@ -95,6 +98,33 @@ class Manga {
|
|||
customCoverFromTracker = json['customCoverFromTracker'];
|
||||
}
|
||||
|
||||
Manga.fromJsonV1(Map<String, dynamic> json) {
|
||||
author = json['author'];
|
||||
artist = json['artist'];
|
||||
categories = json['categories']?.cast<int>();
|
||||
customCoverImage = json['customCoverImage']?.cast<int>();
|
||||
dateAdded = json['dateAdded'];
|
||||
description = json['description'];
|
||||
favorite = json['favorite']!;
|
||||
genre = json['genre']?.cast<String>();
|
||||
id = json['id'];
|
||||
imageUrl = json['imageUrl'];
|
||||
isLocalArchive = json['isLocalArchive'];
|
||||
itemType = json['isManga'] is bool
|
||||
? json['isManga'] == true
|
||||
? ItemType.manga
|
||||
: ItemType.anime
|
||||
: ItemType.manga;
|
||||
lang = json['lang'];
|
||||
lastRead = json['lastRead'];
|
||||
lastUpdate = json['lastUpdate'];
|
||||
link = json['link'];
|
||||
name = json['name'];
|
||||
source = json['source'];
|
||||
status = Status.values[json['status']];
|
||||
customCoverFromTracker = json['customCoverFromTracker'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'author': author,
|
||||
'artist': artist,
|
||||
|
|
@ -128,8 +158,4 @@ enum Status {
|
|||
publishingFinished
|
||||
}
|
||||
|
||||
enum ItemType {
|
||||
manga,
|
||||
anime,
|
||||
novel
|
||||
}
|
||||
enum ItemType { manga, anime, novel }
|
||||
|
|
|
|||
|
|
@ -72,44 +72,49 @@ const MangaSchema = CollectionSchema(
|
|||
name: r'isLocalArchive',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'itemType': PropertySchema(
|
||||
r'isManga': PropertySchema(
|
||||
id: 11,
|
||||
name: r'isManga',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'itemType': PropertySchema(
|
||||
id: 12,
|
||||
name: r'itemType',
|
||||
type: IsarType.byte,
|
||||
enumMap: _MangaitemTypeEnumValueMap,
|
||||
),
|
||||
r'lang': PropertySchema(
|
||||
id: 12,
|
||||
id: 13,
|
||||
name: r'lang',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'lastRead': PropertySchema(
|
||||
id: 13,
|
||||
id: 14,
|
||||
name: r'lastRead',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'lastUpdate': PropertySchema(
|
||||
id: 14,
|
||||
id: 15,
|
||||
name: r'lastUpdate',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'link': PropertySchema(
|
||||
id: 15,
|
||||
id: 16,
|
||||
name: r'link',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'name': PropertySchema(
|
||||
id: 16,
|
||||
id: 17,
|
||||
name: r'name',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'source': PropertySchema(
|
||||
id: 17,
|
||||
id: 18,
|
||||
name: r'source',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'status': PropertySchema(
|
||||
id: 18,
|
||||
id: 19,
|
||||
name: r'status',
|
||||
type: IsarType.byte,
|
||||
enumMap: _MangastatusEnumValueMap,
|
||||
|
|
@ -241,14 +246,15 @@ void _mangaSerialize(
|
|||
writer.writeStringList(offsets[8], object.genre);
|
||||
writer.writeString(offsets[9], object.imageUrl);
|
||||
writer.writeBool(offsets[10], object.isLocalArchive);
|
||||
writer.writeByte(offsets[11], object.itemType.index);
|
||||
writer.writeString(offsets[12], object.lang);
|
||||
writer.writeLong(offsets[13], object.lastRead);
|
||||
writer.writeLong(offsets[14], object.lastUpdate);
|
||||
writer.writeString(offsets[15], object.link);
|
||||
writer.writeString(offsets[16], object.name);
|
||||
writer.writeString(offsets[17], object.source);
|
||||
writer.writeByte(offsets[18], object.status.index);
|
||||
writer.writeBool(offsets[11], object.isManga);
|
||||
writer.writeByte(offsets[12], object.itemType.index);
|
||||
writer.writeString(offsets[13], object.lang);
|
||||
writer.writeLong(offsets[14], object.lastRead);
|
||||
writer.writeLong(offsets[15], object.lastUpdate);
|
||||
writer.writeString(offsets[16], object.link);
|
||||
writer.writeString(offsets[17], object.name);
|
||||
writer.writeString(offsets[18], object.source);
|
||||
writer.writeByte(offsets[19], object.status.index);
|
||||
}
|
||||
|
||||
Manga _mangaDeserialize(
|
||||
|
|
@ -270,15 +276,16 @@ Manga _mangaDeserialize(
|
|||
id: id,
|
||||
imageUrl: reader.readStringOrNull(offsets[9]),
|
||||
isLocalArchive: reader.readBoolOrNull(offsets[10]),
|
||||
itemType: _MangaitemTypeValueEnumMap[reader.readByteOrNull(offsets[11])] ??
|
||||
isManga: reader.readBoolOrNull(offsets[11]),
|
||||
itemType: _MangaitemTypeValueEnumMap[reader.readByteOrNull(offsets[12])] ??
|
||||
ItemType.manga,
|
||||
lang: reader.readStringOrNull(offsets[12]),
|
||||
lastRead: reader.readLongOrNull(offsets[13]),
|
||||
lastUpdate: reader.readLongOrNull(offsets[14]),
|
||||
link: reader.readStringOrNull(offsets[15]),
|
||||
name: reader.readStringOrNull(offsets[16]),
|
||||
source: reader.readStringOrNull(offsets[17]),
|
||||
status: _MangastatusValueEnumMap[reader.readByteOrNull(offsets[18])] ??
|
||||
lang: reader.readStringOrNull(offsets[13]),
|
||||
lastRead: reader.readLongOrNull(offsets[14]),
|
||||
lastUpdate: reader.readLongOrNull(offsets[15]),
|
||||
link: reader.readStringOrNull(offsets[16]),
|
||||
name: reader.readStringOrNull(offsets[17]),
|
||||
source: reader.readStringOrNull(offsets[18]),
|
||||
status: _MangastatusValueEnumMap[reader.readByteOrNull(offsets[19])] ??
|
||||
Status.ongoing,
|
||||
);
|
||||
return object;
|
||||
|
|
@ -314,21 +321,23 @@ P _mangaDeserializeProp<P>(
|
|||
case 10:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 11:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 12:
|
||||
return (_MangaitemTypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
ItemType.manga) as P;
|
||||
case 12:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 13:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 14:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 15:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 16:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 17:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 18:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 19:
|
||||
return (_MangastatusValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
Status.ongoing) as P;
|
||||
default:
|
||||
|
|
@ -1924,6 +1933,32 @@ extension MangaQueryFilter on QueryBuilder<Manga, Manga, QFilterCondition> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterFilterCondition> isMangaIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'isManga',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterFilterCondition> isMangaIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'isManga',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterFilterCondition> isMangaEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'isManga',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterFilterCondition> itemTypeEqualTo(
|
||||
ItemType value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
|
@ -2903,6 +2938,18 @@ extension MangaQuerySortBy on QueryBuilder<Manga, Manga, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterSortBy> sortByIsManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterSortBy> sortByIsMangaDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterSortBy> sortByItemType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'itemType', Sort.asc);
|
||||
|
|
@ -3109,6 +3156,18 @@ extension MangaQuerySortThenBy on QueryBuilder<Manga, Manga, QSortThenBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterSortBy> thenByIsManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterSortBy> thenByIsMangaDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isManga', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QAfterSortBy> thenByItemType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'itemType', Sort.asc);
|
||||
|
|
@ -3279,6 +3338,12 @@ extension MangaQueryWhereDistinct on QueryBuilder<Manga, Manga, QDistinct> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QDistinct> distinctByIsManga() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'isManga');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, Manga, QDistinct> distinctByItemType() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'itemType');
|
||||
|
|
@ -3406,6 +3471,12 @@ extension MangaQueryProperty on QueryBuilder<Manga, Manga, QQueryProperty> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, bool?, QQueryOperations> isMangaProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'isManga');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Manga, ItemType, QQueryOperations> itemTypeProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'itemType');
|
||||
|
|
|
|||
|
|
@ -215,6 +215,12 @@ class Settings {
|
|||
@enumerated
|
||||
late DisplayType novelDisplayType;
|
||||
|
||||
bool? hideManga;
|
||||
|
||||
bool? hideAnime;
|
||||
|
||||
bool? hideNovel;
|
||||
|
||||
Settings(
|
||||
{this.id = 227,
|
||||
this.displayType = DisplayType.compactGrid,
|
||||
|
|
@ -309,7 +315,10 @@ class Settings {
|
|||
this.novelLibraryShowContinueReadingButton = false,
|
||||
this.novelLibraryLocalSource,
|
||||
this.sortLibraryNovel,
|
||||
this.novelDisplayType = DisplayType.comfortableGrid});
|
||||
this.novelDisplayType = DisplayType.comfortableGrid,
|
||||
this.hideManga = false,
|
||||
this.hideAnime = false,
|
||||
this.hideNovel = false});
|
||||
|
||||
Settings.fromJson(Map<String, dynamic> json) {
|
||||
animatePageTransitions = json['animatePageTransitions'];
|
||||
|
|
@ -479,6 +488,9 @@ class Settings {
|
|||
: null;
|
||||
novelDisplayType = DisplayType
|
||||
.values[json['novelDisplayType'] ?? DisplayType.compactGrid.index];
|
||||
hideManga = json['hideManga'];
|
||||
hideAnime = json['hideAnime'];
|
||||
hideNovel = json['hideNovel'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
@ -591,6 +603,9 @@ class Settings {
|
|||
'novelLibraryLocalSource': novelLibraryLocalSource,
|
||||
'sortLibraryNovel': sortLibraryNovel?.toJson(),
|
||||
'novelDisplayType': novelDisplayType.index,
|
||||
'hideManga': hideManga,
|
||||
'hideAnime': hideAnime,
|
||||
'hideNovel': hideNovel
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -125,6 +125,38 @@ class Source {
|
|||
SourceCodeLanguage.values[json['sourceCodeLanguage'] ?? 0];
|
||||
}
|
||||
|
||||
Source.fromJsonV1(Map<String, dynamic> json) {
|
||||
apiUrl = json['apiUrl'];
|
||||
appMinVerReq = json['appMinVerReq'];
|
||||
baseUrl = json['baseUrl'];
|
||||
dateFormat = json['dateFormat'];
|
||||
dateFormatLocale = json['dateFormatLocale'];
|
||||
hasCloudflare = json['hasCloudflare'];
|
||||
headers = json['headers'];
|
||||
iconUrl = json['iconUrl'];
|
||||
id = json['id'];
|
||||
isActive = json['isActive'];
|
||||
isAdded = json['isAdded'];
|
||||
isFullData = json['isFullData'];
|
||||
isManga = json['isManga'];
|
||||
itemType = isManga == true ? ItemType.manga : ItemType.anime;
|
||||
isNsfw = json['isNsfw'];
|
||||
isPinned = json['isPinned'];
|
||||
lang = json['lang'];
|
||||
lastUsed = json['lastUsed'];
|
||||
name = json['name'];
|
||||
sourceCode = json['sourceCode'];
|
||||
sourceCodeUrl = json['sourceCodeUrl'];
|
||||
typeSource = json['typeSource'];
|
||||
version = json['version'];
|
||||
versionLast = json['versionLast'];
|
||||
additionalParams = json['additionalParams'] ?? "";
|
||||
isObsolete = json['isObsolete'];
|
||||
isLocal = json['isLocal'];
|
||||
sourceCodeLanguage =
|
||||
SourceCodeLanguage.values[json['sourceCodeLanguage'] ?? 0];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'apiUrl': apiUrl,
|
||||
'appMinVerReq': appMinVerReq,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import 'package:mangayomi/models/chapter.dart';
|
|||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/history/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
|
|
@ -30,17 +31,20 @@ class HistoryScreen extends ConsumerStatefulWidget {
|
|||
class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
int tabs = 3;
|
||||
|
||||
void tabListener() {
|
||||
setState(() {
|
||||
_textEditingController.clear();
|
||||
_isSearch = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_tabBarController = TabController(length: 3, vsync: this);
|
||||
_tabBarController = TabController(length: tabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(() {
|
||||
setState(() {
|
||||
_textEditingController.clear();
|
||||
_isSearch = false;
|
||||
});
|
||||
});
|
||||
_tabBarController.addListener(tabListener);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
|
@ -49,10 +53,27 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
|||
List<History> entriesData = [];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int newTabs = 0;
|
||||
final hideManga = ref.watch(hideMangaStateProvider);
|
||||
final hideAnime = ref.watch(hideAnimeStateProvider);
|
||||
final hideNovel = ref.watch(hideNovelStateProvider);
|
||||
if (!hideManga) newTabs++;
|
||||
if (!hideAnime) newTabs++;
|
||||
if (!hideNovel) newTabs++;
|
||||
if (tabs != newTabs) {
|
||||
_tabBarController.removeListener(tabListener);
|
||||
_tabBarController.dispose();
|
||||
_tabBarController = TabController(length: newTabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(tabListener);
|
||||
setState(() {
|
||||
tabs = newTabs;
|
||||
});
|
||||
}
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return DefaultTabController(
|
||||
animationDuration: Duration.zero,
|
||||
length: 2,
|
||||
length: newTabs,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
|
|
@ -120,10 +141,16 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
|||
.idIsNotNull()
|
||||
.chapter((q) => q.manga((q) => q
|
||||
.itemTypeEqualTo(_tabBarController
|
||||
.index ==
|
||||
0
|
||||
.index ==
|
||||
0 &&
|
||||
!hideManga
|
||||
? ItemType.manga
|
||||
: _tabBarController.index == 1
|
||||
: _tabBarController.index ==
|
||||
1 -
|
||||
(hideManga
|
||||
? 1
|
||||
: 0) &&
|
||||
!hideAnime
|
||||
? ItemType.anime
|
||||
: ItemType.novel)))
|
||||
.findAllSync()
|
||||
|
|
@ -151,27 +178,30 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
|||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
controller: _tabBarController,
|
||||
tabs: [
|
||||
Tab(text: l10n.manga),
|
||||
Tab(text: l10n.anime),
|
||||
Tab(text: l10n.novel),
|
||||
if (!hideManga) Tab(text: l10n.manga),
|
||||
if (!hideAnime) Tab(text: l10n.anime),
|
||||
if (!hideNovel) Tab(text: l10n.novel),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: TabBarView(controller: _tabBarController, children: [
|
||||
HistoryTab(
|
||||
itemType: ItemType.manga,
|
||||
query: _textEditingController.text,
|
||||
),
|
||||
HistoryTab(
|
||||
itemType: ItemType.anime,
|
||||
query: _textEditingController.text,
|
||||
),
|
||||
HistoryTab(
|
||||
itemType: ItemType.novel,
|
||||
query: _textEditingController.text,
|
||||
)
|
||||
if (!hideManga)
|
||||
HistoryTab(
|
||||
itemType: ItemType.manga,
|
||||
query: _textEditingController.text,
|
||||
),
|
||||
if (!hideAnime)
|
||||
HistoryTab(
|
||||
itemType: ItemType.anime,
|
||||
query: _textEditingController.text,
|
||||
),
|
||||
if (!hideNovel)
|
||||
HistoryTab(
|
||||
itemType: ItemType.novel,
|
||||
query: _textEditingController.text,
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:isar/isar.dart';
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/update.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/modules/widgets/loading_icon.dart';
|
||||
import 'package:mangayomi/services/fetch_anime_sources.dart';
|
||||
import 'package:mangayomi/services/fetch_manga_sources.dart';
|
||||
|
|
@ -54,17 +55,34 @@ class MainScreen extends ConsumerWidget {
|
|||
final location = ref.watch(
|
||||
routerCurrentLocationStateProvider(context),
|
||||
);
|
||||
bool isReadingScreen =
|
||||
location == '/mangaReaderView' || location == '/animePlayerView' || location == '/novelReaderView';
|
||||
int currentIndex = switch (location) {
|
||||
null || '/MangaLibrary' => 0,
|
||||
'/AnimeLibrary' => 1,
|
||||
'/NovelLibrary' => 2,
|
||||
'/updates' => 3,
|
||||
'/history' => 4,
|
||||
'/browse' => 5,
|
||||
_ => 6,
|
||||
};
|
||||
final hideManga = ref.watch(hideMangaStateProvider);
|
||||
final hideAnime = ref.watch(hideAnimeStateProvider);
|
||||
final hideNovel = ref.watch(hideNovelStateProvider);
|
||||
bool isReadingScreen = location == '/mangaReaderView' ||
|
||||
location == '/animePlayerView' ||
|
||||
location == '/novelReaderView';
|
||||
final dest = [
|
||||
'/MangaLibrary',
|
||||
'/AnimeLibrary',
|
||||
'/NovelLibrary',
|
||||
'/updates',
|
||||
'/history',
|
||||
'/browse',
|
||||
'/more'
|
||||
];
|
||||
if (hideManga) {
|
||||
dest.removeWhere((d) => d == "/MangaLibrary");
|
||||
}
|
||||
if (hideAnime) {
|
||||
dest.removeWhere((d) => d == "/AnimeLibrary");
|
||||
}
|
||||
if (hideNovel) {
|
||||
dest.removeWhere((d) => d == "/NovelLibrary");
|
||||
}
|
||||
int currentIndex = dest.indexOf(location ?? "/more");
|
||||
if (currentIndex == -1) {
|
||||
currentIndex = dest.length - 1;
|
||||
}
|
||||
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
|
|
@ -134,38 +152,50 @@ class MainScreen extends ConsumerWidget {
|
|||
labelType: NavigationRailLabelType.all,
|
||||
useIndicator: true,
|
||||
destinations: [
|
||||
if (!hideManga)
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(
|
||||
Icons.collections_bookmark),
|
||||
icon: const Icon(Icons
|
||||
.collections_bookmark_outlined),
|
||||
label: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.manga))),
|
||||
if (!hideAnime)
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(
|
||||
Icons.video_collection),
|
||||
icon: const Icon(Icons
|
||||
.video_collection_outlined),
|
||||
label: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.anime))),
|
||||
if (!hideNovel)
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(
|
||||
Icons.local_library),
|
||||
icon: const Icon(
|
||||
Icons.local_library_outlined),
|
||||
label: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.novel))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(
|
||||
Icons.collections_bookmark),
|
||||
icon: const Icon(Icons
|
||||
.collections_bookmark_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.manga))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(
|
||||
Icons.video_collection),
|
||||
icon: const Icon(Icons
|
||||
.video_collection_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.anime))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(
|
||||
Icons.local_library),
|
||||
icon: const Icon(Icons
|
||||
.local_library_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.novel))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.new_releases),
|
||||
icon: const Icon(
|
||||
Icons.new_releases_outlined),
|
||||
selectedIcon: Badge(
|
||||
label: _updatesTotalNumbers(ref),
|
||||
child: const Icon(
|
||||
Icons.new_releases),
|
||||
),
|
||||
icon: Badge(
|
||||
label: _updatesTotalNumbers(ref),
|
||||
child: const Icon(
|
||||
Icons.new_releases_outlined),
|
||||
),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
|
|
@ -194,10 +224,19 @@ class MainScreen extends ConsumerWidget {
|
|||
top: 5),
|
||||
child: Text(l10n.history))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.explore),
|
||||
icon: const Icon(
|
||||
Icons.explore_outlined),
|
||||
selectedIcon: Badge(
|
||||
label:
|
||||
_extensionUpdateTotalNumbers(
|
||||
ref),
|
||||
child: const Icon(Icons.explore),
|
||||
),
|
||||
icon: Badge(
|
||||
label:
|
||||
_extensionUpdateTotalNumbers(
|
||||
ref),
|
||||
child: const Icon(
|
||||
Icons.explore_outlined),
|
||||
),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
|
|
@ -214,28 +253,34 @@ class MainScreen extends ConsumerWidget {
|
|||
],
|
||||
selectedIndex: currentIndex,
|
||||
onDestinationSelected: (newIndex) {
|
||||
final fn = switch (newIndex) {
|
||||
0 => route.go('/MangaLibrary'),
|
||||
1 => route.go('/AnimeLibrary'),
|
||||
2 => route.go('/NovelLibrary'),
|
||||
3 => route.go('/updates'),
|
||||
4 => route.go('/history'),
|
||||
5 => route.go('/browse'),
|
||||
_ => route.go('/more'),
|
||||
};
|
||||
fn;
|
||||
final dest = [
|
||||
'/MangaLibrary',
|
||||
'/AnimeLibrary',
|
||||
'/NovelLibrary',
|
||||
'/updates',
|
||||
'/history',
|
||||
'/browse',
|
||||
'/more'
|
||||
];
|
||||
if (hideManga) {
|
||||
dest.removeWhere(
|
||||
(d) => d == "/MangaLibrary");
|
||||
}
|
||||
if (hideAnime) {
|
||||
dest.removeWhere(
|
||||
(d) => d == "/AnimeLibrary");
|
||||
}
|
||||
if (hideNovel) {
|
||||
dest.removeWhere(
|
||||
(d) => d == "/NovelLibrary");
|
||||
}
|
||||
route.go(dest[newIndex >= dest.length
|
||||
? dest.length - 1
|
||||
: newIndex]);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
Positioned(
|
||||
right: 18,
|
||||
top: 140,
|
||||
child: _updatesTotalNumbers(ref)),
|
||||
Positioned(
|
||||
right: 18,
|
||||
top: 275,
|
||||
child: _extensionUpdateTotalNumbers(ref)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -273,70 +318,76 @@ class MainScreen extends ConsumerWidget {
|
|||
const Duration(milliseconds: 500),
|
||||
selectedIndex: currentIndex,
|
||||
destinations: [
|
||||
if (!hideManga)
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.collections_bookmark),
|
||||
icon: const Icon(
|
||||
Icons.collections_bookmark_outlined),
|
||||
label: l10n.manga),
|
||||
if (!hideAnime)
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.video_collection),
|
||||
icon: const Icon(
|
||||
Icons.video_collection_outlined),
|
||||
label: l10n.anime),
|
||||
if (!hideNovel)
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.local_library),
|
||||
icon: const Icon(
|
||||
Icons.local_library_outlined),
|
||||
label: l10n.novel),
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.collections_bookmark),
|
||||
icon: const Icon(
|
||||
Icons.collections_bookmark_outlined),
|
||||
label: l10n.manga),
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.video_collection),
|
||||
icon: const Icon(
|
||||
Icons.video_collection_outlined),
|
||||
label: l10n.anime),
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.local_library),
|
||||
icon: const Icon(
|
||||
Icons.local_library_outlined),
|
||||
label: l10n.novel),
|
||||
Stack(
|
||||
children: [
|
||||
NavigationDestination(
|
||||
selectedIcon:
|
||||
const Icon(Icons.new_releases),
|
||||
icon: const Icon(
|
||||
Icons.new_releases_outlined),
|
||||
label: l10n.updates),
|
||||
Positioned(
|
||||
right: 14,
|
||||
top: 3,
|
||||
child: _updatesTotalNumbers(ref)),
|
||||
],
|
||||
),
|
||||
selectedIcon: Badge(
|
||||
label: _updatesTotalNumbers(ref),
|
||||
child: const Icon(Icons.new_releases),
|
||||
),
|
||||
icon: Badge(
|
||||
label: _updatesTotalNumbers(ref),
|
||||
child: const Icon(Icons.new_releases),
|
||||
),
|
||||
label: l10n.updates),
|
||||
NavigationDestination(
|
||||
selectedIcon: const Icon(Icons.history),
|
||||
icon: const Icon(Icons.history_outlined),
|
||||
label: l10n.history),
|
||||
Stack(
|
||||
children: [
|
||||
NavigationDestination(
|
||||
selectedIcon: const Icon(Icons.explore),
|
||||
icon: const Icon(Icons.explore_outlined),
|
||||
label: l10n.browse),
|
||||
Positioned(
|
||||
right: 14,
|
||||
top: 3,
|
||||
child: _extensionUpdateTotalNumbers(ref)),
|
||||
],
|
||||
),
|
||||
NavigationDestination(
|
||||
selectedIcon: Badge(
|
||||
label: _extensionUpdateTotalNumbers(ref),
|
||||
child: const Icon(Icons.explore)),
|
||||
icon: Badge(
|
||||
label: _extensionUpdateTotalNumbers(ref),
|
||||
child: const Icon(Icons.explore)),
|
||||
label: l10n.browse),
|
||||
NavigationDestination(
|
||||
selectedIcon: const Icon(Icons.more_horiz),
|
||||
icon: const Icon(Icons.more_horiz_outlined),
|
||||
label: l10n.more),
|
||||
],
|
||||
onDestinationSelected: (newIndex) {
|
||||
final fn = switch (newIndex) {
|
||||
0 => route.go('/MangaLibrary'),
|
||||
1 => route.go('/AnimeLibrary'),
|
||||
2 => route.go('/NovelLibrary'),
|
||||
3 => route.go('/updates'),
|
||||
4 => route.go('/history'),
|
||||
5 => route.go('/browse'),
|
||||
_ => route.go('/more'),
|
||||
};
|
||||
fn;
|
||||
final dest = [
|
||||
'/MangaLibrary',
|
||||
'/AnimeLibrary',
|
||||
'/NovelLibrary',
|
||||
'/updates',
|
||||
'/history',
|
||||
'/browse',
|
||||
'/more'
|
||||
];
|
||||
if (hideManga) {
|
||||
dest.removeWhere((d) => d == "/MangaLibrary");
|
||||
}
|
||||
if (hideAnime) {
|
||||
dest.removeWhere((d) => d == "/AnimeLibrary");
|
||||
}
|
||||
if (hideNovel) {
|
||||
dest.removeWhere((d) => d == "/NovelLibrary");
|
||||
}
|
||||
route.go(dest[newIndex >= dest.length
|
||||
? dest.length - 1
|
||||
: newIndex]);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
@ -368,25 +419,9 @@ Widget _extensionUpdateTotalNumbers(WidgetRef ref) {
|
|||
.where((element) =>
|
||||
compareVersions(element.version!, element.versionLast!) < 0)
|
||||
.toList();
|
||||
return entries.isEmpty
|
||||
? Container()
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: const Color.fromARGB(255, 176, 46, 37)),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
|
||||
child: Text(
|
||||
entries.length.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
),
|
||||
),
|
||||
);
|
||||
return entries.isEmpty ? Text("0") : Text("${entries.length}");
|
||||
}
|
||||
return Container();
|
||||
return Text("0");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -401,24 +436,8 @@ Widget _updatesTotalNumbers(WidgetRef ref) {
|
|||
}
|
||||
return !(element.chapter.value?.isRead ?? false);
|
||||
}).toList();
|
||||
return entries.isEmpty
|
||||
? Container()
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: const Color.fromARGB(255, 176, 46, 37)),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
|
||||
child: Text(
|
||||
entries.length.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
),
|
||||
),
|
||||
);
|
||||
return entries.isEmpty ? Text("0") : Text("${entries.length}");
|
||||
}
|
||||
return Container();
|
||||
return Text("0");
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,7 +385,8 @@ List<String> _getList(BuildContext context) {
|
|||
l10n.tracking,
|
||||
l10n.history,
|
||||
l10n.settings,
|
||||
l10n.extensions
|
||||
l10n.extensions,
|
||||
l10n.updates
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import 'package:mangayomi/models/settings.dart';
|
|||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/models/track.dart';
|
||||
import 'package:mangayomi/models/track_preference.dart';
|
||||
import 'package:mangayomi/models/update.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
|
@ -28,7 +29,7 @@ void doBackUp(Ref ref,
|
|||
required String path,
|
||||
required BuildContext? context}) {
|
||||
Map<String, dynamic> datas = {};
|
||||
datas.addAll({"version": "1"});
|
||||
datas.addAll({"version": "2"});
|
||||
if (list.contains(0)) {
|
||||
final res = isar.mangas
|
||||
.filter()
|
||||
|
|
@ -116,6 +117,15 @@ void doBackUp(Ref ref,
|
|||
.toList();
|
||||
datas.addAll({"extensions_preferences": resSourePref});
|
||||
}
|
||||
if (list.contains(7)) {
|
||||
final res = isar.updates
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.findAllSync()
|
||||
.map((e) => e.toJson())
|
||||
.toList();
|
||||
datas.addAll({"updates": res});
|
||||
}
|
||||
final regExp = RegExp(r'[^a-zA-Z0-9 .()\-\s]');
|
||||
final name =
|
||||
'mangayomi_${DateTime.now().toString().replaceAll(regExp, '_').replaceAll(' ', '_')}';
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'backup.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$doBackUpHash() => r'1082dfee2a9c9e5655a04d027fde40c29d634a6d';
|
||||
String _$doBackUpHash() => r'98c1eb56bd4937033c82accf71beb84c85a2acc6';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -32,143 +32,274 @@ void doRestore(Ref ref, {required String path, required BuildContext context}) {
|
|||
final backup = jsonDecode(utf8.decode(archive.files.first.content))
|
||||
as Map<String, dynamic>;
|
||||
if (backup['version'] == "1") {
|
||||
try {
|
||||
final manga =
|
||||
(backup["manga"] as List?)?.map((e) => Manga.fromJson(e)).toList();
|
||||
final chapters = (backup["chapters"] as List?)
|
||||
?.map((e) => Chapter.fromJson(e))
|
||||
.toList();
|
||||
final categories = (backup["categories"] as List?)
|
||||
?.map((e) => Category.fromJson(e))
|
||||
.toList();
|
||||
final track =
|
||||
(backup["tracks"] as List?)?.map((e) => Track.fromJson(e)).toList();
|
||||
final trackPreferences = (backup["trackPreferences"] as List?)
|
||||
?.map((e) => TrackPreference.fromJson(e))
|
||||
.toList();
|
||||
final history = (backup["history"] as List?)
|
||||
?.map((e) => History.fromJson(e))
|
||||
.toList();
|
||||
final downloads = (backup["downloads"] as List?)
|
||||
?.map((e) => Download.fromJson(e))
|
||||
.toList();
|
||||
final settings = (backup["settings"] as List?)
|
||||
?.map((e) => Settings.fromJson(e))
|
||||
.toList();
|
||||
final extensions = (backup["extensions"] as List?)
|
||||
?.map((e) => Source.fromJson(e))
|
||||
.toList();
|
||||
final extensionsPref = (backup["extensions_preferences"] as List?)
|
||||
?.map((e) => SourcePreference.fromJson(e))
|
||||
.toList();
|
||||
final updates =
|
||||
(backup["updates"] as List?)?.map((e) => Update.fromJson(e)).toList();
|
||||
restoreV1(ref, backup);
|
||||
} else if (backup['version'] == "2") {
|
||||
restoreV2(ref, backup);
|
||||
}
|
||||
BotToast.showNotification(
|
||||
animationDuration: const Duration(milliseconds: 200),
|
||||
animationReverseDuration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(seconds: 5),
|
||||
backButtonBehavior: BackButtonBehavior.none,
|
||||
leading: (_) => Image.asset('assets/app_icons/icon-red.png', height: 40),
|
||||
title: (_) => const Text(
|
||||
"Backup restored!",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
enableSlideOff: true,
|
||||
onlyOne: true,
|
||||
crossPage: true);
|
||||
}
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.clearSync();
|
||||
if (manga != null) {
|
||||
isar.mangas.putAllSync(manga);
|
||||
if (chapters != null) {
|
||||
isar.chapters.clearSync();
|
||||
for (var chapter in chapters) {
|
||||
final manga = isar.mangas.getSync(chapter.mangaId!);
|
||||
if (manga != null) {
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
@riverpod
|
||||
void restoreV1(Ref ref, Map<String, dynamic> backup) {
|
||||
try {
|
||||
final manga =
|
||||
(backup["manga"] as List?)?.map((e) => Manga.fromJsonV1(e)).toList();
|
||||
final chapters =
|
||||
(backup["chapters"] as List?)?.map((e) => Chapter.fromJson(e)).toList();
|
||||
final categories = (backup["categories"] as List?)
|
||||
?.map((e) => Category.fromJsonV1(e))
|
||||
.toList();
|
||||
final track =
|
||||
(backup["tracks"] as List?)?.map((e) => Track.fromJson(e)).toList();
|
||||
final trackPreferences = (backup["trackPreferences"] as List?)
|
||||
?.map((e) => TrackPreference.fromJson(e))
|
||||
.toList();
|
||||
final history = (backup["history"] as List?)
|
||||
?.map((e) => History.fromJsonV1(e))
|
||||
.toList();
|
||||
final downloads = (backup["downloads"] as List?)
|
||||
?.map((e) => Download.fromJson(e))
|
||||
.toList();
|
||||
final settings = (backup["settings"] as List?)
|
||||
?.map((e) => Settings.fromJson(e))
|
||||
.toList();
|
||||
final extensions = (backup["extensions"] as List?)
|
||||
?.map((e) => Source.fromJsonV1(e))
|
||||
.toList();
|
||||
final extensionsPref = (backup["extensions_preferences"] as List?)
|
||||
?.map((e) => SourcePreference.fromJson(e))
|
||||
.toList();
|
||||
final updates =
|
||||
(backup["updates"] as List?)?.map((e) => Update.fromJson(e)).toList();
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.clearSync();
|
||||
if (manga != null) {
|
||||
isar.mangas.putAllSync(manga);
|
||||
if (chapters != null) {
|
||||
isar.chapters.clearSync();
|
||||
for (var chapter in chapters) {
|
||||
final manga = isar.mangas.getSync(chapter.mangaId!);
|
||||
if (manga != null) {
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
}
|
||||
|
||||
isar.downloads.clearSync();
|
||||
if (downloads != null) {
|
||||
for (var download in downloads) {
|
||||
final chapter = isar.chapters.getSync(download.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.downloads.putSync(download..chapter.value = chapter);
|
||||
download.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.historys.clearSync();
|
||||
if (history != null) {
|
||||
for (var element in history) {
|
||||
final chapter = isar.chapters.getSync(element.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.historys.putSync(element..chapter.value = chapter);
|
||||
element.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.updates.clearSync();
|
||||
if (updates != null) {
|
||||
final tempChapters =
|
||||
isar.chapters.filter().idIsNotNull().findAllSync().toList();
|
||||
for (var update in updates) {
|
||||
final matchingChapter = tempChapters
|
||||
.where((chapter) =>
|
||||
chapter.mangaId == update.mangaId &&
|
||||
chapter.name == update.chapterName)
|
||||
.firstOrNull;
|
||||
if (matchingChapter != null) {
|
||||
isar.updates.putSync(update..chapter.value = matchingChapter);
|
||||
update.chapter.saveSync();
|
||||
}
|
||||
isar.downloads.clearSync();
|
||||
if (downloads != null) {
|
||||
for (var download in downloads) {
|
||||
final chapter = isar.chapters.getSync(download.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.downloads.putSync(download..chapter.value = chapter);
|
||||
download.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.categorys.clearSync();
|
||||
if (categories != null) {
|
||||
isar.categorys.putAllSync(categories);
|
||||
isar.historys.clearSync();
|
||||
if (history != null) {
|
||||
for (var element in history) {
|
||||
final chapter = isar.chapters.getSync(element.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.historys.putSync(element..chapter.value = chapter);
|
||||
element.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.updates.clearSync();
|
||||
if (updates != null) {
|
||||
final tempChapters =
|
||||
isar.chapters.filter().idIsNotNull().findAllSync().toList();
|
||||
for (var update in updates) {
|
||||
final matchingChapter = tempChapters
|
||||
.where((chapter) =>
|
||||
chapter.mangaId == update.mangaId &&
|
||||
chapter.name == update.chapterName)
|
||||
.firstOrNull;
|
||||
if (matchingChapter != null) {
|
||||
isar.updates.putSync(update..chapter.value = matchingChapter);
|
||||
update.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.tracks.clearSync();
|
||||
if (track != null) {
|
||||
isar.tracks.putAllSync(track);
|
||||
isar.categorys.clearSync();
|
||||
if (categories != null) {
|
||||
isar.categorys.putAllSync(categories);
|
||||
}
|
||||
}
|
||||
|
||||
isar.trackPreferences.clearSync();
|
||||
if (trackPreferences != null) {
|
||||
isar.trackPreferences.putAllSync(trackPreferences);
|
||||
}
|
||||
isar.tracks.clearSync();
|
||||
if (track != null) {
|
||||
isar.tracks.putAllSync(track);
|
||||
}
|
||||
|
||||
isar.sources.clearSync();
|
||||
if (extensions != null) {
|
||||
isar.sources.putAllSync(extensions);
|
||||
}
|
||||
isar.trackPreferences.clearSync();
|
||||
if (trackPreferences != null) {
|
||||
isar.trackPreferences.putAllSync(trackPreferences);
|
||||
}
|
||||
|
||||
isar.sourcePreferences.clearSync();
|
||||
if (extensionsPref != null) {
|
||||
isar.sourcePreferences.putAllSync(extensionsPref);
|
||||
}
|
||||
isar.settings.clearSync();
|
||||
if (settings != null) {
|
||||
isar.settings.putAllSync(settings);
|
||||
}
|
||||
ref.invalidate(themeModeStateProvider);
|
||||
ref.invalidate(blendLevelStateProvider);
|
||||
ref.invalidate(flexSchemeColorStateProvider);
|
||||
ref.invalidate(pureBlackDarkModeStateProvider);
|
||||
ref.invalidate(l10nLocaleStateProvider);
|
||||
});
|
||||
} catch (e) {
|
||||
botToast(e.toString());
|
||||
}
|
||||
BotToast.showNotification(
|
||||
animationDuration: const Duration(milliseconds: 200),
|
||||
animationReverseDuration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(seconds: 5),
|
||||
backButtonBehavior: BackButtonBehavior.none,
|
||||
leading: (_) =>
|
||||
Image.asset('assets/app_icons/icon-red.png', height: 40),
|
||||
title: (_) => const Text(
|
||||
"Backup restored!",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
enableSlideOff: true,
|
||||
onlyOne: true,
|
||||
crossPage: true);
|
||||
isar.sources.clearSync();
|
||||
if (extensions != null) {
|
||||
isar.sources.putAllSync(extensions);
|
||||
}
|
||||
|
||||
isar.sourcePreferences.clearSync();
|
||||
if (extensionsPref != null) {
|
||||
isar.sourcePreferences.putAllSync(extensionsPref);
|
||||
}
|
||||
isar.settings.clearSync();
|
||||
if (settings != null) {
|
||||
isar.settings.putAllSync(settings);
|
||||
}
|
||||
ref.invalidate(themeModeStateProvider);
|
||||
ref.invalidate(blendLevelStateProvider);
|
||||
ref.invalidate(flexSchemeColorStateProvider);
|
||||
ref.invalidate(pureBlackDarkModeStateProvider);
|
||||
ref.invalidate(l10nLocaleStateProvider);
|
||||
});
|
||||
} catch (e) {
|
||||
botToast(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
void restoreV2(Ref ref, Map<String, dynamic> backup) {
|
||||
try {
|
||||
final manga =
|
||||
(backup["manga"] as List?)?.map((e) => Manga.fromJson(e)).toList();
|
||||
final chapters =
|
||||
(backup["chapters"] as List?)?.map((e) => Chapter.fromJson(e)).toList();
|
||||
final categories = (backup["categories"] as List?)
|
||||
?.map((e) => Category.fromJson(e))
|
||||
.toList();
|
||||
final track =
|
||||
(backup["tracks"] as List?)?.map((e) => Track.fromJson(e)).toList();
|
||||
final trackPreferences = (backup["trackPreferences"] as List?)
|
||||
?.map((e) => TrackPreference.fromJson(e))
|
||||
.toList();
|
||||
final history =
|
||||
(backup["history"] as List?)?.map((e) => History.fromJson(e)).toList();
|
||||
final downloads = (backup["downloads"] as List?)
|
||||
?.map((e) => Download.fromJson(e))
|
||||
.toList();
|
||||
final settings = (backup["settings"] as List?)
|
||||
?.map((e) => Settings.fromJson(e))
|
||||
.toList();
|
||||
final extensions = (backup["extensions"] as List?)
|
||||
?.map((e) => Source.fromJson(e))
|
||||
.toList();
|
||||
final extensionsPref = (backup["extensions_preferences"] as List?)
|
||||
?.map((e) => SourcePreference.fromJson(e))
|
||||
.toList();
|
||||
final updates =
|
||||
(backup["updates"] as List?)?.map((e) => Update.fromJson(e)).toList();
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.clearSync();
|
||||
if (manga != null) {
|
||||
isar.mangas.putAllSync(manga);
|
||||
if (chapters != null) {
|
||||
isar.chapters.clearSync();
|
||||
for (var chapter in chapters) {
|
||||
final manga = isar.mangas.getSync(chapter.mangaId!);
|
||||
if (manga != null) {
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
}
|
||||
|
||||
isar.downloads.clearSync();
|
||||
if (downloads != null) {
|
||||
for (var download in downloads) {
|
||||
final chapter = isar.chapters.getSync(download.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.downloads.putSync(download..chapter.value = chapter);
|
||||
download.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.historys.clearSync();
|
||||
if (history != null) {
|
||||
for (var element in history) {
|
||||
final chapter = isar.chapters.getSync(element.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.historys.putSync(element..chapter.value = chapter);
|
||||
element.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.updates.clearSync();
|
||||
if (updates != null) {
|
||||
final tempChapters =
|
||||
isar.chapters.filter().idIsNotNull().findAllSync().toList();
|
||||
for (var update in updates) {
|
||||
final matchingChapter = tempChapters
|
||||
.where((chapter) =>
|
||||
chapter.mangaId == update.mangaId &&
|
||||
chapter.name == update.chapterName)
|
||||
.firstOrNull;
|
||||
if (matchingChapter != null) {
|
||||
isar.updates.putSync(update..chapter.value = matchingChapter);
|
||||
update.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.categorys.clearSync();
|
||||
if (categories != null) {
|
||||
isar.categorys.putAllSync(categories);
|
||||
}
|
||||
}
|
||||
|
||||
isar.tracks.clearSync();
|
||||
if (track != null) {
|
||||
isar.tracks.putAllSync(track);
|
||||
}
|
||||
|
||||
isar.trackPreferences.clearSync();
|
||||
if (trackPreferences != null) {
|
||||
isar.trackPreferences.putAllSync(trackPreferences);
|
||||
}
|
||||
|
||||
isar.sources.clearSync();
|
||||
if (extensions != null) {
|
||||
isar.sources.putAllSync(extensions);
|
||||
}
|
||||
|
||||
isar.sourcePreferences.clearSync();
|
||||
if (extensionsPref != null) {
|
||||
isar.sourcePreferences.putAllSync(extensionsPref);
|
||||
}
|
||||
isar.settings.clearSync();
|
||||
if (settings != null) {
|
||||
isar.settings.putAllSync(settings);
|
||||
}
|
||||
ref.invalidate(themeModeStateProvider);
|
||||
ref.invalidate(blendLevelStateProvider);
|
||||
ref.invalidate(flexSchemeColorStateProvider);
|
||||
ref.invalidate(pureBlackDarkModeStateProvider);
|
||||
ref.invalidate(l10nLocaleStateProvider);
|
||||
});
|
||||
} catch (e) {
|
||||
botToast(e.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'restore.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$doRestoreHash() => r'15a02b8de4cc4c7f5185a9f645b734a75f5950ca';
|
||||
String _$doRestoreHash() => r'508725e75a03ac5f561c2cf8bf4943052d605d5b';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -172,5 +172,263 @@ class _DoRestoreProviderElement extends AutoDisposeProviderElement<void>
|
|||
@override
|
||||
BuildContext get context => (origin as DoRestoreProvider).context;
|
||||
}
|
||||
|
||||
String _$restoreV1Hash() => r'4dca1ac4cec79fdc78bec4d71367e77caf696f17';
|
||||
|
||||
/// See also [restoreV1].
|
||||
@ProviderFor(restoreV1)
|
||||
const restoreV1Provider = RestoreV1Family();
|
||||
|
||||
/// See also [restoreV1].
|
||||
class RestoreV1Family extends Family<void> {
|
||||
/// See also [restoreV1].
|
||||
const RestoreV1Family();
|
||||
|
||||
/// See also [restoreV1].
|
||||
RestoreV1Provider call(
|
||||
Map<String, dynamic> backup,
|
||||
) {
|
||||
return RestoreV1Provider(
|
||||
backup,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
RestoreV1Provider getProviderOverride(
|
||||
covariant RestoreV1Provider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.backup,
|
||||
);
|
||||
}
|
||||
|
||||
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'restoreV1Provider';
|
||||
}
|
||||
|
||||
/// See also [restoreV1].
|
||||
class RestoreV1Provider extends AutoDisposeProvider<void> {
|
||||
/// See also [restoreV1].
|
||||
RestoreV1Provider(
|
||||
Map<String, dynamic> backup,
|
||||
) : this._internal(
|
||||
(ref) => restoreV1(
|
||||
ref as RestoreV1Ref,
|
||||
backup,
|
||||
),
|
||||
from: restoreV1Provider,
|
||||
name: r'restoreV1Provider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$restoreV1Hash,
|
||||
dependencies: RestoreV1Family._dependencies,
|
||||
allTransitiveDependencies: RestoreV1Family._allTransitiveDependencies,
|
||||
backup: backup,
|
||||
);
|
||||
|
||||
RestoreV1Provider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.backup,
|
||||
}) : super.internal();
|
||||
|
||||
final Map<String, dynamic> backup;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
void Function(RestoreV1Ref provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: RestoreV1Provider._internal(
|
||||
(ref) => create(ref as RestoreV1Ref),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
backup: backup,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeProviderElement<void> createElement() {
|
||||
return _RestoreV1ProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is RestoreV1Provider && other.backup == backup;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, backup.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin RestoreV1Ref on AutoDisposeProviderRef<void> {
|
||||
/// The parameter `backup` of this provider.
|
||||
Map<String, dynamic> get backup;
|
||||
}
|
||||
|
||||
class _RestoreV1ProviderElement extends AutoDisposeProviderElement<void>
|
||||
with RestoreV1Ref {
|
||||
_RestoreV1ProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> get backup => (origin as RestoreV1Provider).backup;
|
||||
}
|
||||
|
||||
String _$restoreV2Hash() => r'fbdd1978f8be7512277620e351b9a0eee1827bfc';
|
||||
|
||||
/// See also [restoreV2].
|
||||
@ProviderFor(restoreV2)
|
||||
const restoreV2Provider = RestoreV2Family();
|
||||
|
||||
/// See also [restoreV2].
|
||||
class RestoreV2Family extends Family<void> {
|
||||
/// See also [restoreV2].
|
||||
const RestoreV2Family();
|
||||
|
||||
/// See also [restoreV2].
|
||||
RestoreV2Provider call(
|
||||
Map<String, dynamic> backup,
|
||||
) {
|
||||
return RestoreV2Provider(
|
||||
backup,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
RestoreV2Provider getProviderOverride(
|
||||
covariant RestoreV2Provider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.backup,
|
||||
);
|
||||
}
|
||||
|
||||
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'restoreV2Provider';
|
||||
}
|
||||
|
||||
/// See also [restoreV2].
|
||||
class RestoreV2Provider extends AutoDisposeProvider<void> {
|
||||
/// See also [restoreV2].
|
||||
RestoreV2Provider(
|
||||
Map<String, dynamic> backup,
|
||||
) : this._internal(
|
||||
(ref) => restoreV2(
|
||||
ref as RestoreV2Ref,
|
||||
backup,
|
||||
),
|
||||
from: restoreV2Provider,
|
||||
name: r'restoreV2Provider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$restoreV2Hash,
|
||||
dependencies: RestoreV2Family._dependencies,
|
||||
allTransitiveDependencies: RestoreV2Family._allTransitiveDependencies,
|
||||
backup: backup,
|
||||
);
|
||||
|
||||
RestoreV2Provider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.backup,
|
||||
}) : super.internal();
|
||||
|
||||
final Map<String, dynamic> backup;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
void Function(RestoreV2Ref provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: RestoreV2Provider._internal(
|
||||
(ref) => create(ref as RestoreV2Ref),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
backup: backup,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeProviderElement<void> createElement() {
|
||||
return _RestoreV2ProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is RestoreV2Provider && other.backup == backup;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, backup.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin RestoreV2Ref on AutoDisposeProviderRef<void> {
|
||||
/// The parameter `backup` of this provider.
|
||||
Map<String, dynamic> get backup;
|
||||
}
|
||||
|
||||
class _RestoreV2ProviderElement extends AutoDisposeProviderElement<void>
|
||||
with RestoreV2Ref {
|
||||
_RestoreV2ProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> get backup => (origin as RestoreV2Provider).backup;
|
||||
}
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:mangayomi/models/category.dart';
|
|||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/more/categories/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/modules/more/categories/widgets/custom_textfield.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
|
||||
|
|
@ -19,9 +20,10 @@ class CategoriesScreen extends ConsumerStatefulWidget {
|
|||
class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
int tabs = 3;
|
||||
@override
|
||||
void initState() {
|
||||
_tabBarController = TabController(length: 3, vsync: this);
|
||||
_tabBarController = TabController(length: tabs, vsync: this);
|
||||
_tabBarController.animateTo(widget.data.$2);
|
||||
|
||||
super.initState();
|
||||
|
|
@ -29,10 +31,25 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int newTabs = 0;
|
||||
final hideManga = ref.watch(hideMangaStateProvider);
|
||||
final hideAnime = ref.watch(hideAnimeStateProvider);
|
||||
final hideNovel = ref.watch(hideNovelStateProvider);
|
||||
if (!hideManga) newTabs++;
|
||||
if (!hideAnime) newTabs++;
|
||||
if (!hideNovel) newTabs++;
|
||||
if (tabs != newTabs) {
|
||||
_tabBarController.dispose();
|
||||
_tabBarController = TabController(length: newTabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
setState(() {
|
||||
tabs = newTabs;
|
||||
});
|
||||
}
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return DefaultTabController(
|
||||
animationDuration: Duration.zero,
|
||||
length: 2,
|
||||
length: newTabs,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
|
|
@ -45,22 +62,25 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
|
|||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
controller: _tabBarController,
|
||||
tabs: [
|
||||
Tab(text: l10n.manga),
|
||||
Tab(text: l10n.anime),
|
||||
Tab(text: l10n.novel),
|
||||
if (!hideManga) Tab(text: l10n.manga),
|
||||
if (!hideAnime) Tab(text: l10n.anime),
|
||||
if (!hideNovel) Tab(text: l10n.novel),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: TabBarView(controller: _tabBarController, children: const [
|
||||
CategoriesTab(
|
||||
itemType: ItemType.manga,
|
||||
),
|
||||
CategoriesTab(
|
||||
itemType: ItemType.anime,
|
||||
),
|
||||
CategoriesTab(
|
||||
itemType: ItemType.novel,
|
||||
)
|
||||
body: TabBarView(controller: _tabBarController, children: [
|
||||
if (!hideManga)
|
||||
CategoriesTab(
|
||||
itemType: ItemType.manga,
|
||||
),
|
||||
if (!hideAnime)
|
||||
CategoriesTab(
|
||||
itemType: ItemType.anime,
|
||||
),
|
||||
if (!hideNovel)
|
||||
CategoriesTab(
|
||||
itemType: ItemType.novel,
|
||||
)
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/modules/more/settings/player/providers/player_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:numberpicker/numberpicker.dart';
|
||||
|
|
@ -20,6 +21,7 @@ class PlayerScreen extends ConsumerWidget {
|
|||
final enableAutoSkip = ref.watch(enableAutoSkipStateProvider);
|
||||
final aniSkipTimeoutLength = ref.watch(aniSkipTimeoutLengthStateProvider);
|
||||
final useLibass = ref.watch(useLibassStateProvider);
|
||||
final hideAnime = ref.watch(hideAnimeStateProvider);
|
||||
final fullScreenPlayer = ref.watch(fullScreenPlayerStateProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -28,6 +30,12 @@ class PlayerScreen extends ConsumerWidget {
|
|||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
SwitchListTile(
|
||||
value: hideAnime,
|
||||
title: Text(context.l10n.hide_anime),
|
||||
onChanged: (value) {
|
||||
ref.read(hideAnimeStateProvider.notifier).set(value);
|
||||
}),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
final values = [100, 95, 90, 85, 80, 75, 70];
|
||||
|
|
|
|||
|
|
@ -137,3 +137,48 @@ class FullScreenReaderState extends _$FullScreenReaderState {
|
|||
() => isar.settings.putSync(settings!..fullScreenReader = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class HideMangaState extends _$HideMangaState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.hideManga ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..hideManga = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class HideAnimeState extends _$HideAnimeState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.hideAnime ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..hideAnime = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class HideNovelState extends _$HideNovelState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.hideNovel ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..hideNovel = value));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,5 +157,53 @@ final fullScreenReaderStateProvider =
|
|||
);
|
||||
|
||||
typedef _$FullScreenReaderState = AutoDisposeNotifier<bool>;
|
||||
String _$hideMangaStateHash() => r'fd24207581798fd1634ff6df2c85b8895053d14c';
|
||||
|
||||
/// See also [HideMangaState].
|
||||
@ProviderFor(HideMangaState)
|
||||
final hideMangaStateProvider =
|
||||
AutoDisposeNotifierProvider<HideMangaState, bool>.internal(
|
||||
HideMangaState.new,
|
||||
name: r'hideMangaStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$hideMangaStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$HideMangaState = AutoDisposeNotifier<bool>;
|
||||
String _$hideAnimeStateHash() => r'3e8748d9312b9ea84364959b7de17fed2204d303';
|
||||
|
||||
/// See also [HideAnimeState].
|
||||
@ProviderFor(HideAnimeState)
|
||||
final hideAnimeStateProvider =
|
||||
AutoDisposeNotifierProvider<HideAnimeState, bool>.internal(
|
||||
HideAnimeState.new,
|
||||
name: r'hideAnimeStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$hideAnimeStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$HideAnimeState = AutoDisposeNotifier<bool>;
|
||||
String _$hideNovelStateHash() => r'697efab85819783a7c1982797927feb397770191';
|
||||
|
||||
/// See also [HideNovelState].
|
||||
@ProviderFor(HideNovelState)
|
||||
final hideNovelStateProvider =
|
||||
AutoDisposeNotifierProvider<HideNovelState, bool>.internal(
|
||||
HideNovelState.new,
|
||||
name: r'hideNovelStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$hideNovelStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$HideNovelState = AutoDisposeNotifier<bool>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class ReaderScreen extends ConsumerWidget {
|
|||
final backgroundColor = ref.watch(backgroundColorStateProvider);
|
||||
final usePageTapZones = ref.watch(usePageTapZonesStateProvider);
|
||||
final fullScreenReader = ref.watch(fullScreenReaderStateProvider);
|
||||
final hideManga = ref.watch(hideMangaStateProvider);
|
||||
final hideNovel = ref.watch(hideNovelStateProvider);
|
||||
final cropBorders = ref.watch(cropBordersStateProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -328,6 +330,18 @@ class ReaderScreen extends ConsumerWidget {
|
|||
style: TextStyle(fontSize: 11, color: context.secondaryColor),
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: hideManga,
|
||||
title: Text(context.l10n.hide_manga),
|
||||
onChanged: (value) {
|
||||
ref.read(hideMangaStateProvider.notifier).set(value);
|
||||
}),
|
||||
SwitchListTile(
|
||||
value: hideNovel,
|
||||
title: Text(context.l10n.hide_novel),
|
||||
onChanged: (value) {
|
||||
ref.read(hideNovelStateProvider.notifier).set(value);
|
||||
}),
|
||||
SwitchListTile(
|
||||
value: fullScreenReader,
|
||||
title: Text(context.l10n.fullscreen),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'package:mangayomi/models/update.dart';
|
|||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/update_manga_detail_providers.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/modules/updates/widgets/update_chapter_list_tile_widget.dart';
|
||||
import 'package:mangayomi/modules/history/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
|
|
@ -31,6 +32,7 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
bool _isLoading = false;
|
||||
int tabs = 3;
|
||||
Future<void> _updateLibrary() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
|
|
@ -70,16 +72,18 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
});
|
||||
}
|
||||
|
||||
void tabListener() {
|
||||
setState(() {
|
||||
_textEditingController.clear();
|
||||
_isSearch = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_tabBarController = TabController(length: 3, vsync: this);
|
||||
_tabBarController = TabController(length: tabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(() {
|
||||
setState(() {
|
||||
_textEditingController.clear();
|
||||
_isSearch = false;
|
||||
});
|
||||
});
|
||||
_tabBarController.addListener(tabListener);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
|
@ -88,10 +92,27 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
List<History> entriesData = [];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int newTabs = 0;
|
||||
final hideManga = ref.watch(hideMangaStateProvider);
|
||||
final hideAnime = ref.watch(hideAnimeStateProvider);
|
||||
final hideNovel = ref.watch(hideNovelStateProvider);
|
||||
if (!hideManga) newTabs++;
|
||||
if (!hideAnime) newTabs++;
|
||||
if (!hideNovel) newTabs++;
|
||||
if (tabs != newTabs) {
|
||||
_tabBarController.removeListener(tabListener);
|
||||
_tabBarController.dispose();
|
||||
_tabBarController = TabController(length: newTabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(tabListener);
|
||||
setState(() {
|
||||
tabs = newTabs;
|
||||
});
|
||||
}
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return DefaultTabController(
|
||||
animationDuration: Duration.zero,
|
||||
length: 2,
|
||||
length: newTabs,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
|
|
@ -166,10 +187,16 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
.idIsNotNull()
|
||||
.chapter((q) => q.manga((q) => q
|
||||
.itemTypeEqualTo(_tabBarController
|
||||
.index ==
|
||||
0
|
||||
.index ==
|
||||
0 &&
|
||||
!hideManga
|
||||
? ItemType.manga
|
||||
: _tabBarController.index == 1
|
||||
: _tabBarController.index ==
|
||||
1 -
|
||||
(hideManga
|
||||
? 1
|
||||
: 0) &&
|
||||
!hideAnime
|
||||
? ItemType.anime
|
||||
: ItemType.novel)))
|
||||
.findAllSync()
|
||||
|
|
@ -197,27 +224,30 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
controller: _tabBarController,
|
||||
tabs: [
|
||||
Tab(text: l10n.manga),
|
||||
Tab(text: l10n.anime),
|
||||
Tab(text: l10n.novel),
|
||||
if (!hideManga) Tab(text: l10n.manga),
|
||||
if (!hideAnime) Tab(text: l10n.anime),
|
||||
if (!hideNovel) Tab(text: l10n.novel),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: TabBarView(controller: _tabBarController, children: [
|
||||
UpdateTab(
|
||||
itemType: ItemType.manga,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading),
|
||||
UpdateTab(
|
||||
itemType: ItemType.anime,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading),
|
||||
UpdateTab(
|
||||
itemType: ItemType.novel,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading)
|
||||
if (!hideManga)
|
||||
UpdateTab(
|
||||
itemType: ItemType.manga,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading),
|
||||
if (!hideAnime)
|
||||
UpdateTab(
|
||||
itemType: ItemType.anime,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading),
|
||||
if (!hideNovel)
|
||||
UpdateTab(
|
||||
itemType: ItemType.novel,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading)
|
||||
]),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'package:mangayomi/models/chapter.dart';
|
|||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/modules/more/backup_and_restore/providers/restore.dart';
|
||||
import 'package:mangayomi/modules/more/settings/sync/models/jwt.dart';
|
||||
import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart';
|
||||
import 'package:mangayomi/modules/more/settings/appearance/providers/blend_level_state_provider.dart';
|
||||
|
|
@ -195,113 +196,9 @@ class SyncServer extends _$SyncServer {
|
|||
|
||||
void _restore(Map<String, dynamic> backup) {
|
||||
if (backup['version'] == "1") {
|
||||
try {
|
||||
final manga =
|
||||
(backup["manga"] as List?)?.map((e) => Manga.fromJson(e)).toList();
|
||||
final chapters = (backup["chapters"] as List?)
|
||||
?.map((e) => Chapter.fromJson(e))
|
||||
.toList();
|
||||
final categories = (backup["categories"] as List?)
|
||||
?.map((e) => Category.fromJson(e))
|
||||
.toList();
|
||||
final track =
|
||||
(backup["tracks"] as List?)?.map((e) => Track.fromJson(e)).toList();
|
||||
final history = (backup["history"] as List?)
|
||||
?.map((e) => History.fromJson(e))
|
||||
.toList();
|
||||
final settings = (backup["settings"] as List?)
|
||||
?.map((e) => Settings.fromJson(e))
|
||||
.toList();
|
||||
final extensions = (backup["extensions"] as List?)
|
||||
?.map((e) => Source.fromJson(e))
|
||||
.toList();
|
||||
final extensionsPref = (backup["extensions_preferences"] as List?)
|
||||
?.map((e) => SourcePreference.fromJson(e))
|
||||
.toList();
|
||||
final updates = (backup["updates"] as List?)
|
||||
?.map((e) => Update.fromJson(e))
|
||||
.toList();
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.clearSync();
|
||||
if (manga != null) {
|
||||
isar.mangas.putAllSync(manga);
|
||||
if (chapters != null) {
|
||||
isar.chapters.clearSync();
|
||||
for (var chapter in chapters) {
|
||||
final manga = isar.mangas.getSync(chapter.mangaId!);
|
||||
if (manga != null) {
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
}
|
||||
|
||||
isar.historys.clearSync();
|
||||
if (history != null) {
|
||||
for (var element in history) {
|
||||
final chapter = isar.chapters.getSync(element.chapterId!);
|
||||
if (chapter != null) {
|
||||
isar.historys.putSync(element..chapter.value = chapter);
|
||||
element.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.updates.clearSync();
|
||||
if (updates != null) {
|
||||
final tempChapters =
|
||||
isar.chapters.filter().idIsNotNull().findAllSync().toList();
|
||||
for (var update in updates) {
|
||||
final matchingChapter = tempChapters
|
||||
.where((chapter) =>
|
||||
chapter.mangaId == update.mangaId &&
|
||||
chapter.name == update.chapterName)
|
||||
.firstOrNull;
|
||||
if (matchingChapter != null) {
|
||||
isar.updates
|
||||
.putSync(update..chapter.value = matchingChapter);
|
||||
update.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isar.categorys.clearSync();
|
||||
if (categories != null) {
|
||||
isar.categorys.putAllSync(categories);
|
||||
}
|
||||
}
|
||||
|
||||
isar.tracks.clearSync();
|
||||
if (track != null) {
|
||||
isar.tracks.putAllSync(track);
|
||||
}
|
||||
|
||||
isar.sources.clearSync();
|
||||
if (extensions != null) {
|
||||
isar.sources.putAllSync(extensions);
|
||||
}
|
||||
|
||||
isar.sourcePreferences.clearSync();
|
||||
if (extensionsPref != null) {
|
||||
isar.sourcePreferences.putAllSync(extensionsPref);
|
||||
}
|
||||
isar.settings.clearSync();
|
||||
if (settings != null) {
|
||||
isar.settings.putAllSync(settings);
|
||||
}
|
||||
if (isar.settings.getSync(227) == null) {
|
||||
isar.settings.putSync(Settings(id: 227));
|
||||
}
|
||||
ref.invalidate(themeModeStateProvider);
|
||||
ref.invalidate(blendLevelStateProvider);
|
||||
ref.invalidate(flexSchemeColorStateProvider);
|
||||
ref.invalidate(pureBlackDarkModeStateProvider);
|
||||
ref.invalidate(l10nLocaleStateProvider);
|
||||
});
|
||||
} catch (e) {
|
||||
botToast(e.toString(), second: 5);
|
||||
}
|
||||
ref.watch(restoreV1Provider(backup));
|
||||
} else if (backup['version'] == "2") {
|
||||
ref.watch(restoreV2Provider(backup));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'sync_server.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$syncServerHash() => r'db0f27093c2e76d4158b7af7960359c54c9a00b2';
|
||||
String _$syncServerHash() => r'4ef01cd50d1ec4eaecd971fe2f176d2650147df8';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
Loading…
Reference in a new issue