mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
migration to isar database step 1
This commit is contained in:
parent
752f6e6feb
commit
f0f1d3a6e2
51 changed files with 6813 additions and 1977 deletions
15
.metadata
15
.metadata
|
|
@ -15,21 +15,6 @@ migration:
|
|||
- platform: root
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
- platform: android
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
- platform: ios
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
- platform: linux
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
- platform: macos
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
- platform: web
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
- platform: windows
|
||||
create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
|
||||
|
|
|
|||
|
|
@ -5,51 +5,77 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/models/categories.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:mangayomi/models/manga_history.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/router/router.dart';
|
||||
import 'package:mangayomi/source/source_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/model/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/reader/providers/reader_controller_provider.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/providers/blend_level_state_provider.dart';
|
||||
import 'views/more/settings/appearance/providers/flex_scheme_color_state_provider.dart';
|
||||
import 'views/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
late Isar isar;
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
await Hive.initFlutter();
|
||||
} else {
|
||||
await Hive.initFlutter("Mangayomi/databases");
|
||||
}
|
||||
await FastCachedImageConfig.init();
|
||||
Hive.registerAdapter(ModelMangaAdapter());
|
||||
Hive.registerAdapter(MangaHistoryModelAdapter());
|
||||
await FastCachedImageConfig.init(subDir: "Mangayomi/databases");
|
||||
// Hive.registerAdapter(ModelMangaAdapter());
|
||||
// Hive.registerAdapter(MangaHistoryModelAdapter());
|
||||
Hive.registerAdapter(SourceModelAdapter());
|
||||
Hive.registerAdapter(ReaderModeAdapter());
|
||||
Hive.registerAdapter(TypeSourceAdapter());
|
||||
Hive.registerAdapter(DownloadModelAdapter());
|
||||
Hive.registerAdapter(ModelChaptersAdapter());
|
||||
Hive.registerAdapter(CategoriesModelAdapter());
|
||||
await Hive.openBox<ModelManga>(HiveConstant.hiveBoxManga);
|
||||
await Hive.openBox<MangaHistoryModel>(HiveConstant.hiveBoxMangaHistory);
|
||||
// Hive.registerAdapter(ModelChaptersAdapter());
|
||||
// Hive.registerAdapter(CategoriesModelAdapter());
|
||||
// await Hive.openBox<ModelManga>(HiveConstant.hiveBoxManga);
|
||||
// await Hive.openBox<MangaHistoryModel>(HiveConstant.hiveBoxMangaHistory);
|
||||
await Hive.openBox<ReaderMode>(HiveConstant.hiveBoxReaderMode);
|
||||
await Hive.openBox<SourceModel>(HiveConstant.hiveBoxMangaSource);
|
||||
await Hive.openBox<DownloadModel>(HiveConstant.hiveBoxDownloads);
|
||||
await Hive.openBox(HiveConstant.hiveBoxMangaInfo);
|
||||
// await Hive.openBox(HiveConstant.hiveBoxMangaInfo);
|
||||
await Hive.openBox(HiveConstant.hiveBoxMangaFilter);
|
||||
await Hive.openBox(HiveConstant.hiveBoxAppSettings);
|
||||
await Hive.openBox<CategoriesModel>(HiveConstant.hiveBoxCategories);
|
||||
await Hive.openBox(HiveConstant.hiveBoxMangaInfo);
|
||||
// await Hive.openBox<CategoriesModel>(HiveConstant.hiveBoxCategories);
|
||||
await initIsar();
|
||||
runApp(const ProviderScope(child: MyApp()));
|
||||
}
|
||||
|
||||
initIsar() async {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
isar = Isar.openSync(
|
||||
[ModelMangaSchema, ModelChaptersSchema, CategoriesModelSchema],
|
||||
directory: dir.path,
|
||||
);
|
||||
} else {
|
||||
String rootDir = path.join(Directory.current.path, '.dart_tool', 'isar');
|
||||
await Directory(rootDir).create(recursive: true); // something like this
|
||||
isar = await Isar.open(
|
||||
[ModelMangaSchema, ModelChaptersSchema, CategoriesModelSchema],
|
||||
directory: rootDir,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyApp extends ConsumerWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
// ref.read(isarDataProvider.notifier).set(isar);
|
||||
final isThemeLight = ref.watch(themeModeStateProvider);
|
||||
final blendLevel = ref.watch(blendLevelStateProvider);
|
||||
ThemeData themeLight = FlexThemeData.light(
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
part 'categories.g.dart';
|
||||
|
||||
@HiveType(typeId: 8)
|
||||
class CategoriesModel extends HiveObject {
|
||||
@HiveField(0)
|
||||
final int id;
|
||||
@HiveField(1)
|
||||
final String name;
|
||||
@collection
|
||||
@Name("Category")
|
||||
class CategoriesModel {
|
||||
Id? id;
|
||||
String? name;
|
||||
CategoriesModel({
|
||||
required this.id,
|
||||
this.id = Isar.autoIncrement,
|
||||
required this.name,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,42 +3,486 @@
|
|||
part of 'categories.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// IsarCollectionGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class CategoriesModelAdapter extends TypeAdapter<CategoriesModel> {
|
||||
@override
|
||||
final int typeId = 8;
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
||||
|
||||
@override
|
||||
CategoriesModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return CategoriesModel(
|
||||
id: fields[0] as int,
|
||||
name: fields[1] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, CategoriesModel obj) {
|
||||
writer
|
||||
..writeByte(2)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.name);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is CategoriesModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
extension GetCategoriesModelCollection on Isar {
|
||||
IsarCollection<CategoriesModel> get categoriesModels => this.collection();
|
||||
}
|
||||
|
||||
const CategoriesModelSchema = CollectionSchema(
|
||||
name: r'Category',
|
||||
id: 5751694338128944171,
|
||||
properties: {
|
||||
r'name': PropertySchema(
|
||||
id: 0,
|
||||
name: r'name',
|
||||
type: IsarType.string,
|
||||
)
|
||||
},
|
||||
estimateSize: _categoriesModelEstimateSize,
|
||||
serialize: _categoriesModelSerialize,
|
||||
deserialize: _categoriesModelDeserialize,
|
||||
deserializeProp: _categoriesModelDeserializeProp,
|
||||
idName: r'id',
|
||||
indexes: {},
|
||||
links: {},
|
||||
embeddedSchemas: {},
|
||||
getId: _categoriesModelGetId,
|
||||
getLinks: _categoriesModelGetLinks,
|
||||
attach: _categoriesModelAttach,
|
||||
version: '3.1.0+1',
|
||||
);
|
||||
|
||||
int _categoriesModelEstimateSize(
|
||||
CategoriesModel object,
|
||||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
var bytesCount = offsets.last;
|
||||
{
|
||||
final value = object.name;
|
||||
if (value != null) {
|
||||
bytesCount += 3 + value.length * 3;
|
||||
}
|
||||
}
|
||||
return bytesCount;
|
||||
}
|
||||
|
||||
void _categoriesModelSerialize(
|
||||
CategoriesModel object,
|
||||
IsarWriter writer,
|
||||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
writer.writeString(offsets[0], object.name);
|
||||
}
|
||||
|
||||
CategoriesModel _categoriesModelDeserialize(
|
||||
Id id,
|
||||
IsarReader reader,
|
||||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
final object = CategoriesModel(
|
||||
id: id,
|
||||
name: reader.readStringOrNull(offsets[0]),
|
||||
);
|
||||
return object;
|
||||
}
|
||||
|
||||
P _categoriesModelDeserializeProp<P>(
|
||||
IsarReader reader,
|
||||
int propertyId,
|
||||
int offset,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
switch (propertyId) {
|
||||
case 0:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
}
|
||||
}
|
||||
|
||||
Id _categoriesModelGetId(CategoriesModel object) {
|
||||
return object.id ?? Isar.autoIncrement;
|
||||
}
|
||||
|
||||
List<IsarLinkBase<dynamic>> _categoriesModelGetLinks(CategoriesModel object) {
|
||||
return [];
|
||||
}
|
||||
|
||||
void _categoriesModelAttach(
|
||||
IsarCollection<dynamic> col, Id id, CategoriesModel object) {
|
||||
object.id = id;
|
||||
}
|
||||
|
||||
extension CategoriesModelQueryWhereSort
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QWhere> {
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterWhere> anyId() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(const IdWhereClause.any());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension CategoriesModelQueryWhere
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QWhereClause> {
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterWhereClause> idEqualTo(
|
||||
Id id) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IdWhereClause.between(
|
||||
lower: id,
|
||||
upper: id,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterWhereClause>
|
||||
idNotEqualTo(Id id) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
if (query.whereSort == Sort.asc) {
|
||||
return query
|
||||
.addWhereClause(
|
||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
||||
)
|
||||
.addWhereClause(
|
||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
||||
);
|
||||
} else {
|
||||
return query
|
||||
.addWhereClause(
|
||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
||||
)
|
||||
.addWhereClause(
|
||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterWhereClause>
|
||||
idGreaterThan(Id id, {bool include = false}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(
|
||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterWhereClause> idLessThan(
|
||||
Id id,
|
||||
{bool include = false}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(
|
||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterWhereClause> idBetween(
|
||||
Id lowerId,
|
||||
Id upperId, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IdWhereClause.between(
|
||||
lower: lowerId,
|
||||
includeLower: includeLower,
|
||||
upper: upperId,
|
||||
includeUpper: includeUpper,
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension CategoriesModelQueryFilter
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QFilterCondition> {
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
idIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'id',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
idIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'id',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
idEqualTo(Id? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'id',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
idGreaterThan(
|
||||
Id? value, {
|
||||
bool include = false,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'id',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
idLessThan(
|
||||
Id? value, {
|
||||
bool include = false,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'id',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
idBetween(
|
||||
Id? lower,
|
||||
Id? upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'id',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'name',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'name',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameEqualTo(
|
||||
String? value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'name',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameGreaterThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'name',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameLessThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'name',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameBetween(
|
||||
String? lower,
|
||||
String? upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'name',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'name',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'name',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'name',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'name',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'name',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterFilterCondition>
|
||||
nameIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'name',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension CategoriesModelQueryObject
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QFilterCondition> {}
|
||||
|
||||
extension CategoriesModelQueryLinks
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QFilterCondition> {}
|
||||
|
||||
extension CategoriesModelQuerySortBy
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QSortBy> {
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterSortBy> sortByName() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'name', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterSortBy>
|
||||
sortByNameDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'name', Sort.desc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension CategoriesModelQuerySortThenBy
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QSortThenBy> {
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterSortBy> thenById() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'id', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterSortBy> thenByIdDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'id', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterSortBy> thenByName() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'name', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QAfterSortBy>
|
||||
thenByNameDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'name', Sort.desc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension CategoriesModelQueryWhereDistinct
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QDistinct> {
|
||||
QueryBuilder<CategoriesModel, CategoriesModel, QDistinct> distinctByName(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'name', caseSensitive: caseSensitive);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension CategoriesModelQueryProperty
|
||||
on QueryBuilder<CategoriesModel, CategoriesModel, QQueryProperty> {
|
||||
QueryBuilder<CategoriesModel, int, QQueryOperations> idProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'id');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<CategoriesModel, String?, QQueryOperations> nameProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'name');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
part 'manga_history.g.dart';
|
||||
// import 'package:hive/hive.dart';
|
||||
// import 'package:mangayomi/models/model_manga.dart';
|
||||
// part 'manga_history.g.dart';
|
||||
|
||||
@HiveType(typeId: 2)
|
||||
class MangaHistoryModel extends HiveObject {
|
||||
@HiveField(0)
|
||||
final ModelManga modelManga;
|
||||
@HiveField(1)
|
||||
final String date;
|
||||
MangaHistoryModel({required this.date, required this.modelManga});
|
||||
}
|
||||
// @HiveType(typeId: 2)
|
||||
// class MangaHistoryModel extends HiveObject {
|
||||
// @HiveField(0)
|
||||
// final ModelManga modelManga;
|
||||
// @HiveField(1)
|
||||
// final String date;
|
||||
// MangaHistoryModel({required this.date, required this.modelManga});
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'manga_history.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class MangaHistoryModelAdapter extends TypeAdapter<MangaHistoryModel> {
|
||||
@override
|
||||
final int typeId = 2;
|
||||
|
||||
@override
|
||||
MangaHistoryModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return MangaHistoryModel(
|
||||
date: fields[1] as String,
|
||||
modelManga: fields[0] as ModelManga,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, MangaHistoryModel obj) {
|
||||
writer
|
||||
..writeByte(2)
|
||||
..writeByte(0)
|
||||
..write(obj.modelManga)
|
||||
..writeByte(1)
|
||||
..write(obj.date);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is MangaHistoryModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
|
|
@ -1,97 +1,87 @@
|
|||
import 'package:hive/hive.dart';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
part 'model_manga.g.dart';
|
||||
|
||||
@HiveType(typeId: 0)
|
||||
class ModelManga extends HiveObject {
|
||||
@HiveField(0)
|
||||
@collection
|
||||
@Name("Manga")
|
||||
class ModelManga {
|
||||
Id? id;
|
||||
|
||||
String? name;
|
||||
|
||||
@HiveField(1)
|
||||
String? link;
|
||||
|
||||
@HiveField(2)
|
||||
String? imageUrl;
|
||||
|
||||
@HiveField(3)
|
||||
String? description;
|
||||
|
||||
@HiveField(4)
|
||||
String? author;
|
||||
|
||||
@HiveField(5)
|
||||
String? status;
|
||||
|
||||
@HiveField(6)
|
||||
List<String>? genre;
|
||||
|
||||
@HiveField(7)
|
||||
bool favorite;
|
||||
|
||||
@HiveField(8)
|
||||
String? source;
|
||||
|
||||
@HiveField(9)
|
||||
String? lang;
|
||||
|
||||
@HiveField(10)
|
||||
int? dateAdded;
|
||||
|
||||
@HiveField(11)
|
||||
int? lastUpdate;
|
||||
|
||||
@HiveField(12)
|
||||
List<ModelChapters>? chapters;
|
||||
|
||||
@HiveField(13)
|
||||
String? lastRead;
|
||||
|
||||
@HiveField(14)
|
||||
List<int>? categories;
|
||||
@Backlink(to: "manga")
|
||||
final chapters = IsarLinks<ModelChapters>();
|
||||
|
||||
ModelManga(
|
||||
{required this.source,
|
||||
required this.author,
|
||||
required this.favorite,
|
||||
required this.genre,
|
||||
required this.imageUrl,
|
||||
required this.lang,
|
||||
required this.link,
|
||||
required this.name,
|
||||
required this.status,
|
||||
required this.description,
|
||||
required this.dateAdded,
|
||||
required this.lastUpdate,
|
||||
required this.categories,
|
||||
required this.lastRead,
|
||||
required this.chapters});
|
||||
ModelManga({
|
||||
this.id = Isar.autoIncrement,
|
||||
required this.source,
|
||||
required this.author,
|
||||
required this.favorite,
|
||||
required this.genre,
|
||||
required this.imageUrl,
|
||||
required this.lang,
|
||||
required this.link,
|
||||
required this.name,
|
||||
required this.status,
|
||||
required this.description,
|
||||
required this.dateAdded,
|
||||
required this.lastUpdate,
|
||||
required this.categories,
|
||||
required this.lastRead,
|
||||
});
|
||||
}
|
||||
|
||||
@HiveType(typeId: 7)
|
||||
class ModelChapters extends HiveObject {
|
||||
@HiveField(0)
|
||||
@collection
|
||||
@Name("Chapters")
|
||||
class ModelChapters {
|
||||
Id? id;
|
||||
|
||||
int? mangaId;
|
||||
|
||||
String? name;
|
||||
|
||||
@HiveField(1)
|
||||
String? url;
|
||||
|
||||
@HiveField(2)
|
||||
String? dateUpload;
|
||||
|
||||
@HiveField(3)
|
||||
String? scanlator;
|
||||
|
||||
@HiveField(4)
|
||||
bool isBookmarked;
|
||||
bool? isBookmarked;
|
||||
|
||||
@HiveField(5)
|
||||
bool isRead;
|
||||
bool? isRead;
|
||||
|
||||
@HiveField(6)
|
||||
String lastPageRead;
|
||||
String? lastPageRead;
|
||||
|
||||
final manga = IsarLink<ModelManga>();
|
||||
|
||||
ModelChapters(
|
||||
{required this.name,
|
||||
{this.id = Isar.autoIncrement,
|
||||
required this.mangaId,
|
||||
required this.name,
|
||||
required this.url,
|
||||
required this.dateUpload,
|
||||
required this.isBookmarked,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,28 +1,30 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/models/categories.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:mangayomi/models/manga_history.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/source/source_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/model/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/reader/providers/reader_controller_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'hive_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
Box<ModelManga> hiveBoxManga(HiveBoxMangaRef ref) {
|
||||
return Hive.box<ModelManga>(HiveConstant.hiveBoxManga);
|
||||
}
|
||||
// @riverpod
|
||||
// Box<ModelManga> hiveBoxManga(HiveBoxMangaRef ref) {
|
||||
// return Hive.box<ModelManga>(HiveConstant.hiveBoxManga);
|
||||
// }
|
||||
|
||||
@riverpod
|
||||
Box hiveBoxMangaInfo(HiveBoxMangaInfoRef ref) {
|
||||
return Hive.box(HiveConstant.hiveBoxMangaInfo);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Box<MangaHistoryModel> hiveBoxMangaHistory(HiveBoxMangaHistoryRef ref) {
|
||||
return Hive.box<MangaHistoryModel>(HiveConstant.hiveBoxMangaHistory);
|
||||
}
|
||||
// @riverpod
|
||||
// Box<MangaHistoryModel> hiveBoxMangaHistory(HiveBoxMangaHistoryRef ref) {
|
||||
// return Hive.box<MangaHistoryModel>(HiveConstant.hiveBoxMangaHistory);
|
||||
// }
|
||||
|
||||
@riverpod
|
||||
Box<ReaderMode> hiveBoxReaderMode(HiveBoxReaderModeRef ref) {
|
||||
|
|
@ -53,3 +55,4 @@ Box hiveBoxSettings(HiveBoxSettingsRef ref) {
|
|||
Box<CategoriesModel> hiveBoxCategories(HiveBoxCategoriesRef ref) {
|
||||
return Hive.box(HiveConstant.hiveBoxCategories);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,20 +6,6 @@ part of 'hive_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$hiveBoxMangaHash() => r'63b8c649d7ac482b84fafa635626249294d4f92d';
|
||||
|
||||
/// See also [hiveBoxManga].
|
||||
@ProviderFor(hiveBoxManga)
|
||||
final hiveBoxMangaProvider = AutoDisposeProvider<Box<ModelManga>>.internal(
|
||||
hiveBoxManga,
|
||||
name: r'hiveBoxMangaProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$hiveBoxMangaHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef HiveBoxMangaRef = AutoDisposeProviderRef<Box<ModelManga>>;
|
||||
String _$hiveBoxMangaInfoHash() => r'638c65c996c731a9764acc5911f9b0ec75b60273';
|
||||
|
||||
/// See also [hiveBoxMangaInfo].
|
||||
|
|
@ -35,23 +21,6 @@ final hiveBoxMangaInfoProvider = AutoDisposeProvider<Box<dynamic>>.internal(
|
|||
);
|
||||
|
||||
typedef HiveBoxMangaInfoRef = AutoDisposeProviderRef<Box<dynamic>>;
|
||||
String _$hiveBoxMangaHistoryHash() =>
|
||||
r'dd5c7a3cd8bfceb7b577c56f5ef8755914416c1e';
|
||||
|
||||
/// See also [hiveBoxMangaHistory].
|
||||
@ProviderFor(hiveBoxMangaHistory)
|
||||
final hiveBoxMangaHistoryProvider =
|
||||
AutoDisposeProvider<Box<MangaHistoryModel>>.internal(
|
||||
hiveBoxMangaHistory,
|
||||
name: r'hiveBoxMangaHistoryProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$hiveBoxMangaHistoryHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef HiveBoxMangaHistoryRef = AutoDisposeProviderRef<Box<MangaHistoryModel>>;
|
||||
String _$hiveBoxReaderModeHash() => r'fabc2f9e6b46c1ba0f1965630ff91f0bdccfeb99';
|
||||
|
||||
/// See also [hiveBoxReaderMode].
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ class StorageProvider {
|
|||
|
||||
Future<Directory?> getMangaChapterDirectory(
|
||||
ModelManga modelManga, index) async {
|
||||
String scanlator = modelManga.chapters![index].scanlator!.isNotEmpty
|
||||
? "${modelManga.chapters![index].scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
String scanlator = modelManga.chapters.toList()[index].scanlator!.isNotEmpty
|
||||
? "${modelManga.chapters.toList()[index].scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
: "";
|
||||
final dir = await getDirectory();
|
||||
return Directory(
|
||||
"${dir!.path}/downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
"${dir!.path}/downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${modelManga.chapters.toList()[index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
}
|
||||
|
||||
Future<Directory?> getMangaMainDirectory(ModelManga modelManga, index) async {
|
||||
|
|
|
|||
|
|
@ -106,23 +106,19 @@ class AsyncRouterNotifier extends ChangeNotifier {
|
|||
GoRoute(
|
||||
path: '/manga-reader/detail',
|
||||
builder: (context, state) {
|
||||
ModelManga? model;
|
||||
|
||||
model = state.extra as ModelManga;
|
||||
int idManga = state.extra as int;
|
||||
|
||||
return MangaReaderDetail(
|
||||
modelManga: model,
|
||||
idManga: idManga,
|
||||
);
|
||||
},
|
||||
pageBuilder: (context, state) {
|
||||
ModelManga? model;
|
||||
|
||||
model = state.extra as ModelManga;
|
||||
int idManga = state.extra as int;
|
||||
|
||||
return CustomTransition(
|
||||
key: state.pageKey,
|
||||
child: MangaReaderDetail(
|
||||
modelManga: model,
|
||||
idManga: idManga,
|
||||
));
|
||||
}),
|
||||
GoRoute(
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
List<bool> isLocaleList = [];
|
||||
String source = modelManga.source!.toLowerCase();
|
||||
List pagesUrl = ref.watch(hiveBoxMangaInfoProvider).get(
|
||||
"${modelManga.lang}-${modelManga.source}/${modelManga.name}/${modelManga.chapters![index].name}-pageurl",
|
||||
"${modelManga.lang}-${modelManga.source}/${modelManga.name}/${modelManga.chapters.toList()[index].name}-pageurl",
|
||||
defaultValue: []);
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
path = await StorageProvider().getMangaChapterDirectory(modelManga, index);
|
||||
|
|
@ -98,7 +98,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
/********/
|
||||
else if (getWpMangTypeSource(source) == TypeSource.comick) {
|
||||
String mangaId =
|
||||
modelManga.chapters![index].url!.split('/').last.split('-').first;
|
||||
modelManga.chapters.toList()[index].url!.split('/').last.split('-').first;
|
||||
|
||||
final response = await httpGet(
|
||||
url: 'https://api.comick.fun/chapter/$mangaId?tachiyomi=true',
|
||||
|
|
@ -117,7 +117,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
else if (getWpMangTypeSource(source) == TypeSource.mangathemesia) {
|
||||
final dom = await httpGet(
|
||||
useUserAgent: true,
|
||||
url: modelManga.chapters![index].url!,
|
||||
url: modelManga.chapters.toList()[index].url!,
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
if (dom!.querySelectorAll('#readerarea').isNotEmpty) {
|
||||
|
|
@ -165,7 +165,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
|
||||
else if (source == 'mangakawaii') {
|
||||
final response = await httpGet(
|
||||
url: modelManga.chapters![index].url!,
|
||||
url: modelManga.chapters.toList()[index].url!,
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
var chapterSlug = RegExp("""var chapter_slug = "([^"]*)";""")
|
||||
|
|
@ -193,7 +193,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
else if (getWpMangTypeSource(source) == TypeSource.mmrcms) {
|
||||
final dom = await httpGet(
|
||||
useUserAgent: true,
|
||||
url: modelManga.chapters![index].url!,
|
||||
url: modelManga.chapters.toList()[index].url!,
|
||||
source: source,
|
||||
resDom: true) as Document?;
|
||||
if (dom!.querySelectorAll('#all > .img-responsive').isNotEmpty) {
|
||||
|
|
@ -242,7 +242,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
return secretKeyResultScript;
|
||||
}
|
||||
|
||||
var link = "http://www.mangahere.cc${modelManga.chapters![index].url!}";
|
||||
var link = "http://www.mangahere.cc${modelManga.chapters.toList()[index].url!}";
|
||||
final response =
|
||||
await httpGet(url: link, source: source, resDom: false) as String?;
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
} else if (source == 'japscan') {
|
||||
final response = await httpGet(
|
||||
useUserAgent: true,
|
||||
url: modelManga.chapters![index].url!,
|
||||
url: modelManga.chapters.toList()[index].url!,
|
||||
source: source,
|
||||
resDom: false) as String?;
|
||||
RegExp regex = RegExp(r'<script src="/zjs/(.*?)"');
|
||||
|
|
@ -349,7 +349,7 @@ Future<GetMangaChapterUrlModel> getMangaChapterUrl(
|
|||
if (urll.isNotEmpty) {
|
||||
if (!incognitoMode) {
|
||||
ref.watch(hiveBoxMangaInfoProvider).put(
|
||||
"${modelManga.lang}-${modelManga.source}/${modelManga.name}/${modelManga.chapters![index].name}-pageurl",
|
||||
"${modelManga.lang}-${modelManga.source}/${modelManga.name}/${modelManga.chapters.toList()[index].name}-pageurl",
|
||||
urll);
|
||||
}
|
||||
for (var i = 0; i < urll.length; i++) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ part of 'get_manga_chapter_url.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$getMangaChapterUrlHash() =>
|
||||
r'6b40f393d25504e820401a92e7b5387fd07ab973';
|
||||
r'30b846643d79dbe431155158f8a9568878e8ad57';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:http/http.dart' as http;
|
|||
import 'package:mangayomi/models/comick/manga_chapter_detail.dart';
|
||||
import 'package:mangayomi/models/comick/manga_detail_comick.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/services/get_popular_manga.dart';
|
||||
import 'package:mangayomi/services/http_service/http_res_to_dom_html.dart';
|
||||
import 'package:mangayomi/services/http_service/http_service.dart';
|
||||
|
|
@ -86,6 +87,7 @@ Future<GetMangaDetailModel> getMangaDetail(GetMangaDetailRef ref,
|
|||
String? description;
|
||||
List<ModelChapters> chapters = [];
|
||||
List<String> scanlators = [];
|
||||
|
||||
/********/
|
||||
/*comick*/
|
||||
/********/
|
||||
|
|
@ -669,7 +671,8 @@ Future<GetMangaDetailModel> getMangaDetail(GetMangaDetailRef ref,
|
|||
isBookmarked: false,
|
||||
scanlator: scanlators.isEmpty ? "" : scanlators[i],
|
||||
isRead: false,
|
||||
lastPageRead: ''));
|
||||
lastPageRead: '',
|
||||
mangaId: null));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'get_manga_detail.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$getMangaDetailHash() => r'ded3d41646d56c670699614c7ab01069ddc52b8d';
|
||||
String _$getMangaDetailHash() => r'8a6b3c3948b179e4614ce45e293d11e0faf9a3ba';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -151,14 +151,14 @@ List<SourceModel> sourcesList = [
|
|||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia,
|
||||
logoUrl: ''),
|
||||
SourceModel(
|
||||
sourceName: "ArenaScans",
|
||||
url: "https://arenascans.net",
|
||||
lang: "en",
|
||||
typeSource: TypeSource.mangathemesia,
|
||||
logoUrl:
|
||||
'https://arenascans.net/wp-content/uploads/2023/02/arena-logo-1.png',
|
||||
isCloudflare: true),
|
||||
// SourceModel(
|
||||
// sourceName: "ArenaScans",
|
||||
// url: "https://arenascans.net",
|
||||
// lang: "en",
|
||||
// typeSource: TypeSource.mangathemesia,
|
||||
// logoUrl:
|
||||
// 'https://arenascans.net/wp-content/uploads/2023/02/arena-logo-1.png',
|
||||
// isCloudflare: true),
|
||||
SourceModel(
|
||||
sourceName: "AzureScans",
|
||||
url: "https://azuremanga.com",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
class HiveConstant {
|
||||
static String get hiveBoxManga => "manga_box";
|
||||
static String get hiveBoxMangaInfo => "manga_box_info";
|
||||
static String get hiveBoxMangaHistory => "_manga_box_history_";
|
||||
static String get hiveBoxMangaSource => "_manga_box_source_";
|
||||
static String get hiveBoxMangaFilter => "_manga_box_filter_";
|
||||
static String get hiveBoxAppSettings => "_app_box_settings_";
|
||||
static String get hiveBoxDownloads => "_manga_box_downloads_";
|
||||
static String get hiveBoxReaderSettings => "_reader_box_settings_";
|
||||
static String get hiveBoxReaderMode => "_readerMode_box_settings_";
|
||||
static String get hiveBoxCategories => "_manga_box_categorie_";
|
||||
static String get hiveBoxManga => "manga_box_";
|
||||
static String get hiveBoxMangaInfo => "manga_box_info_";
|
||||
static String get hiveBoxMangaHistory => "_manga_box_history__";
|
||||
static String get hiveBoxMangaSource => "_manga_box_source__";
|
||||
static String get hiveBoxMangaFilter => "_manga_box_filter__";
|
||||
static String get hiveBoxAppSettings => "_app_box_settings__";
|
||||
static String get hiveBoxDownloads => "_manga_box_downloads___";
|
||||
static String get hiveBoxReaderSettings => "_reader_box_settings__";
|
||||
static String get hiveBoxReaderMode => "_readerMode_box_settings__";
|
||||
static String get hiveBoxCategories => "_manga_box_categorie__";
|
||||
}
|
||||
|
||||
const defaultUserAgent =
|
||||
|
|
|
|||
|
|
@ -193,7 +193,6 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
|||
lang: widget.lang,
|
||||
dateAdded: DateTime.now().microsecondsSinceEpoch,
|
||||
lastUpdate: DateTime.now().microsecondsSinceEpoch,
|
||||
chapters: data.chapters,
|
||||
categories: null,
|
||||
lastRead: '');
|
||||
if (mounted) {
|
||||
|
|
|
|||
|
|
@ -22,283 +22,288 @@ class HistoryScreen extends ConsumerStatefulWidget {
|
|||
class _HistoryScreenState extends ConsumerState<HistoryScreen> {
|
||||
final _textEditingController = TextEditingController();
|
||||
bool _isSearch = false;
|
||||
List<MangaHistoryModel> entriesData = [];
|
||||
List<MangaHistoryModel> entriesFilter = [];
|
||||
// List<MangaHistoryModel> entriesData = [];
|
||||
// List<MangaHistoryModel> entriesFilter = [];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
title: _isSearch
|
||||
? null
|
||||
: Text(
|
||||
'History',
|
||||
style: TextStyle(color: Theme.of(context).hintColor),
|
||||
),
|
||||
actions: [
|
||||
_isSearch
|
||||
? SeachFormTextField(
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
entriesFilter = entriesData
|
||||
.where((element) => element.modelManga.name!
|
||||
.toLowerCase()
|
||||
.contains(value.toLowerCase()))
|
||||
.toList();
|
||||
});
|
||||
},
|
||||
onSuffixPressed: () {
|
||||
_textEditingController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearch = false;
|
||||
});
|
||||
_textEditingController.clear();
|
||||
},
|
||||
controller: _textEditingController,
|
||||
)
|
||||
: IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearch = true;
|
||||
});
|
||||
},
|
||||
icon: Icon(Icons.search, color: Theme.of(context).hintColor)),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Remove everything",
|
||||
),
|
||||
content: const Text(
|
||||
'Are you sure? All history will be lost.'),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text("Cancel")),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.watch(hiveBoxMangaHistoryProvider)
|
||||
.clear();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text("Ok")),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
icon: Icon(Icons.delete_sweep_outlined,
|
||||
color: Theme.of(context).hintColor)),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: ValueListenableBuilder<Box<MangaHistoryModel>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaHistoryProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries = value.values.toList();
|
||||
entriesData = value.values.toList();
|
||||
final entriesHistory = _textEditingController.text.isNotEmpty
|
||||
? entriesFilter
|
||||
: entries;
|
||||
if (entries.isNotEmpty) {
|
||||
return GroupedListView<MangaHistoryModel, String>(
|
||||
elements: entriesHistory,
|
||||
groupBy: (element) => element.date.substring(0, 10),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(dateFormat(DateTime.parse(groupByValue))),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, MangaHistoryModel element) {
|
||||
return SizedBox(
|
||||
height: 105,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 60,
|
||||
height: 90,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.push('/manga-reader/detail',
|
||||
extra: element.modelManga);
|
||||
},
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: cachedNetworkImage(
|
||||
headers: headers(element.modelManga.source!),
|
||||
imageUrl: element.modelManga.imageUrl!,
|
||||
width: 60,
|
||||
height: 90,
|
||||
fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: ValueListenableBuilder<Box>(
|
||||
valueListenable: ref
|
||||
.watch(hiveBoxMangaInfoProvider)
|
||||
.listenable(),
|
||||
builder: (context, value, child) {
|
||||
final values = value.get(
|
||||
"${element.modelManga.lang}-${element.modelManga.source}/${element.modelManga.name}-chapter_index",
|
||||
defaultValue: '');
|
||||
if (values.isNotEmpty) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
pushMangaReaderView(
|
||||
context: context,
|
||||
modelManga: element.modelManga,
|
||||
index:
|
||||
int.parse(values.toString()));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
element.modelManga.name!,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight:
|
||||
FontWeight.bold),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Wrap(
|
||||
crossAxisAlignment:
|
||||
WrapCrossAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
element
|
||||
.modelManga
|
||||
.chapters![int.parse(
|
||||
values
|
||||
.toString())]
|
||||
.name!,
|
||||
style: const TextStyle(
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
const Text(' - '),
|
||||
Text(
|
||||
DateFormat.Hm().format(
|
||||
DateTime.parse(
|
||||
element.date)),
|
||||
style: const TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight:
|
||||
FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Remove",
|
||||
),
|
||||
content: const Text(
|
||||
'This will remove the read date of this chapter. Are you sure?'),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: const Text(
|
||||
"Cancel")),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.watch(
|
||||
hiveBoxMangaHistoryProvider)
|
||||
.delete(
|
||||
'${element.modelManga.lang}-${element.modelManga.link}');
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: const Text(
|
||||
"Remove")),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.delete_outline,
|
||||
size: 25,
|
||||
)),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.date.compareTo(item2.date),
|
||||
order: GroupedListOrder.DESC,
|
||||
);
|
||||
}
|
||||
return const Center(
|
||||
child: Text('Nothing read recently'),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
return Container();
|
||||
|
||||
|
||||
|
||||
|
||||
// Scaffold(
|
||||
// appBar: AppBar(
|
||||
// elevation: 0,
|
||||
// backgroundColor: Colors.transparent,
|
||||
// title: _isSearch
|
||||
// ? null
|
||||
// : Text(
|
||||
// 'History',
|
||||
// style: TextStyle(color: Theme.of(context).hintColor),
|
||||
// ),
|
||||
// actions: [
|
||||
// _isSearch
|
||||
// ? SeachFormTextField(
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
// entriesFilter = entriesData
|
||||
// .where((element) => element.modelManga.name!
|
||||
// .toLowerCase()
|
||||
// .contains(value.toLowerCase()))
|
||||
// .toList();
|
||||
// });
|
||||
// },
|
||||
// onSuffixPressed: () {
|
||||
// _textEditingController.clear();
|
||||
// setState(() {});
|
||||
// },
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _isSearch = false;
|
||||
// });
|
||||
// _textEditingController.clear();
|
||||
// },
|
||||
// controller: _textEditingController,
|
||||
// )
|
||||
// : IconButton(
|
||||
// splashRadius: 20,
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _isSearch = true;
|
||||
// });
|
||||
// },
|
||||
// icon: Icon(Icons.search, color: Theme.of(context).hintColor)),
|
||||
// IconButton(
|
||||
// splashRadius: 20,
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return AlertDialog(
|
||||
// title: const Text(
|
||||
// "Remove everything",
|
||||
// ),
|
||||
// content: const Text(
|
||||
// 'Are you sure? All history will be lost.'),
|
||||
// actions: [
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
// children: [
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// child: const Text("Cancel")),
|
||||
// const SizedBox(
|
||||
// width: 15,
|
||||
// ),
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// ref
|
||||
// .watch(hiveBoxMangaHistoryProvider)
|
||||
// .clear();
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// child: const Text("Ok")),
|
||||
// ],
|
||||
// )
|
||||
// ],
|
||||
// );
|
||||
// });
|
||||
// },
|
||||
// icon: Icon(Icons.delete_sweep_outlined,
|
||||
// color: Theme.of(context).hintColor)),
|
||||
// ],
|
||||
// ),
|
||||
// body: Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
// child: ValueListenableBuilder<Box<MangaHistoryModel>>(
|
||||
// valueListenable: ref.watch(hiveBoxMangaHistoryProvider).listenable(),
|
||||
// builder: (context, value, child) {
|
||||
// final entries = value.values.toList();
|
||||
// entriesData = value.values.toList();
|
||||
// final entriesHistory = _textEditingController.text.isNotEmpty
|
||||
// ? entriesFilter
|
||||
// : entries;
|
||||
// if (entries.isNotEmpty) {
|
||||
// return GroupedListView<MangaHistoryModel, String>(
|
||||
// elements: entriesHistory,
|
||||
// groupBy: (element) => element.date.substring(0, 10),
|
||||
// groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 8),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(dateFormat(DateTime.parse(groupByValue))),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// itemBuilder: (context, MangaHistoryModel element) {
|
||||
// return SizedBox(
|
||||
// height: 105,
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// width: 60,
|
||||
// height: 90,
|
||||
// child: GestureDetector(
|
||||
// onTap: () {
|
||||
// context.push('/manga-reader/detail',
|
||||
// extra: element.modelManga);
|
||||
// },
|
||||
// child: ClipRRect(
|
||||
// borderRadius: BorderRadius.circular(7),
|
||||
// child: cachedNetworkImage(
|
||||
// headers: headers(element.modelManga.source!),
|
||||
// imageUrl: element.modelManga.imageUrl!,
|
||||
// width: 60,
|
||||
// height: 90,
|
||||
// fit: BoxFit.cover),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Flexible(
|
||||
// child: ValueListenableBuilder<Box>(
|
||||
// valueListenable: ref
|
||||
// .watch(hiveBoxMangaInfoProvider)
|
||||
// .listenable(),
|
||||
// builder: (context, value, child) {
|
||||
// final values = value.get(
|
||||
// "${element.modelManga.lang}-${element.modelManga.source}/${element.modelManga.name}-chapter_index",
|
||||
// defaultValue: '');
|
||||
// if (values.isNotEmpty) {
|
||||
// return Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: GestureDetector(
|
||||
// onTap: () {
|
||||
// pushMangaReaderView(
|
||||
// context: context,
|
||||
// modelManga: element.modelManga,
|
||||
// index:
|
||||
// int.parse(values.toString()));
|
||||
// },
|
||||
// child: Container(
|
||||
// color: Colors.transparent,
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Column(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.center,
|
||||
// crossAxisAlignment:
|
||||
// CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// element.modelManga.name!,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 14,
|
||||
// fontWeight:
|
||||
// FontWeight.bold),
|
||||
// textAlign: TextAlign.start,
|
||||
// ),
|
||||
// Wrap(
|
||||
// crossAxisAlignment:
|
||||
// WrapCrossAlignment.end,
|
||||
// children: [
|
||||
// Text(
|
||||
// element
|
||||
// .modelManga.chapters
|
||||
// .toList()[int.parse(
|
||||
// values
|
||||
// .toString())]
|
||||
// .name!,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 11,
|
||||
// ),
|
||||
// ),
|
||||
// const Text(' - '),
|
||||
// Text(
|
||||
// DateFormat.Hm().format(
|
||||
// DateTime.parse(
|
||||
// element.date)),
|
||||
// style: const TextStyle(
|
||||
// fontSize: 11,
|
||||
// fontWeight:
|
||||
// FontWeight.w400),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return AlertDialog(
|
||||
// title: const Text(
|
||||
// "Remove",
|
||||
// ),
|
||||
// content: const Text(
|
||||
// 'This will remove the read date of this chapter. Are you sure?'),
|
||||
// actions: [
|
||||
// Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.end,
|
||||
// children: [
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// Navigator.pop(
|
||||
// context);
|
||||
// },
|
||||
// child: const Text(
|
||||
// "Cancel")),
|
||||
// const SizedBox(
|
||||
// width: 15,
|
||||
// ),
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// ref
|
||||
// .watch(
|
||||
// hiveBoxMangaHistoryProvider)
|
||||
// .delete(
|
||||
// '${element.modelManga.lang}-${element.modelManga.link}');
|
||||
// Navigator.pop(
|
||||
// context);
|
||||
// },
|
||||
// child: const Text(
|
||||
// "Remove")),
|
||||
// ],
|
||||
// )
|
||||
// ],
|
||||
// );
|
||||
// });
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.delete_outline,
|
||||
// size: 25,
|
||||
// )),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
// return Container();
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// itemComparator: (item1, item2) =>
|
||||
// item1.date.compareTo(item2.date),
|
||||
// order: GroupedListOrder.DESC,
|
||||
// );
|
||||
// }
|
||||
// return const Center(
|
||||
// child: Text('Nothing read recently'),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import 'package:draggable_menu/draggable_menu.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/categories.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
|
|
@ -45,12 +47,17 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
final isNotFiltering = ref
|
||||
.read(mangaFilterResultStateProvider(mangaList: entries).notifier)
|
||||
.isNotFiltering();
|
||||
return ValueListenableBuilder<Box<CategoriesModel>>(
|
||||
valueListenable: ref.watch(hiveBoxCategoriesProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entr = value.values.toList();
|
||||
if (entr.isNotEmpty && showCategoryTabs) {
|
||||
tabBarController = TabController(length: entr.length, vsync: this);
|
||||
return StreamBuilder(
|
||||
stream: isar.categoriesModels
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData &&
|
||||
snapshot.data!.isNotEmpty &&
|
||||
showCategoryTabs) {
|
||||
final entr = snapshot.data;
|
||||
tabBarController = TabController(length: entr!.length, vsync: this);
|
||||
tabBarController.animateTo(tabIndex);
|
||||
tabBarController.addListener(() {
|
||||
tabIndex = tabBarController.index;
|
||||
|
|
@ -73,35 +80,35 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
children: entr
|
||||
.map(
|
||||
(e) => Scaffold(
|
||||
body: ValueListenableBuilder<Box<ModelManga>>(
|
||||
valueListenable: ref
|
||||
.watch(hiveBoxMangaProvider)
|
||||
.listenable(),
|
||||
builder: (context, value, child) {
|
||||
entries = value.values
|
||||
.where((element) =>
|
||||
element.favorite &&
|
||||
element.categories != null &&
|
||||
element.categories!.contains(e.id))
|
||||
.toList();
|
||||
final data = ref.watch(
|
||||
mangaFilterResultStateProvider(
|
||||
mangaList: entries));
|
||||
entriesFilter = _textEditingController
|
||||
.text.isNotEmpty
|
||||
? data
|
||||
.where((element) => element.name!
|
||||
.toLowerCase()
|
||||
.contains(_textEditingController
|
||||
.text
|
||||
.toLowerCase()))
|
||||
.toList()
|
||||
: data;
|
||||
final entriesManga = reverse
|
||||
? entriesFilter.reversed.toList()
|
||||
: entriesFilter;
|
||||
body: StreamBuilder(
|
||||
stream: isar.modelMangas
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.favoriteEqualTo(true)
|
||||
.categoriesIsNotEmpty()
|
||||
.categoriesElementEqualTo(e.id!)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
// final data = ref.watch(
|
||||
// mangaFilterResultStateProvider(
|
||||
// mangaList: entries));
|
||||
// entriesFilter = _textEditingController
|
||||
// .text.isNotEmpty
|
||||
// ? data
|
||||
// .where((element) => element.name!
|
||||
// .toLowerCase()
|
||||
// .contains(_textEditingController
|
||||
// .text
|
||||
// .toLowerCase()))
|
||||
// .toList()
|
||||
// : data;
|
||||
|
||||
if (entriesFilter.isNotEmpty) {
|
||||
if (snapshot.hasData &&
|
||||
snapshot.data!.isNotEmpty) {
|
||||
final entries = snapshot.data!;
|
||||
final entriesManga = reverse
|
||||
? entries.reversed.toList()
|
||||
: entries;
|
||||
return displayType == DisplayType.list
|
||||
? LibraryListViewWidget(
|
||||
entriesManga: entriesManga,
|
||||
|
|
@ -143,25 +150,17 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
}
|
||||
return Scaffold(
|
||||
appBar: _appBar(isNotFiltering, showNumbersOfItems, entries.length),
|
||||
body: ValueListenableBuilder<Box<ModelManga>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
entries =
|
||||
value.values.where((element) => element.favorite).toList();
|
||||
final data = ref
|
||||
.watch(mangaFilterResultStateProvider(mangaList: entries));
|
||||
entriesFilter = _textEditingController.text.isNotEmpty
|
||||
? data
|
||||
.where((element) => element.name!
|
||||
.toLowerCase()
|
||||
.contains(
|
||||
_textEditingController.text.toLowerCase()))
|
||||
.toList()
|
||||
: data;
|
||||
final entriesManga =
|
||||
reverse ? entriesFilter.reversed.toList() : entriesFilter;
|
||||
|
||||
if (entriesFilter.isNotEmpty) {
|
||||
body: StreamBuilder(
|
||||
stream: isar.modelMangas
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.favoriteEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final entries = snapshot.data!;
|
||||
final entriesManga =
|
||||
reverse ? entries.reversed.toList() : entries;
|
||||
return displayType == DisplayType.list
|
||||
? LibraryListViewWidget(
|
||||
entriesManga: entriesManga,
|
||||
|
|
|
|||
|
|
@ -84,13 +84,13 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(chap.name, defaultValue: null);
|
||||
if (modelChapDownload != null &&
|
||||
modelChapDownload.isDownload == true) {
|
||||
list.add(true);
|
||||
}
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(chap.name, defaultValue: null);
|
||||
// if (modelChapDownload != null &&
|
||||
// modelChapDownload.isDownload == true) {
|
||||
// list.add(true);
|
||||
// }
|
||||
}
|
||||
return list.isNotEmpty;
|
||||
}).toList();
|
||||
|
|
@ -100,13 +100,13 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(chap.name, defaultValue: null);
|
||||
if (modelChapDownload == null ||
|
||||
modelChapDownload.isDownload == false) {
|
||||
list.add(true);
|
||||
}
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(chap.name, defaultValue: null);
|
||||
// if (modelChapDownload == null ||
|
||||
// modelChapDownload.isDownload == false) {
|
||||
// list.add(true);
|
||||
// }
|
||||
}
|
||||
return list.length == element.chapters!.length;
|
||||
}).toList();
|
||||
|
|
@ -121,13 +121,13 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(chap.name, defaultValue: null);
|
||||
if (modelChapDownload != null &&
|
||||
modelChapDownload.isDownload == true) {
|
||||
list.add(true);
|
||||
}
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(chap.name, defaultValue: null);
|
||||
// if (modelChapDownload != null &&
|
||||
// modelChapDownload.isDownload == true) {
|
||||
// list.add(true);
|
||||
// }
|
||||
}
|
||||
return list.isNotEmpty;
|
||||
}).toList();
|
||||
|
|
@ -137,13 +137,13 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(chap.name, defaultValue: null);
|
||||
if (modelChapDownload == null ||
|
||||
modelChapDownload.isDownload == false) {
|
||||
list.add(true);
|
||||
}
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(chap.name, defaultValue: null);
|
||||
// if (modelChapDownload == null ||
|
||||
// modelChapDownload.isDownload == false) {
|
||||
// list.add(true);
|
||||
// }
|
||||
}
|
||||
return list.length == element.chapters!.length;
|
||||
}).toList();
|
||||
|
|
@ -180,7 +180,7 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (!chap.isRead) {
|
||||
if (!chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (chap.isRead) {
|
||||
if (chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -208,7 +208,7 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (!chap.isRead) {
|
||||
if (!chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -220,7 +220,7 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (chap.isRead) {
|
||||
if (chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -259,7 +259,7 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (!chap.isRead) {
|
||||
if (!chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -270,7 +270,7 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (chap.isRead) {
|
||||
if (chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +287,7 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (!chap.isRead) {
|
||||
if (!chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (chap.isRead) {
|
||||
if (chap.isRead!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (chap.isBookmarked) {
|
||||
if (chap.isBookmarked!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -349,7 +349,7 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (!chap.isBookmarked) {
|
||||
if (!chap.isBookmarked!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -366,7 +366,7 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (chap.isBookmarked) {
|
||||
if (chap.isBookmarked!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -378,7 +378,7 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
|||
final data = mangaList.where((element) {
|
||||
List list = [];
|
||||
for (var chap in element.chapters!) {
|
||||
if (!chap.isBookmarked) {
|
||||
if (!chap.isBookmarked!) {
|
||||
list.add(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ final libraryDisplayTypeStateProvider =
|
|||
|
||||
typedef _$LibraryDisplayTypeState = AutoDisposeNotifier<String>;
|
||||
String _$mangaFilterDownloadedStateHash() =>
|
||||
r'18ed17c06f41084cbb92b0b3300025f4e65aa413';
|
||||
r'3c09b61fc80e35711b308b2b0050879c37cdd299';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -161,7 +161,7 @@ class MangaFilterDownloadedStateProvider
|
|||
}
|
||||
|
||||
String _$mangaFilterUnreadStateHash() =>
|
||||
r'5eed6ec9f46f1562d48eb89a078f666ed5b466d8';
|
||||
r'bb771edf600c96e1b9fe4ceb786f143fe7050bfb';
|
||||
|
||||
abstract class _$MangaFilterUnreadState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -260,7 +260,7 @@ class MangaFilterUnreadStateProvider
|
|||
}
|
||||
|
||||
String _$mangaFilterStartedStateHash() =>
|
||||
r'cf5440f02e8454d75de4f311f945b33f73668ea2';
|
||||
r'b8447b0eb414f15c4200bad461c260bdde3fe91c';
|
||||
|
||||
abstract class _$MangaFilterStartedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -359,7 +359,7 @@ class MangaFilterStartedStateProvider
|
|||
}
|
||||
|
||||
String _$mangaFilterBookmarkedStateHash() =>
|
||||
r'cdeeb68e7428e4856db3551443c70e28c3c7f95d';
|
||||
r'777ac2ceb266d5bf6837ea270fd62ab8471add92';
|
||||
|
||||
abstract class _$MangaFilterBookmarkedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import 'package:mangayomi/providers/hive_provider.dart';
|
|||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/views/manga/download/download_model.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||
|
|
@ -38,7 +37,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.push('/manga-reader/detail', extra: entriesManga[index]);
|
||||
context.push('/manga-reader/detail', extra: entriesManga[index].id);
|
||||
},
|
||||
child: CoverViewWidget(
|
||||
bottomTextWidget: BottomTextWidget(
|
||||
|
|
@ -76,7 +75,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
for (var i = 0;
|
||||
i <
|
||||
entriesManga[index]
|
||||
.chapters!
|
||||
.chapters
|
||||
.length;
|
||||
i++) {
|
||||
final entries = ref
|
||||
|
|
@ -84,12 +83,10 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
hiveBoxMangaDownloadsProvider)
|
||||
.values
|
||||
.where((element) =>
|
||||
element
|
||||
.modelManga
|
||||
.chapters![element.index]
|
||||
.name ==
|
||||
element.chapterName ==
|
||||
entriesManga[index]
|
||||
.chapters![i]
|
||||
.chapters
|
||||
.toList()[i]
|
||||
.name)
|
||||
.toList();
|
||||
if (entries.isNotEmpty &&
|
||||
|
|
@ -127,7 +124,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(right: 3),
|
||||
child: Text(
|
||||
entriesManga[index]
|
||||
.chapters!
|
||||
.chapters
|
||||
.length
|
||||
.toString(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
|
|
@ -217,7 +214,7 @@ class LibraryGridViewWidget extends StatelessWidget {
|
|||
context: context,
|
||||
modelManga: entriesManga[index],
|
||||
index: entriesManga[index]
|
||||
.chapters!
|
||||
.chapters
|
||||
.length -
|
||||
1);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import 'package:mangayomi/providers/hive_provider.dart';
|
|||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/listview_widget.dart';
|
||||
|
||||
|
|
@ -87,21 +86,16 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
builder: (context, ref, child) {
|
||||
List nbrDown = [];
|
||||
for (var i = 0;
|
||||
i <
|
||||
entriesManga[index]
|
||||
.chapters!
|
||||
.length;
|
||||
i < entriesManga[index].chapters.length;
|
||||
i++) {
|
||||
final entries = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.values
|
||||
.where((element) =>
|
||||
element
|
||||
.modelManga
|
||||
.chapters![element.index]
|
||||
.name ==
|
||||
element.chapterName ==
|
||||
entriesManga[index]
|
||||
.chapters![i]
|
||||
.chapters
|
||||
.toList()[i]
|
||||
.name)
|
||||
.toList();
|
||||
if (entries.isNotEmpty &&
|
||||
|
|
@ -136,7 +130,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(right: 3),
|
||||
child: Text(
|
||||
entriesManga[index].chapters!.length.toString(),
|
||||
entriesManga[index].chapters.length.toString(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
|
|
@ -208,9 +202,8 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
pushMangaReaderView(
|
||||
context: context,
|
||||
modelManga: entriesManga[index],
|
||||
index:
|
||||
entriesManga[index].chapters!.length -
|
||||
1);
|
||||
index: entriesManga[index].chapters.length -
|
||||
1);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
bool _expanded = false;
|
||||
ScrollController _scrollController = ScrollController();
|
||||
|
||||
List<ModelChapters>? _chapters;
|
||||
ModelManga? _modelManga;
|
||||
int? _pageLength;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final chapterNameList = ref.watch(chapterIdsListStateProvider);
|
||||
bool reverse = ref.watch(
|
||||
reverseChapterStateProvider(modelManga: widget.modelManga!))["reverse"];
|
||||
return NotificationListener<UserScrollNotification>(
|
||||
onNotification: (notification) {
|
||||
if (notification.direction == ScrollDirection.forward) {
|
||||
|
|
@ -85,7 +85,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
.isNotFiltering();
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final chapterNameList =
|
||||
ref.watch(chapterNameListStateProvider);
|
||||
ref.watch(chapterIdsListStateProvider);
|
||||
return isLongPressed
|
||||
? Container(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
|
|
@ -96,7 +96,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
leading: IconButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.read(chapterIdsListStateProvider
|
||||
.notifier)
|
||||
.clear();
|
||||
|
||||
|
|
@ -109,49 +109,37 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
for (var i = 0;
|
||||
i <
|
||||
widget
|
||||
.modelManga!.chapters!.length;
|
||||
i++) {
|
||||
for (var chapter
|
||||
in widget.modelManga!.chapters) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.read(chapterIdsListStateProvider
|
||||
.notifier)
|
||||
.selectAll(
|
||||
"${widget.modelManga!.chapters![i].name!}$i");
|
||||
.selectAll(chapter);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.select_all)),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (widget.modelManga!.chapters!.length ==
|
||||
if (widget.modelManga!.chapters.length ==
|
||||
chapterNameList.length) {
|
||||
for (var i = 0;
|
||||
i <
|
||||
widget.modelManga!.chapters!
|
||||
.length;
|
||||
i++) {
|
||||
for (var chapter
|
||||
in widget.modelManga!.chapters) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.read(chapterIdsListStateProvider
|
||||
.notifier)
|
||||
.selectSome(
|
||||
"${widget.modelManga!.chapters![i].name}$i");
|
||||
.selectSome(chapter);
|
||||
}
|
||||
ref
|
||||
.read(isLongPressedStateProvider
|
||||
.notifier)
|
||||
.update(false);
|
||||
} else {
|
||||
for (var i = 0;
|
||||
i <
|
||||
widget.modelManga!.chapters!
|
||||
.length;
|
||||
i++) {
|
||||
for (var chapter
|
||||
in widget.modelManga!.chapters) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.read(chapterIdsListStateProvider
|
||||
.notifier)
|
||||
.selectSome(
|
||||
"${widget.modelManga!.chapters![i].name}$i");
|
||||
.selectSome(chapter);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -160,227 +148,201 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
],
|
||||
),
|
||||
)
|
||||
: AppBar(
|
||||
title: ref.watch(offetProvider) > 200
|
||||
? Text(
|
||||
widget.modelManga!.name!,
|
||||
style: const TextStyle(fontSize: 17),
|
||||
)
|
||||
: null,
|
||||
backgroundColor: ref.watch(offetProvider) == 0.0
|
||||
? Colors.transparent
|
||||
: Theme.of(context).scaffoldBackgroundColor,
|
||||
actions: [
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
Icons.download_outlined,
|
||||
: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
child: Stack(
|
||||
children: [
|
||||
cachedNetworkImage(
|
||||
headers: headers(
|
||||
widget.modelManga!.source!),
|
||||
imageUrl:
|
||||
widget.modelManga!.imageUrl!,
|
||||
width: mediaWidth(context, 1),
|
||||
height: 410,
|
||||
fit: BoxFit.cover),
|
||||
Container(
|
||||
width: mediaWidth(context, 1),
|
||||
height: 465,
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.9),
|
||||
),
|
||||
],
|
||||
)),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
_showDraggableMenu();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.filter_list_sharp,
|
||||
color:
|
||||
isNotFiltering ? null : Colors.yellow,
|
||||
)),
|
||||
PopupMenuButton(
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
if (widget.modelManga!.favorite)
|
||||
const PopupMenuItem<int>(
|
||||
value: 0,
|
||||
child: Text("Edit categories")),
|
||||
if (widget.modelManga!.favorite)
|
||||
const PopupMenuItem<int>(
|
||||
value: 0, child: Text("Migrate")),
|
||||
const PopupMenuItem<int>(
|
||||
value: 0, child: Text("Share")),
|
||||
];
|
||||
},
|
||||
onSelected: (value) {}),
|
||||
AppBar(
|
||||
title: ref.watch(offetProvider) > 200
|
||||
? Text(
|
||||
widget.modelManga!.name!,
|
||||
style: const TextStyle(fontSize: 17),
|
||||
)
|
||||
: null,
|
||||
backgroundColor: ref.watch(offetProvider) == 0.0
|
||||
? Colors.transparent
|
||||
: Theme.of(context).scaffoldBackgroundColor,
|
||||
actions: [
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
Icons.download_outlined,
|
||||
)),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
_showDraggableMenu();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.filter_list_sharp,
|
||||
color: isNotFiltering
|
||||
? null
|
||||
: Colors.yellow,
|
||||
)),
|
||||
PopupMenuButton(
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
if (widget.modelManga!.favorite)
|
||||
const PopupMenuItem<int>(
|
||||
value: 0,
|
||||
child: Text("Edit categories")),
|
||||
if (widget.modelManga!.favorite)
|
||||
const PopupMenuItem<int>(
|
||||
value: 0,
|
||||
child: Text("Migrate")),
|
||||
const PopupMenuItem<int>(
|
||||
value: 0, child: Text("Share")),
|
||||
];
|
||||
},
|
||||
onSelected: (value) {}),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
)),
|
||||
body: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
child: Stack(
|
||||
children: [
|
||||
cachedNetworkImage(
|
||||
headers: headers(widget.modelManga!.source!),
|
||||
imageUrl: widget.modelManga!.imageUrl!,
|
||||
width: mediaWidth(context, 1),
|
||||
height: 461,
|
||||
fit: BoxFit.cover),
|
||||
Container(
|
||||
width: mediaWidth(context, 1),
|
||||
height: 465,
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withOpacity(0.9),
|
||||
body: SafeArea(
|
||||
child: DraggableScrollbar(
|
||||
heightScrollThumb: 48.0,
|
||||
backgroundColor: primaryColor(context),
|
||||
scrollThumbBuilder: (backgroundColor, thumbAnimation,
|
||||
labelAnimation, height,
|
||||
{labelConstraints, labelText}) {
|
||||
return FadeTransition(
|
||||
opacity: thumbAnimation,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
height: height,
|
||||
width: 8.0,
|
||||
),
|
||||
SafeArea(
|
||||
child: Container(
|
||||
width: mediaWidth(context, 1),
|
||||
height: mediaHeight(context, 1),
|
||||
color: Theme.of(context).scaffoldBackgroundColor),
|
||||
)
|
||||
],
|
||||
)),
|
||||
SafeArea(child: Consumer(builder: (context, ref, child) {
|
||||
_pageLength = ref
|
||||
.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!))
|
||||
.chapters!
|
||||
.length +
|
||||
1;
|
||||
_chapters = ref
|
||||
.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!))
|
||||
.chapters;
|
||||
_modelManga = ref.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!));
|
||||
bool reverse = ref.watch(reverseChapterStateProvider(
|
||||
modelManga: widget.modelManga!))["reverse"];
|
||||
return DraggableScrollbar(
|
||||
heightScrollThumb: 48.0,
|
||||
backgroundColor: primaryColor(context),
|
||||
scrollThumbBuilder: (backgroundColor, thumbAnimation,
|
||||
labelAnimation, height,
|
||||
{labelConstraints, labelText}) {
|
||||
return FadeTransition(
|
||||
opacity: thumbAnimation,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
height: height,
|
||||
width: 8.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
scrollbarTimeToFade: const Duration(seconds: 2),
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.only(top: 0, bottom: 60),
|
||||
itemCount: _pageLength,
|
||||
itemBuilder: (context, index) {
|
||||
int finalIndex = index - 1;
|
||||
if (index == 0) {
|
||||
return _bodyContainer();
|
||||
}
|
||||
int reverseIndex = _chapters!.length -
|
||||
_chapters!.reversed.toList().indexOf(
|
||||
_chapters!.reversed.toList()[finalIndex]) -
|
||||
1;
|
||||
);
|
||||
},
|
||||
scrollbarTimeToFade: const Duration(seconds: 2),
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.only(top: 0, bottom: 60),
|
||||
itemCount: widget.listLength,
|
||||
itemBuilder: (context, index) {
|
||||
int finalIndex = index - 1;
|
||||
if (index == 0) {
|
||||
return _bodyContainer();
|
||||
}
|
||||
|
||||
List<ModelChapters> chapters = reverse
|
||||
? _chapters!.reversed.toList()
|
||||
: _chapters!;
|
||||
int reverseIndex =
|
||||
widget.modelManga!.chapters.length -
|
||||
widget.modelManga!.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.indexOf(widget.modelManga!.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()[finalIndex]) -
|
||||
1;
|
||||
final indexx = reverse ? reverseIndex : finalIndex;
|
||||
List<ModelChapters> chapters = reverse
|
||||
? widget.modelManga!.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
: widget.modelManga!.chapters.toList();
|
||||
|
||||
return ChapterListTileWidget(
|
||||
chapters: chapters,
|
||||
modelManga: _modelManga!,
|
||||
reverse: reverse,
|
||||
reverseIndex: reverseIndex,
|
||||
finalIndex: finalIndex,
|
||||
);
|
||||
}));
|
||||
})),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final chapter = ref.watch(chapterModelStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
return AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor(context).withOpacity(0.2),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20))),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
height: isLongPressed ? 70 : 0,
|
||||
width: mediaWidth(context, 1),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent),
|
||||
onPressed: () async {
|
||||
ref
|
||||
.read(chapterSetIsBookmarkStateProvider(
|
||||
modelManga: widget.modelManga!)
|
||||
.notifier)
|
||||
.set();
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: Icon(chapter.isBookmarked
|
||||
? Icons.bookmark_remove
|
||||
: Icons.bookmark_add_outlined)),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(chapterSetIsReadStateProvider(
|
||||
modelManga: widget.modelManga!)
|
||||
.notifier)
|
||||
.set();
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: Icon(chapter.isRead
|
||||
? Icons.remove_done_sharp
|
||||
: Icons.done_all_sharp)),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(chapterSetDownloadStateProvider(
|
||||
modelManga: widget.modelManga!)
|
||||
.notifier)
|
||||
.set();
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: const Icon(Icons.download_outlined)),
|
||||
),
|
||||
)
|
||||
],
|
||||
return ChapterListTileWidget(
|
||||
modelManga: widget.modelManga!,
|
||||
chapter: chapters[indexx],
|
||||
chapterNameList: chapterNameList,
|
||||
chapterIndex: indexx,
|
||||
);
|
||||
}))),
|
||||
bottomNavigationBar: AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor(context).withOpacity(0.2),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20))),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
height: isLongPressed ? 70 : 0,
|
||||
width: mediaWidth(context, 1),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(chapterSetIsBookmarkStateProvider(
|
||||
modelManga: widget.modelManga!)
|
||||
.notifier)
|
||||
.set();
|
||||
},
|
||||
child: const Icon(Icons.bookmark_add_outlined)),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(chapterSetIsReadStateProvider(
|
||||
modelManga: widget.modelManga!)
|
||||
.notifier)
|
||||
.set();
|
||||
},
|
||||
child: const Icon(Icons.done_all_sharp)),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(chapterSetDownloadStateProvider(
|
||||
modelManga: widget.modelManga!)
|
||||
.notifier)
|
||||
.set();
|
||||
},
|
||||
child: const Icon(Icons.download_outlined)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -659,7 +621,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'${(_pageLength! - 1)} chapters',
|
||||
'${(widget.listLength - 1)} chapters',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/categories.dart';
|
||||
import 'package:mangayomi/models/manga_reader.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
|
|
@ -55,132 +57,132 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manga = ref.watch(hiveBoxMangaProvider);
|
||||
_checkFavorite(widget.modelManga.favorite);
|
||||
return Scaffold(
|
||||
floatingActionButton: ref.watch(isLongPressedStateProvider) == true
|
||||
? null
|
||||
: widget.modelManga.chapters!.isNotEmpty
|
||||
? ValueListenableBuilder<Box>(
|
||||
valueListenable:
|
||||
ref.watch(hiveBoxMangaInfoProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries = value.get(
|
||||
"${widget.modelManga.lang}-${widget.modelManga.source}/${widget.modelManga.name}-chapter_index",
|
||||
defaultValue: '');
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
// floatingActionButton: ref.watch(isLongPressedStateProvider) == true
|
||||
// ? null
|
||||
// : widget.modelManga.chapters!.isNotEmpty
|
||||
// ? ValueListenableBuilder<Box>(
|
||||
// valueListenable:
|
||||
// ref.watch(hiveBoxMangaInfoProvider).listenable(),
|
||||
// builder: (context, value, child) {
|
||||
// final entries = value.get(
|
||||
// "${widget.modelManga.lang}-${widget.modelManga.source}/${widget.modelManga.name}-chapter_index",
|
||||
// defaultValue: '');
|
||||
// final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
|
||||
if (entries.isNotEmpty && !incognitoMode) {
|
||||
return Consumer(builder: (context, ref, child) {
|
||||
final isExtended = ref.watch(isExtendedStateProvider);
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
height: 55,
|
||||
width: !isExtended ? 63 : 130,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeIn,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor(context),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(15))),
|
||||
onPressed: () {
|
||||
pushMangaReaderView(
|
||||
context: context,
|
||||
modelManga: widget.modelManga,
|
||||
index: int.parse(entries.toString()));
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
),
|
||||
AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
width: !isExtended ? 0 : 8,
|
||||
duration:
|
||||
const Duration(milliseconds: 500),
|
||||
),
|
||||
AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
width: !isExtended ? 0 : 60,
|
||||
duration:
|
||||
const Duration(milliseconds: 200),
|
||||
child: const Text(
|
||||
"Continue",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
return Consumer(builder: (context, ref, child) {
|
||||
final isExtended = ref.watch(isExtendedStateProvider);
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
height: 55,
|
||||
width: !isExtended ? 60 : 105,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor(context),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15))),
|
||||
onPressed: () {
|
||||
pushMangaReaderView(
|
||||
context: context,
|
||||
modelManga: widget.modelManga,
|
||||
index:
|
||||
widget.modelManga.chapters!.length - 1);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
),
|
||||
AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
width: !isExtended ? 0 : 5,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
),
|
||||
AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
width: !isExtended ? 0 : 40,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: const Text(
|
||||
"Read",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
)
|
||||
: null,
|
||||
// if (entries.isNotEmpty && !incognitoMode) {
|
||||
// return Consumer(builder: (context, ref, child) {
|
||||
// final isExtended = ref.watch(isExtendedStateProvider);
|
||||
// return Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
// children: [
|
||||
// AnimatedContainer(
|
||||
// height: 55,
|
||||
// width: !isExtended ? 63 : 130,
|
||||
// duration: const Duration(milliseconds: 200),
|
||||
// curve: Curves.easeIn,
|
||||
// child: ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: primaryColor(context),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius:
|
||||
// BorderRadius.circular(15))),
|
||||
// onPressed: () {
|
||||
// pushMangaReaderView(
|
||||
// context: context,
|
||||
// modelManga: widget.modelManga,
|
||||
// index: int.parse(entries.toString()));
|
||||
// },
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// const Icon(
|
||||
// Icons.play_arrow,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// AnimatedContainer(
|
||||
// curve: Curves.easeIn,
|
||||
// width: !isExtended ? 0 : 8,
|
||||
// duration:
|
||||
// const Duration(milliseconds: 500),
|
||||
// ),
|
||||
// AnimatedContainer(
|
||||
// curve: Curves.easeIn,
|
||||
// width: !isExtended ? 0 : 60,
|
||||
// duration:
|
||||
// const Duration(milliseconds: 200),
|
||||
// child: const Text(
|
||||
// "Continue",
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// style: TextStyle(
|
||||
// fontSize: 14, color: Colors.white),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
// return Consumer(builder: (context, ref, child) {
|
||||
// final isExtended = ref.watch(isExtendedStateProvider);
|
||||
// return Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
// children: [
|
||||
// AnimatedContainer(
|
||||
// height: 55,
|
||||
// width: !isExtended ? 60 : 105,
|
||||
// duration: const Duration(milliseconds: 300),
|
||||
// curve: Curves.easeIn,
|
||||
// child: ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: primaryColor(context),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(15))),
|
||||
// onPressed: () {
|
||||
// pushMangaReaderView(
|
||||
// context: context,
|
||||
// modelManga: widget.modelManga,
|
||||
// index:
|
||||
// widget.modelManga.chapters!.length - 1);
|
||||
// },
|
||||
// child: Row(
|
||||
// children: [
|
||||
// const Icon(
|
||||
// Icons.play_arrow,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// AnimatedContainer(
|
||||
// curve: Curves.easeIn,
|
||||
// width: !isExtended ? 0 : 5,
|
||||
// duration: const Duration(milliseconds: 300),
|
||||
// ),
|
||||
// AnimatedContainer(
|
||||
// curve: Curves.easeIn,
|
||||
// width: !isExtended ? 0 : 40,
|
||||
// duration: const Duration(milliseconds: 300),
|
||||
// child: const Text(
|
||||
// "Read",
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// style: TextStyle(
|
||||
// fontSize: 14,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// });
|
||||
// },
|
||||
// )
|
||||
// : null,
|
||||
body: MangaDetailView(
|
||||
titleDescription: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
@ -210,185 +212,160 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
)
|
||||
],
|
||||
),
|
||||
action: ValueListenableBuilder<Box<ModelManga>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries = value.values
|
||||
.where((element) =>
|
||||
'${element.lang}-${element.link}' ==
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}')
|
||||
.toList();
|
||||
if (entries.isNotEmpty) {
|
||||
if (entries[0].favorite == true) {
|
||||
_checkFavorite(true);
|
||||
|
||||
return SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () {
|
||||
_setFavorite(false);
|
||||
final model = ModelManga(
|
||||
imageUrl: widget.modelManga.imageUrl,
|
||||
name: widget.modelManga.name,
|
||||
genre: widget.modelManga.genre,
|
||||
author: widget.modelManga.author,
|
||||
status: widget.modelManga.status,
|
||||
description: widget.modelManga.description,
|
||||
favorite: false,
|
||||
link: widget.modelManga.link,
|
||||
source: widget.modelManga.source,
|
||||
lang: widget.modelManga.lang,
|
||||
dateAdded: widget.modelManga.dateAdded,
|
||||
lastUpdate: widget.modelManga.lastUpdate,
|
||||
chapters: widget.modelManga.chapters,
|
||||
categories: [],
|
||||
lastRead: widget.modelManga.lastRead);
|
||||
manga.put(
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
model);
|
||||
},
|
||||
child: Column(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.favorite,
|
||||
size: 22,
|
||||
),
|
||||
SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
'In library',
|
||||
style: TextStyle(fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
action: widget.modelManga.favorite
|
||||
? SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () async {
|
||||
_setFavorite(false);
|
||||
final model = widget.modelManga;
|
||||
await isar.writeTxn(() async {
|
||||
model.favorite = false;
|
||||
await isar.modelMangas.put(model);
|
||||
});
|
||||
},
|
||||
child: Column(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.favorite,
|
||||
size: 22,
|
||||
),
|
||||
SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
'In library',
|
||||
style: TextStyle(fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
_checkFavorite(false);
|
||||
return SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () {
|
||||
final checkCategoryList = ref
|
||||
.watch(hiveBoxCategoriesProvider)
|
||||
.values
|
||||
.toList()
|
||||
.isNotEmpty;
|
||||
if (checkCategoryList) {
|
||||
_openCategory(manga);
|
||||
} else {
|
||||
_setFavorite(true);
|
||||
final model = ModelManga(
|
||||
imageUrl: widget.modelManga.imageUrl,
|
||||
name: widget.modelManga.name,
|
||||
genre: widget.modelManga.genre,
|
||||
author: widget.modelManga.author,
|
||||
status: widget.modelManga.status,
|
||||
description: widget.modelManga.description,
|
||||
favorite: true,
|
||||
link: widget.modelManga.link,
|
||||
source: widget.modelManga.source,
|
||||
lang: widget.modelManga.lang,
|
||||
dateAdded: DateTime.now().microsecondsSinceEpoch,
|
||||
lastUpdate: DateTime.now().microsecondsSinceEpoch,
|
||||
chapters: widget.modelManga.chapters,
|
||||
categories: [],
|
||||
lastRead: '');
|
||||
manga.put(
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
model);
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.favorite_border_rounded,
|
||||
size: 22,
|
||||
color: secondaryColor(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
'Add to library',
|
||||
style: TextStyle(
|
||||
color: secondaryColor(context), fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () async {
|
||||
final checkCategoryList = await isar.categoriesModels
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.isNotEmpty();
|
||||
if (checkCategoryList) {
|
||||
_openCategory(widget.modelManga);
|
||||
} else {
|
||||
_setFavorite(true);
|
||||
final model = widget.modelManga;
|
||||
await isar.writeTxn(() async {
|
||||
model.favorite = true;
|
||||
await isar.modelMangas.put(model);
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.favorite_border_rounded,
|
||||
size: 22,
|
||||
color: secondaryColor(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
'Add to library',
|
||||
style: TextStyle(
|
||||
color: secondaryColor(context), fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return SizedBox(
|
||||
width: mediaWidth(context, 0.4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () {
|
||||
final checkCategoryList = ref
|
||||
.watch(hiveBoxCategoriesProvider)
|
||||
.values
|
||||
.toList()
|
||||
.isNotEmpty;
|
||||
if (checkCategoryList) {
|
||||
_openCategory(manga);
|
||||
} else {
|
||||
_setFavorite(true);
|
||||
final model = ModelManga(
|
||||
imageUrl: widget.modelManga.imageUrl,
|
||||
name: widget.modelManga.name,
|
||||
genre: widget.modelManga.genre,
|
||||
author: widget.modelManga.author,
|
||||
status: widget.modelManga.status,
|
||||
description: widget.modelManga.description,
|
||||
favorite: true,
|
||||
link: widget.modelManga.link,
|
||||
source: widget.modelManga.source,
|
||||
lang: widget.modelManga.lang,
|
||||
dateAdded: DateTime.now().microsecondsSinceEpoch,
|
||||
lastUpdate: DateTime.now().microsecondsSinceEpoch,
|
||||
chapters: widget.modelManga.chapters,
|
||||
categories: [],
|
||||
lastRead: '');
|
||||
manga.put(
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
model);
|
||||
}
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.favorite_border_rounded,
|
||||
size: 22,
|
||||
color: secondaryColor(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
'Add to library',
|
||||
style: TextStyle(
|
||||
color: secondaryColor(context), fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// ValueListenableBuilder<Box<ModelManga>>(
|
||||
// valueListenable: ref.watch(hiveBoxMangaProvider).listenable(),
|
||||
// builder: (context, value, child) {
|
||||
// final entries = value.values
|
||||
// .where((element) =>
|
||||
// '${element.lang}-${element.link}' ==
|
||||
// '${widget.modelManga.lang}-${widget.modelManga.link}')
|
||||
// .toList();
|
||||
// if (entries.isNotEmpty) {
|
||||
// if (entries[0].favorite == true) {
|
||||
// _checkFavorite(true);
|
||||
|
||||
// return ;
|
||||
// } else {
|
||||
// _checkFavorite(false);
|
||||
// return ;
|
||||
// }
|
||||
// }
|
||||
// return SizedBox(
|
||||
// width: mediaWidth(context, 0.4),
|
||||
// child: ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
// elevation: 0),
|
||||
// onPressed: () {
|
||||
// final checkCategoryList = ref
|
||||
// .watch(hiveBoxCategoriesProvider)
|
||||
// .values
|
||||
// .toList()
|
||||
// .isNotEmpty;
|
||||
// if (checkCategoryList) {
|
||||
// _openCategory(manga);
|
||||
// } else {
|
||||
// _setFavorite(true);
|
||||
// final model = ModelManga(
|
||||
// imageUrl: widget.modelManga.imageUrl,
|
||||
// name: widget.modelManga.name,
|
||||
// genre: widget.modelManga.genre,
|
||||
// author: widget.modelManga.author,
|
||||
// status: widget.modelManga.status,
|
||||
// description: widget.modelManga.description,
|
||||
// favorite: true,
|
||||
// link: widget.modelManga.link,
|
||||
// source: widget.modelManga.source,
|
||||
// lang: widget.modelManga.lang,
|
||||
// dateAdded: DateTime.now().microsecondsSinceEpoch,
|
||||
// lastUpdate: DateTime.now().microsecondsSinceEpoch,
|
||||
// chapters: widget.modelManga.chapters,
|
||||
// categories: [],
|
||||
// lastRead: '');
|
||||
// manga.put(
|
||||
// '${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
// model);
|
||||
// }
|
||||
// },
|
||||
// child: Column(
|
||||
// children: [
|
||||
// Icon(
|
||||
// Icons.favorite_border_rounded,
|
||||
// size: 22,
|
||||
// color: secondaryColor(context),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 4,
|
||||
// ),
|
||||
// Text(
|
||||
// 'Add to library',
|
||||
// style: TextStyle(
|
||||
// color: secondaryColor(context), fontSize: 13),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
modelManga: widget.modelManga,
|
||||
listLength: widget.modelManga.chapters!.length + 1,
|
||||
listLength: widget.modelManga.chapters.length + 1,
|
||||
isExtended: (value) {
|
||||
ref.read(isExtendedStateProvider.notifier).update(value);
|
||||
},
|
||||
|
|
@ -396,7 +373,7 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
);
|
||||
}
|
||||
|
||||
_openCategory(Box<ModelManga> manga) {
|
||||
_openCategory(ModelManga manga) {
|
||||
List<int> categoryIds = [];
|
||||
showDialog(
|
||||
context: context,
|
||||
|
|
@ -409,32 +386,38 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: ValueListenableBuilder<Box<CategoriesModel>>(
|
||||
valueListenable:
|
||||
ref.watch(hiveBoxCategoriesProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries = value.values.toList();
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTileChapterFilter(
|
||||
label: entries[index].name,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (categoryIds.contains(entries[index].id)) {
|
||||
categoryIds.remove(entries[index].id);
|
||||
} else {
|
||||
categoryIds.add(entries[index].id);
|
||||
}
|
||||
});
|
||||
},
|
||||
type: categoryIds.contains(entries[index].id)
|
||||
? 1
|
||||
: 0,
|
||||
);
|
||||
},
|
||||
);
|
||||
child: StreamBuilder(
|
||||
stream: isar.categoriesModels
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final entries = snapshot.data!;
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTileChapterFilter(
|
||||
label: entries[index].name!,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (categoryIds
|
||||
.contains(entries[index].id)) {
|
||||
categoryIds.remove(entries[index].id);
|
||||
} else {
|
||||
categoryIds.add(entries[index].id!);
|
||||
}
|
||||
});
|
||||
},
|
||||
type: categoryIds.contains(entries[index].id)
|
||||
? 1
|
||||
: 0,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
}),
|
||||
),
|
||||
actions: [
|
||||
|
|
@ -458,30 +441,17 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
onPressed: () async {
|
||||
_setFavorite(true);
|
||||
final model = ModelManga(
|
||||
imageUrl: widget.modelManga.imageUrl,
|
||||
name: widget.modelManga.name,
|
||||
genre: widget.modelManga.genre,
|
||||
author: widget.modelManga.author,
|
||||
status: widget.modelManga.status,
|
||||
description: widget.modelManga.description,
|
||||
favorite: true,
|
||||
link: widget.modelManga.link,
|
||||
source: widget.modelManga.source,
|
||||
lang: widget.modelManga.lang,
|
||||
dateAdded:
|
||||
DateTime.now().microsecondsSinceEpoch,
|
||||
lastUpdate:
|
||||
DateTime.now().microsecondsSinceEpoch,
|
||||
chapters: widget.modelManga.chapters,
|
||||
categories: categoryIds,
|
||||
lastRead: '');
|
||||
manga.put(
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
model);
|
||||
Navigator.pop(context);
|
||||
final model = widget.modelManga;
|
||||
await isar.writeTxn(() async {
|
||||
model.favorite = true;
|
||||
model.categories = categoryIds;
|
||||
await isar.modelMangas.put(model);
|
||||
});
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: const Text(
|
||||
"OK",
|
||||
|
|
|
|||
|
|
@ -1,22 +1,33 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/services/get_manga_detail.dart';
|
||||
import 'package:mangayomi/views/manga/detail/manga_details_view.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
class MangaReaderDetail extends ConsumerStatefulWidget {
|
||||
final ModelManga modelManga;
|
||||
const MangaReaderDetail({super.key, required this.modelManga});
|
||||
final int idManga;
|
||||
const MangaReaderDetail({super.key, required this.idManga});
|
||||
|
||||
@override
|
||||
ConsumerState<MangaReaderDetail> createState() => _MangaReaderDetailState();
|
||||
}
|
||||
|
||||
final mangaa = StreamProvider.family<ModelManga?, int>((ref, id) async* {
|
||||
// final ddd = isar.modelMangas.filter().chapters((q) => q.isReadEqualTo(true)).build().watch();
|
||||
yield* isar.modelMangas.watchObject(id, fireImmediately: true);
|
||||
});
|
||||
|
||||
class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
||||
bool _isFavorite = false;
|
||||
@override
|
||||
|
|
@ -25,6 +36,7 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
|||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
|
@ -36,95 +48,118 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mm = ref.watch(mangaa(widget.idManga));
|
||||
return Scaffold(
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
if (_isFavorite) {
|
||||
bool isOk = false;
|
||||
ref
|
||||
.watch(getMangaDetailProvider(
|
||||
imageUrl: widget.modelManga.imageUrl!,
|
||||
lang: widget.modelManga.lang!,
|
||||
title: widget.modelManga.name!,
|
||||
source: widget.modelManga.source!,
|
||||
url: widget.modelManga.link!)
|
||||
.future)
|
||||
.then((value) {
|
||||
if (value.chapters.isNotEmpty &&
|
||||
value.chapters.length > widget.modelManga.chapters!.length) {
|
||||
List<ModelChapters>? chapters = [];
|
||||
for (var chap in widget.modelManga.chapters!) {
|
||||
chapters.add(chap);
|
||||
}
|
||||
int newChapsSize =
|
||||
value.chapters.length - widget.modelManga.chapters!.length;
|
||||
for (var i = 0; i < newChapsSize; i++) {
|
||||
chapters.insert(i, value.chapters[i]);
|
||||
}
|
||||
final model = ModelManga(
|
||||
imageUrl: widget.modelManga.imageUrl,
|
||||
name: widget.modelManga.name,
|
||||
genre: widget.modelManga.genre,
|
||||
author: widget.modelManga.author,
|
||||
description: widget.modelManga.description,
|
||||
status: value.status,
|
||||
favorite: _isFavorite,
|
||||
link: widget.modelManga.link,
|
||||
source: widget.modelManga.source,
|
||||
lang: widget.modelManga.lang,
|
||||
dateAdded: widget.modelManga.dateAdded,
|
||||
lastUpdate: DateTime.now().microsecondsSinceEpoch,
|
||||
chapters: chapters,
|
||||
categories: widget.modelManga.categories,
|
||||
lastRead: widget.modelManga.lastRead);
|
||||
ref.watch(hiveBoxMangaProvider).put(
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
model);
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
isOk = true;
|
||||
});
|
||||
}
|
||||
body: mm.when(
|
||||
data: (data) {
|
||||
// final mang = data.where((element) => element.id==widget.idManga).toList().first;
|
||||
return MangaDetailsView(
|
||||
modelManga: data!,
|
||||
isFavorite: (value) {
|
||||
setState(() {
|
||||
_isFavorite = value;
|
||||
});
|
||||
await Future.doWhile(() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
if (isOk == true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: ValueListenableBuilder<Box<ModelManga>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
final entries = value.values
|
||||
.where((element) =>
|
||||
'${element.lang}-${element.link}' ==
|
||||
'${widget.modelManga.lang}-${widget.modelManga.link}')
|
||||
.toList();
|
||||
if (entries.isNotEmpty) {
|
||||
return MangaDetailsView(
|
||||
modelManga: entries[0],
|
||||
isFavorite: (value) {
|
||||
setState(() {
|
||||
_isFavorite = value;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
return MangaDetailsView(
|
||||
modelManga: widget.modelManga,
|
||||
isFavorite: (value) {
|
||||
setState(() {
|
||||
_isFavorite = value;
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
},
|
||||
error: (Object error, StackTrace stackTrace) {
|
||||
return Text("data");
|
||||
},
|
||||
loading: () {
|
||||
return Text("eeee");
|
||||
},
|
||||
)
|
||||
|
||||
// RefreshIndicator(
|
||||
// onRefresh: () async {
|
||||
// if (_isFavorite) {
|
||||
// // bool isOk = false;
|
||||
// // ref
|
||||
// // .watch(getMangaDetailProvider(
|
||||
// // imageUrl: widget.modelManga.imageUrl!,
|
||||
// // lang: widget.modelManga.lang!,
|
||||
// // title: widget.modelManga.name!,
|
||||
// // source: widget.modelManga.source!,
|
||||
// // url: widget.modelManga.link!)
|
||||
// // .future)
|
||||
// // .then((value) {
|
||||
// // if (value.chapters.isNotEmpty &&
|
||||
// // value.chapters.length > widget.modelManga.chapters!.length) {
|
||||
// // List<ModelChapters>? chapters = [];
|
||||
// // for (var chap in widget.modelManga.chapters!) {
|
||||
// // chapters.add(chap);
|
||||
// // }
|
||||
// // int newChapsSize =
|
||||
// // value.chapters.length - widget.modelManga.chapters!.length;
|
||||
// // for (var i = 0; i < newChapsSize; i++) {
|
||||
// // chapters.insert(i, value.chapters[i]);
|
||||
// // }
|
||||
// // final model = ModelManga(
|
||||
// // imageUrl: widget.modelManga.imageUrl,
|
||||
// // name: widget.modelManga.name,
|
||||
// // genre: widget.modelManga.genre,
|
||||
// // author: widget.modelManga.author,
|
||||
// // description: widget.modelManga.description,
|
||||
// // status: value.status,
|
||||
// // favorite: _isFavorite,
|
||||
// // link: widget.modelManga.link,
|
||||
// // source: widget.modelManga.source,
|
||||
// // lang: widget.modelManga.lang,
|
||||
// // dateAdded: widget.modelManga.dateAdded,
|
||||
// // lastUpdate: DateTime.now().microsecondsSinceEpoch,
|
||||
// // chapters: chapters,
|
||||
// // categories: widget.modelManga.categories,
|
||||
// // lastRead: widget.modelManga.lastRead);
|
||||
// // ref.watch(hiveBoxMangaProvider).put(
|
||||
// // '${widget.modelManga.lang}-${widget.modelManga.link}',
|
||||
// // model);
|
||||
// // }
|
||||
// // if (mounted) {
|
||||
// // setState(() {
|
||||
// // isOk = true;
|
||||
// // });
|
||||
// // }
|
||||
// // });
|
||||
// // await Future.doWhile(() async {
|
||||
// // await Future.delayed(const Duration(seconds: 1));
|
||||
// // if (isOk == true) {
|
||||
// // return false;
|
||||
// // }
|
||||
// // return true;
|
||||
// // });
|
||||
// }
|
||||
// },
|
||||
// child:
|
||||
|
||||
// // ValueListenableBuilder<ModelManga>(
|
||||
// // valueListenable: ref.watch(hiveBoxMangaProvider).listenable(),
|
||||
// // builder: (context, value, child) {
|
||||
// // final entries = value.values
|
||||
// // .where((element) =>
|
||||
// // '${element.lang}-${element.link}' ==
|
||||
// // '${widget.modelManga.lang}-${widget.modelManga.link}')
|
||||
// // .toList();
|
||||
// // if (entries.isNotEmpty) {
|
||||
// // return MangaDetailsView(
|
||||
// // modelManga: entries[0],
|
||||
// // isFavorite: (value) {
|
||||
// // setState(() {
|
||||
// // _isFavorite = value;
|
||||
// // });
|
||||
// // },
|
||||
// // );
|
||||
// // }
|
||||
// // return MangaDetailsView(
|
||||
// // modelManga: widget.modelManga,
|
||||
// // isFavorite: (value) {
|
||||
// // setState(() {
|
||||
// // _isFavorite = value;
|
||||
// // });
|
||||
// // },
|
||||
// // );
|
||||
// // },
|
||||
// // ),
|
||||
// ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/views/manga/download/providers/download_provider.dart';
|
||||
|
|
@ -17,7 +19,8 @@ class ChapterModelState extends _$ChapterModelState {
|
|||
isBookmarked: false,
|
||||
scanlator: "",
|
||||
isRead: false,
|
||||
lastPageRead: "");
|
||||
lastPageRead: "",
|
||||
mangaId: null);
|
||||
}
|
||||
|
||||
void update(ModelChapters chapters) {
|
||||
|
|
@ -26,13 +29,13 @@ class ChapterModelState extends _$ChapterModelState {
|
|||
}
|
||||
|
||||
@riverpod
|
||||
class ChapterNameListState extends _$ChapterNameListState {
|
||||
class ChapterIdsListState extends _$ChapterIdsListState {
|
||||
@override
|
||||
List<String> build() {
|
||||
List<ModelChapters> build() {
|
||||
return [];
|
||||
}
|
||||
|
||||
void update(String value) {
|
||||
void update(ModelChapters value) {
|
||||
var newList = state.reversed.toList();
|
||||
if (newList.contains(value)) {
|
||||
newList.remove(value);
|
||||
|
|
@ -45,7 +48,7 @@ class ChapterNameListState extends _$ChapterNameListState {
|
|||
state = newList;
|
||||
}
|
||||
|
||||
void selectAll(String value) {
|
||||
void selectAll(ModelChapters value) {
|
||||
var newList = state.reversed.toList();
|
||||
if (!newList.contains(value)) {
|
||||
newList.add(value);
|
||||
|
|
@ -54,7 +57,7 @@ class ChapterNameListState extends _$ChapterNameListState {
|
|||
state = newList;
|
||||
}
|
||||
|
||||
void selectSome(String value) {
|
||||
void selectSome(ModelChapters value) {
|
||||
var newList = state.reversed.toList();
|
||||
if (newList.contains(value)) {
|
||||
newList.remove(value);
|
||||
|
|
@ -167,26 +170,26 @@ class ChapterFilterDownloadedState extends _$ChapterFilterDownloadedState {
|
|||
ModelManga getData() {
|
||||
if (getType() == 1) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(element.name, defaultValue: null);
|
||||
return modelChapDownload != null &&
|
||||
modelChapDownload.isDownload == true;
|
||||
}).toList();
|
||||
// chap = modelManga.chapters.where((element) {
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(element.name, defaultValue: null);
|
||||
// return modelChapDownload != null &&
|
||||
// modelChapDownload.isDownload == true;
|
||||
// }).toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
||||
return model;
|
||||
} else if (getType() == 2) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(element.name, defaultValue: null);
|
||||
return !(modelChapDownload != null &&
|
||||
modelChapDownload.isDownload == true);
|
||||
}).toList();
|
||||
// chap = modelManga.chapters.where((element) {
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(element.name, defaultValue: null);
|
||||
// return !(modelChapDownload != null &&
|
||||
// modelChapDownload.isDownload == true);
|
||||
// }).toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
||||
|
|
@ -199,26 +202,26 @@ class ChapterFilterDownloadedState extends _$ChapterFilterDownloadedState {
|
|||
ModelManga update() {
|
||||
if (state == 0) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(element.name, defaultValue: null);
|
||||
return modelChapDownload != null &&
|
||||
modelChapDownload.isDownload == true;
|
||||
}).toList();
|
||||
// chap = modelManga.chapters!.where((element) {
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(element.name, defaultValue: null);
|
||||
// return modelChapDownload != null &&
|
||||
// modelChapDownload.isDownload == true;
|
||||
// }).toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
setType(1);
|
||||
return model;
|
||||
} else if (state == 1) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) {
|
||||
final modelChapDownload = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.get(element.name, defaultValue: null);
|
||||
return !(modelChapDownload != null &&
|
||||
modelChapDownload.isDownload == true);
|
||||
}).toList();
|
||||
// chap = modelManga.chapters!.where((element) {
|
||||
// final modelChapDownload = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .get(element.name, defaultValue: null);
|
||||
// return !(modelChapDownload != null &&
|
||||
// modelChapDownload.isDownload == true);
|
||||
// }).toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
setType(2);
|
||||
|
|
@ -253,14 +256,18 @@ class ChapterFilterUnreadState extends _$ChapterFilterUnreadState {
|
|||
ModelManga getData() {
|
||||
if (getType() == 1) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) => !element.isRead).toList();
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isRead == false)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
||||
return model;
|
||||
} else if (getType() == 2) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) => element.isRead).toList();
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isRead == true)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
||||
|
|
@ -273,14 +280,18 @@ class ChapterFilterUnreadState extends _$ChapterFilterUnreadState {
|
|||
ModelManga update() {
|
||||
if (state == 0) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) => !element.isRead).toList();
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isRead == false)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
setType(1);
|
||||
return model;
|
||||
} else if (state == 1) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!.where((element) => element.isRead).toList();
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isRead == false)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
setType(2);
|
||||
|
|
@ -315,16 +326,16 @@ class ChapterFilterBookmarkedState extends _$ChapterFilterBookmarkedState {
|
|||
ModelManga getData() {
|
||||
if (getType() == 1) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!
|
||||
.where((element) => element.isBookmarked)
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isBookmarked == true)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
return model;
|
||||
} else if (getType() == 2) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!
|
||||
.where((element) => !element.isBookmarked)
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isBookmarked == false)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
|
@ -338,8 +349,8 @@ class ChapterFilterBookmarkedState extends _$ChapterFilterBookmarkedState {
|
|||
ModelManga update() {
|
||||
if (state == 0) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!
|
||||
.where((element) => element.isBookmarked)
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isBookmarked == true)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
|
@ -347,8 +358,8 @@ class ChapterFilterBookmarkedState extends _$ChapterFilterBookmarkedState {
|
|||
return model;
|
||||
} else if (state == 1) {
|
||||
List<ModelChapters> chap = [];
|
||||
chap = modelManga.chapters!
|
||||
.where((element) => !element.isBookmarked)
|
||||
chap = modelManga.chapters
|
||||
.where((element) => element.isBookmarked == false)
|
||||
.toList();
|
||||
final model =
|
||||
modelMangaWithNewChapValue(modelManga: modelManga, chapters: chap);
|
||||
|
|
@ -380,7 +391,7 @@ class ChapterFilterResultState extends _$ChapterFilterResultState {
|
|||
.read(chapterFilterBookmarkedStateProvider(modelManga: data2).notifier)
|
||||
.getData();
|
||||
if (indexSelected == 0) {
|
||||
data3.chapters!.sort(
|
||||
data3.chapters.toList().sort(
|
||||
(a, b) {
|
||||
return b.scanlator!.compareTo(a.scanlator!);
|
||||
},
|
||||
|
|
@ -392,7 +403,7 @@ class ChapterFilterResultState extends _$ChapterFilterResultState {
|
|||
// },
|
||||
// );
|
||||
} else {
|
||||
data3.chapters!.sort(
|
||||
data3.chapters.toList().sort(
|
||||
(a, b) {
|
||||
return a.dateUpload!.compareTo(b.dateUpload!);
|
||||
},
|
||||
|
|
@ -430,7 +441,6 @@ ModelManga modelMangaWithNewChapValue(
|
|||
lang: modelManga.lang,
|
||||
dateAdded: modelManga.dateAdded,
|
||||
lastUpdate: modelManga.lastUpdate,
|
||||
chapters: chapters,
|
||||
categories: modelManga.categories,
|
||||
lastRead: modelManga.lastRead);
|
||||
}
|
||||
|
|
@ -440,17 +450,17 @@ class ChapterSetIsBookmarkState extends _$ChapterSetIsBookmarkState {
|
|||
@override
|
||||
build({required ModelManga modelManga}) {}
|
||||
|
||||
set() {
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
for (var name in ref.watch(chapterNameListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters!.length; i++) {
|
||||
modelManga.chapters![i].isBookmarked =
|
||||
name == "${modelManga.chapters![i].name}$i"
|
||||
? !modelManga.chapters![i].isBookmarked
|
||||
: modelManga.chapters![i].isBookmarked;
|
||||
set() async {
|
||||
final chapters = ref.watch(chapterIdsListStateProvider);
|
||||
await isar.writeTxn(() async {
|
||||
for (var chapter in chapters) {
|
||||
chapter.isBookmarked = !chapter.isBookmarked!;
|
||||
await isar.modelChapters.put(chapter..manga.value = modelManga);
|
||||
await chapter.manga.save();
|
||||
}
|
||||
modelManga.save();
|
||||
}
|
||||
});
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
ref.read(chapterIdsListStateProvider.notifier).clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -459,17 +469,17 @@ class ChapterSetIsReadState extends _$ChapterSetIsReadState {
|
|||
@override
|
||||
build({required ModelManga modelManga}) {}
|
||||
|
||||
set() {
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
for (var name in ref.watch(chapterNameListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters!.length; i++) {
|
||||
modelManga.chapters![i].isRead =
|
||||
name == "${modelManga.chapters![i].name}$i"
|
||||
? !modelManga.chapters![i].isRead
|
||||
: modelManga.chapters![i].isRead;
|
||||
set() async {
|
||||
final chapters = ref.watch(chapterIdsListStateProvider);
|
||||
await isar.writeTxn(() async {
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = !chapter.isRead!;
|
||||
await isar.modelChapters.put(chapter..manga.value = modelManga);
|
||||
await chapter.manga.save();
|
||||
}
|
||||
modelManga.save();
|
||||
}
|
||||
});
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
ref.read(chapterIdsListStateProvider.notifier).clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -481,30 +491,31 @@ class ChapterSetDownloadState extends _$ChapterSetDownloadState {
|
|||
set() {
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
List<int> indexList = [];
|
||||
for (var name in ref.watch(chapterNameListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters!.length; i++) {
|
||||
if ("${modelManga.chapters![i].name}$i" == name) {
|
||||
for (var name in ref.watch(chapterIdsListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters.length; i++) {
|
||||
if ("$i" == name) {
|
||||
indexList.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var idx in indexList) {
|
||||
final entries = ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.values
|
||||
.where((element) =>
|
||||
element.modelManga.chapters![element.index].name ==
|
||||
modelManga.chapters![idx].name)
|
||||
.toList();
|
||||
if (entries.isEmpty) {
|
||||
ref.watch(downloadChapterProvider(modelManga: modelManga, index: idx));
|
||||
} else {
|
||||
if (!entries.first.isDownload) {
|
||||
ref.watch(
|
||||
downloadChapterProvider(modelManga: modelManga, index: idx));
|
||||
}
|
||||
}
|
||||
// final entries = ref
|
||||
// .watch(hiveBoxMangaDownloadsProvider)
|
||||
// .values
|
||||
// .where((element) =>
|
||||
// element.modelManga.chapters.toList()[element.index].name ==
|
||||
// modelManga.chapters.toList()[idx].name)
|
||||
// .toList();
|
||||
// if (entries.isEmpty) {
|
||||
// // ref.watch(downloadChapterProvider(modelManga: modelManga, index: idx));
|
||||
// } else {
|
||||
// if (!entries.first.isDownload) {
|
||||
// // ref.watch(
|
||||
// // downloadChapterProvider(modelManga: modelManga, index: idx));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
ref.read(chapterIdsListStateProvider.notifier).clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'state_providers.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$chapterModelStateHash() => r'39804350aba3fc457cb2ddcda25c1ca41069a537';
|
||||
String _$chapterModelStateHash() => r'd36dd66381770f0e710929ae95ed100828c8d9ae';
|
||||
|
||||
/// See also [ChapterModelState].
|
||||
@ProviderFor(ChapterModelState)
|
||||
|
|
@ -22,23 +22,23 @@ final chapterModelStateProvider =
|
|||
);
|
||||
|
||||
typedef _$ChapterModelState = AutoDisposeNotifier<ModelChapters>;
|
||||
String _$chapterNameListStateHash() =>
|
||||
r'7ad81711d912271910489528b88b8d473c1d9c60';
|
||||
String _$chapterIdsListStateHash() =>
|
||||
r'0cfdc515b7c2086eea593eba19ccd0b1f2ecdcd6';
|
||||
|
||||
/// See also [ChapterNameListState].
|
||||
@ProviderFor(ChapterNameListState)
|
||||
final chapterNameListStateProvider =
|
||||
AutoDisposeNotifierProvider<ChapterNameListState, List<String>>.internal(
|
||||
ChapterNameListState.new,
|
||||
name: r'chapterNameListStateProvider',
|
||||
/// See also [ChapterIdsListState].
|
||||
@ProviderFor(ChapterIdsListState)
|
||||
final chapterIdsListStateProvider = AutoDisposeNotifierProvider<
|
||||
ChapterIdsListState, List<ModelChapters>>.internal(
|
||||
ChapterIdsListState.new,
|
||||
name: r'chapterIdsListStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$chapterNameListStateHash,
|
||||
: _$chapterIdsListStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$ChapterNameListState = AutoDisposeNotifier<List<String>>;
|
||||
typedef _$ChapterIdsListState = AutoDisposeNotifier<List<ModelChapters>>;
|
||||
String _$isLongPressedStateHash() =>
|
||||
r'26fe435e8381046a30e3f6c4495303946aa3aaa7';
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ final isExtendedStateProvider =
|
|||
|
||||
typedef _$IsExtendedState = AutoDisposeNotifier<bool>;
|
||||
String _$reverseChapterStateHash() =>
|
||||
r'7fb5d8f60f32377ca365eb328f989e31569c8b19';
|
||||
r'd7f4d869e7c4bbceaee361bf790d4e8bba7df30e';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -193,7 +193,7 @@ class ReverseChapterStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterDownloadedStateHash() =>
|
||||
r'6b433670cf840fe1e8166ae5b7a4fe17c9b56b5d';
|
||||
r'33e96291f58f4ddfb1271c44ab06032da80e7c58';
|
||||
|
||||
abstract class _$ChapterFilterDownloadedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -293,7 +293,7 @@ class ChapterFilterDownloadedStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterUnreadStateHash() =>
|
||||
r'ee96d8e6b3f145096e00ff3c09fda07d5f968047';
|
||||
r'bcd0a645901a80401affe5bf08d92244e3324832';
|
||||
|
||||
abstract class _$ChapterFilterUnreadState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -392,7 +392,7 @@ class ChapterFilterUnreadStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterBookmarkedStateHash() =>
|
||||
r'f9761f9a32d0d6af53f513f862476a7125054ce7';
|
||||
r'2f7d04afd075d55b6d7849ed312bc40fcfd35e05';
|
||||
|
||||
abstract class _$ChapterFilterBookmarkedState
|
||||
extends BuildlessAutoDisposeNotifier<int> {
|
||||
|
|
@ -492,7 +492,7 @@ class ChapterFilterBookmarkedStateProvider
|
|||
}
|
||||
|
||||
String _$chapterFilterResultStateHash() =>
|
||||
r'a0c0bccb457db8ccfba52e2b7e36a1f6e2b6afe3';
|
||||
r'2efadc2a20b1b7ffde1ce95da77e52b9930a5543';
|
||||
|
||||
abstract class _$ChapterFilterResultState
|
||||
extends BuildlessAutoDisposeNotifier<ModelManga> {
|
||||
|
|
@ -591,7 +591,7 @@ class ChapterFilterResultStateProvider extends AutoDisposeNotifierProviderImpl<
|
|||
}
|
||||
|
||||
String _$chapterSetIsBookmarkStateHash() =>
|
||||
r'c12ed82216c7a649b9937226d841e413209ec704';
|
||||
r'd52ed51da1434f4192f99e316279414011a51200';
|
||||
|
||||
abstract class _$ChapterSetIsBookmarkState
|
||||
extends BuildlessAutoDisposeNotifier<dynamic> {
|
||||
|
|
@ -690,7 +690,7 @@ class ChapterSetIsBookmarkStateProvider extends AutoDisposeNotifierProviderImpl<
|
|||
}
|
||||
|
||||
String _$chapterSetIsReadStateHash() =>
|
||||
r'2976cee969928c8ce433e173e53ba67e6ee49d6d';
|
||||
r'88a5f68d8d24924f6399cb86347150669a725211';
|
||||
|
||||
abstract class _$ChapterSetIsReadState
|
||||
extends BuildlessAutoDisposeNotifier<dynamic> {
|
||||
|
|
@ -789,7 +789,7 @@ class ChapterSetIsReadStateProvider
|
|||
}
|
||||
|
||||
String _$chapterSetDownloadStateHash() =>
|
||||
r'cc003f376668ea8b1c8f3f6d03190f72d172f55e';
|
||||
r'b74fbabed0abb3abbebd50c6f1af789b13af3f97';
|
||||
|
||||
abstract class _$ChapterSetDownloadState
|
||||
extends BuildlessAutoDisposeNotifier<dynamic> {
|
||||
|
|
|
|||
|
|
@ -10,79 +10,57 @@ import 'package:mangayomi/views/manga/detail/providers/state_providers.dart';
|
|||
import 'package:mangayomi/views/manga/download/download_page_widget.dart';
|
||||
|
||||
class ChapterListTileWidget extends ConsumerWidget {
|
||||
final List<ModelChapters> chapters;
|
||||
final ModelManga modelManga;
|
||||
final bool reverse;
|
||||
final int reverseIndex;
|
||||
final int finalIndex;
|
||||
|
||||
final ModelChapters chapter;
|
||||
final int chapterIndex;
|
||||
final List<ModelChapters> chapterNameList;
|
||||
const ChapterListTileWidget({
|
||||
required this.chapterNameList,
|
||||
required this.chapter,
|
||||
required this.chapterIndex,
|
||||
super.key,
|
||||
required this.chapters,
|
||||
required this.modelManga,
|
||||
required this.reverse,
|
||||
required this.reverseIndex,
|
||||
required this.finalIndex,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final idx = reverse ? reverseIndex : finalIndex;
|
||||
final chapterNameList = ref.watch(chapterNameListStateProvider);
|
||||
log(chapterNameList.toString());
|
||||
final chapterName = modelManga.chapters![idx].name;
|
||||
return Container(
|
||||
color: chapterNameList.contains("$chapterName$idx")
|
||||
color: chapterNameList.contains(chapter)
|
||||
? primaryColor(context).withOpacity(0.4)
|
||||
: null,
|
||||
child: ListTile(
|
||||
textColor: chapters[finalIndex].isRead
|
||||
textColor: chapter.isRead!
|
||||
? isLight(context)
|
||||
? Colors.black.withOpacity(0.4)
|
||||
: Colors.white.withOpacity(0.3)
|
||||
: null,
|
||||
selectedColor: chapters[finalIndex].isRead
|
||||
? Colors.white.withOpacity(0.3)
|
||||
: Colors.white,
|
||||
selectedColor:
|
||||
chapter.isRead! ? Colors.white.withOpacity(0.3) : Colors.white,
|
||||
onLongPress: () {
|
||||
if (!isLongPressed) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.update("$chapterName$idx");
|
||||
ref
|
||||
.read(chapterModelStateProvider.notifier)
|
||||
.update(chapters[finalIndex]);
|
||||
ref.read(chapterIdsListStateProvider.notifier).update(chapter);
|
||||
ref.read(chapterModelStateProvider.notifier).update(chapter);
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.update("$chapterName$idx");
|
||||
ref
|
||||
.read(chapterModelStateProvider.notifier)
|
||||
.update(chapters[finalIndex]);
|
||||
ref.read(chapterIdsListStateProvider.notifier).update(chapter);
|
||||
ref.read(chapterModelStateProvider.notifier).update(chapter);
|
||||
}
|
||||
},
|
||||
onTap: () async {
|
||||
if (isLongPressed) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.update("$chapterName$idx");
|
||||
ref
|
||||
.read(chapterModelStateProvider.notifier)
|
||||
.update(chapters[finalIndex]);
|
||||
ref.read(chapterIdsListStateProvider.notifier).update(chapter);
|
||||
ref.read(chapterModelStateProvider.notifier).update(chapter);
|
||||
} else {
|
||||
pushMangaReaderView(
|
||||
context: context,
|
||||
modelManga: modelManga,
|
||||
index: reverse ? reverseIndex : finalIndex);
|
||||
context: context, modelManga: modelManga, index: chapterIndex);
|
||||
}
|
||||
},
|
||||
title: Row(
|
||||
children: [
|
||||
chapters[finalIndex].isBookmarked
|
||||
chapter.isBookmarked!
|
||||
? Icon(
|
||||
Icons.bookmark,
|
||||
size: 15,
|
||||
|
|
@ -91,7 +69,7 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
: Container(),
|
||||
Flexible(
|
||||
child: Text(
|
||||
chapters[finalIndex].name!,
|
||||
chapter.name!,
|
||||
style: const TextStyle(fontSize: 13),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
|
@ -101,16 +79,15 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
subtitle: Row(
|
||||
children: [
|
||||
Text(
|
||||
chapters[finalIndex].dateUpload!,
|
||||
chapter.dateUpload!,
|
||||
style: const TextStyle(fontSize: 11),
|
||||
),
|
||||
if (chapters[finalIndex].lastPageRead.isNotEmpty &&
|
||||
chapters[finalIndex].lastPageRead != "1")
|
||||
if (chapter.lastPageRead!.isNotEmpty && chapter.lastPageRead != "1")
|
||||
Row(
|
||||
children: [
|
||||
const Text(' • '),
|
||||
Text(
|
||||
"Page ${chapters[finalIndex].lastPageRead}",
|
||||
"Page ${chapter.lastPageRead}",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: isLight(context)
|
||||
|
|
@ -119,15 +96,15 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (chapters[finalIndex].scanlator!.isNotEmpty)
|
||||
if (chapter.scanlator!.isNotEmpty)
|
||||
Row(
|
||||
children: [
|
||||
const Text(' • '),
|
||||
Text(
|
||||
chapters[finalIndex].scanlator!,
|
||||
chapter.scanlator!,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: chapters[finalIndex].isRead
|
||||
color: chapter.isRead!
|
||||
? isLight(context)
|
||||
? Colors.black.withOpacity(0.4)
|
||||
: Colors.white.withOpacity(0.3)
|
||||
|
|
@ -138,8 +115,9 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
],
|
||||
),
|
||||
trailing: ref.watch(ChapterPageDownloadsProvider(
|
||||
index: reverse ? reverseIndex : finalIndex,
|
||||
modelManga: modelManga)),
|
||||
chapterIndex: chapterIndex,
|
||||
modelManga: modelManga,
|
||||
chapterId: chapter.id!)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
part 'download_model.g.dart';
|
||||
|
||||
@HiveType(typeId: 6)
|
||||
class DownloadModel {
|
||||
@HiveField(0)
|
||||
final ModelManga modelManga;
|
||||
@HiveField(1)
|
||||
final int index;
|
||||
@HiveField(2)
|
||||
final int succeeded;
|
||||
@HiveField(3)
|
||||
final int failed;
|
||||
@HiveField(4)
|
||||
final int total;
|
||||
@HiveField(6)
|
||||
final bool isDownload;
|
||||
@HiveField(7)
|
||||
final List taskIds;
|
||||
@HiveField(8)
|
||||
final bool isStartDownload;
|
||||
DownloadModel(
|
||||
{required this.modelManga,
|
||||
required this.succeeded,
|
||||
required this.failed,
|
||||
required this.index,
|
||||
required this.total,
|
||||
required this.isDownload,
|
||||
required this.taskIds,
|
||||
required this.isStartDownload});
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import 'package:mangayomi/providers/storage_provider.dart';
|
|||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/views/manga/download/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/model/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/providers/download_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'download_page_widget.g.dart';
|
||||
|
|
@ -15,21 +15,27 @@ part 'download_page_widget.g.dart';
|
|||
@riverpod
|
||||
class ChapterPageDownloads extends _$ChapterPageDownloads {
|
||||
@override
|
||||
Widget build({required ModelManga modelManga, required int index}) {
|
||||
Widget build(
|
||||
{required ModelManga modelManga,
|
||||
required int chapterIndex,
|
||||
required int chapterId}) {
|
||||
return ChapterPageDownload(
|
||||
index: index,
|
||||
chapterId: chapterId,
|
||||
chapterIndex: chapterIndex,
|
||||
modelManga: modelManga,
|
||||
);
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
class ChapterPageDownload extends ConsumerStatefulWidget {
|
||||
final ModelManga modelManga;
|
||||
final int index;
|
||||
final int chapterId;
|
||||
final int chapterIndex;
|
||||
const ChapterPageDownload(
|
||||
{super.key, required this.modelManga, required this.index});
|
||||
{super.key,
|
||||
required this.modelManga,
|
||||
required this.chapterId,
|
||||
required this.chapterIndex});
|
||||
|
||||
@override
|
||||
ConsumerState createState() => _ChapterPageDownloadState();
|
||||
|
|
@ -42,7 +48,9 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
final StorageProvider _storageProvider = StorageProvider();
|
||||
_startDownload() async {
|
||||
final data = await ref.watch(downloadChapterProvider(
|
||||
modelManga: widget.modelManga, index: widget.index)
|
||||
modelManga: widget.modelManga,
|
||||
chapterId: widget.chapterId,
|
||||
chapterIndex: widget.chapterIndex)
|
||||
.future);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
|
@ -53,16 +61,16 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
|
||||
_deleteFile(List pageUrl) async {
|
||||
final path = await _storageProvider.getMangaChapterDirectory(
|
||||
widget.modelManga, widget.index);
|
||||
widget.modelManga, widget.chapterIndex);
|
||||
|
||||
try {
|
||||
path!.deleteSync(recursive: true);
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
widget.modelManga.chapters![widget.index].name!,
|
||||
widget.modelManga.chapters.toList()[widget.chapterIndex].name!,
|
||||
);
|
||||
} catch (e) {
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
widget.modelManga.chapters![widget.index].name!,
|
||||
widget.modelManga.chapters.toList()[widget.chapterIndex].name!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -82,8 +90,8 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
builder: (context, val, child) {
|
||||
final entries = val.values
|
||||
.where((element) =>
|
||||
"${element.modelManga.chapters![element.index].name}${element.index}" ==
|
||||
"${widget.modelManga.chapters![widget.index].name}${widget.index}")
|
||||
"${element.chapterName}${element.chapterIndex}${element.chapterId}" ==
|
||||
"${widget.modelManga.chapters.toList()[widget.chapterIndex].name!}${widget.chapterIndex}${widget.chapterId}")
|
||||
.toList();
|
||||
|
||||
if (entries.isNotEmpty) {
|
||||
|
|
@ -216,7 +224,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
.watch(
|
||||
hiveBoxMangaDownloadsProvider)
|
||||
.delete(
|
||||
"${widget.modelManga.chapters![widget.index].name}${widget.index}",
|
||||
"${widget.modelManga.chapters.toList()[widget.chapterIndex].name}${widget.chapterIndex}${widget.chapterId}",
|
||||
);
|
||||
_startDownload();
|
||||
setState(() {
|
||||
|
|
@ -274,7 +282,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
FileDownloader().cancelTasksWithIds(taskIds).then((value) async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
"${widget.modelManga.chapters![widget.index].name}${widget.index}",
|
||||
"${widget.modelManga.chapters.toList()[widget.chapterIndex].name}${widget.chapterIndex}${widget.chapterId}",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ part of 'download_page_widget.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$chapterPageDownloadsHash() =>
|
||||
r'0b3eaf9a3ca4786287616a87e5de62af24259b68';
|
||||
r'682bf480c3b8e3ccda792661746e5fba24755526';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -33,11 +33,13 @@ class _SystemHash {
|
|||
abstract class _$ChapterPageDownloads
|
||||
extends BuildlessAutoDisposeNotifier<Widget> {
|
||||
late final ModelManga modelManga;
|
||||
late final int index;
|
||||
late final int chapterIndex;
|
||||
late final int chapterId;
|
||||
|
||||
Widget build({
|
||||
required ModelManga modelManga,
|
||||
required int index,
|
||||
required int chapterIndex,
|
||||
required int chapterId,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -53,11 +55,13 @@ class ChapterPageDownloadsFamily extends Family<Widget> {
|
|||
/// See also [ChapterPageDownloads].
|
||||
ChapterPageDownloadsProvider call({
|
||||
required ModelManga modelManga,
|
||||
required int index,
|
||||
required int chapterIndex,
|
||||
required int chapterId,
|
||||
}) {
|
||||
return ChapterPageDownloadsProvider(
|
||||
modelManga: modelManga,
|
||||
index: index,
|
||||
chapterIndex: chapterIndex,
|
||||
chapterId: chapterId,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +71,8 @@ class ChapterPageDownloadsFamily extends Family<Widget> {
|
|||
) {
|
||||
return call(
|
||||
modelManga: provider.modelManga,
|
||||
index: provider.index,
|
||||
chapterIndex: provider.chapterIndex,
|
||||
chapterId: provider.chapterId,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -92,11 +97,13 @@ class ChapterPageDownloadsProvider
|
|||
/// See also [ChapterPageDownloads].
|
||||
ChapterPageDownloadsProvider({
|
||||
required this.modelManga,
|
||||
required this.index,
|
||||
required this.chapterIndex,
|
||||
required this.chapterId,
|
||||
}) : super.internal(
|
||||
() => ChapterPageDownloads()
|
||||
..modelManga = modelManga
|
||||
..index = index,
|
||||
..chapterIndex = chapterIndex
|
||||
..chapterId = chapterId,
|
||||
from: chapterPageDownloadsProvider,
|
||||
name: r'chapterPageDownloadsProvider',
|
||||
debugGetCreateSourceHash:
|
||||
|
|
@ -109,20 +116,23 @@ class ChapterPageDownloadsProvider
|
|||
);
|
||||
|
||||
final ModelManga modelManga;
|
||||
final int index;
|
||||
final int chapterIndex;
|
||||
final int chapterId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is ChapterPageDownloadsProvider &&
|
||||
other.modelManga == modelManga &&
|
||||
other.index == index;
|
||||
other.chapterIndex == chapterIndex &&
|
||||
other.chapterId == chapterId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, modelManga.hashCode);
|
||||
hash = _SystemHash.combine(hash, index.hashCode);
|
||||
hash = _SystemHash.combine(hash, chapterIndex.hashCode);
|
||||
hash = _SystemHash.combine(hash, chapterId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
|
|
@ -133,7 +143,8 @@ class ChapterPageDownloadsProvider
|
|||
) {
|
||||
return notifier.build(
|
||||
modelManga: modelManga,
|
||||
index: index,
|
||||
chapterIndex: chapterIndex,
|
||||
chapterId: chapterId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
lib/views/manga/download/model/download_model.dart
Normal file
42
lib/views/manga/download/model/download_model.dart
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
||||
part 'download_model.g.dart';
|
||||
|
||||
@HiveType(typeId: 6)
|
||||
class DownloadModel extends HiveObject {
|
||||
@HiveField(0)
|
||||
final int chapterIndex;
|
||||
@HiveField(1)
|
||||
final int succeeded;
|
||||
@HiveField(2)
|
||||
final int failed;
|
||||
@HiveField(3)
|
||||
final int total;
|
||||
@HiveField(4)
|
||||
final bool isDownload;
|
||||
@HiveField(5)
|
||||
final List taskIds;
|
||||
@HiveField(6)
|
||||
final bool isStartDownload;
|
||||
@HiveField(7)
|
||||
final int? chapterId;
|
||||
@HiveField(9)
|
||||
final String? mangaSource;
|
||||
@HiveField(10)
|
||||
final String? chapterName;
|
||||
@HiveField(11)
|
||||
final String? mangaName;
|
||||
DownloadModel({
|
||||
required this.chapterId,
|
||||
required this.succeeded,
|
||||
required this.failed,
|
||||
required this.chapterIndex,
|
||||
required this.total,
|
||||
required this.isDownload,
|
||||
required this.taskIds,
|
||||
required this.isStartDownload,
|
||||
required this.mangaSource,
|
||||
required this.chapterName,
|
||||
required this.mangaName,
|
||||
});
|
||||
}
|
||||
|
|
@ -17,37 +17,46 @@ class DownloadModelAdapter extends TypeAdapter<DownloadModel> {
|
|||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return DownloadModel(
|
||||
modelManga: fields[0] as ModelManga,
|
||||
succeeded: fields[2] as int,
|
||||
failed: fields[3] as int,
|
||||
index: fields[1] as int,
|
||||
total: fields[4] as int,
|
||||
isDownload: fields[6] as bool,
|
||||
taskIds: (fields[7] as List).cast<dynamic>(),
|
||||
isStartDownload: fields[8] as bool,
|
||||
chapterId: fields[7] as int?,
|
||||
succeeded: fields[1] as int,
|
||||
failed: fields[2] as int,
|
||||
chapterIndex: fields[0] as int,
|
||||
total: fields[3] as int,
|
||||
isDownload: fields[4] as bool,
|
||||
taskIds: (fields[5] as List).cast<dynamic>(),
|
||||
isStartDownload: fields[6] as bool,
|
||||
mangaSource: fields[9] as String?,
|
||||
chapterName: fields[10] as String?,
|
||||
mangaName: fields[11] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, DownloadModel obj) {
|
||||
writer
|
||||
..writeByte(8)
|
||||
..writeByte(11)
|
||||
..writeByte(0)
|
||||
..write(obj.modelManga)
|
||||
..write(obj.chapterIndex)
|
||||
..writeByte(1)
|
||||
..write(obj.index)
|
||||
..writeByte(2)
|
||||
..write(obj.succeeded)
|
||||
..writeByte(3)
|
||||
..writeByte(2)
|
||||
..write(obj.failed)
|
||||
..writeByte(4)
|
||||
..writeByte(3)
|
||||
..write(obj.total)
|
||||
..writeByte(6)
|
||||
..writeByte(4)
|
||||
..write(obj.isDownload)
|
||||
..writeByte(7)
|
||||
..writeByte(5)
|
||||
..write(obj.taskIds)
|
||||
..writeByte(8)
|
||||
..write(obj.isStartDownload);
|
||||
..writeByte(6)
|
||||
..write(obj.isStartDownload)
|
||||
..writeByte(7)
|
||||
..write(obj.chapterId)
|
||||
..writeByte(9)
|
||||
..write(obj.mangaSource)
|
||||
..writeByte(10)
|
||||
..write(obj.chapterName)
|
||||
..writeByte(11)
|
||||
..write(obj.mangaName);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:background_downloader/background_downloader.dart';
|
||||
|
|
@ -9,13 +10,17 @@ import 'package:mangayomi/services/get_manga_chapter_url.dart';
|
|||
import 'package:mangayomi/utils/constant.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
import 'package:mangayomi/views/manga/download/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/model/download_model.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'download_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
||||
{required ModelManga modelManga, required int index}) async {
|
||||
Future<List<dynamic>> downloadChapter(
|
||||
DownloadChapterRef ref, {
|
||||
required ModelManga modelManga,
|
||||
required int chapterIndex,
|
||||
required int chapterId,
|
||||
}) async {
|
||||
List urll = [];
|
||||
List<DownloadTask> tasks = [];
|
||||
final StorageProvider storageProvider = StorageProvider();
|
||||
|
|
@ -23,16 +28,20 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
Directory? path;
|
||||
bool isOk = false;
|
||||
final path1 = await storageProvider.getDirectory();
|
||||
String scanlator = modelManga.chapters![index].scanlator!.isNotEmpty
|
||||
? "${modelManga.chapters![index].scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
String scanlator = modelManga.chapters
|
||||
.toList()[chapterIndex]
|
||||
.scanlator!
|
||||
.isNotEmpty
|
||||
? "${modelManga.chapters.toList()[chapterIndex].scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
: "";
|
||||
final finalPath =
|
||||
"downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}";
|
||||
"downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${modelManga.chapters.toList()[chapterIndex].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}";
|
||||
path = Directory("${path1!.path}$finalPath/");
|
||||
log(scanlator);
|
||||
ref
|
||||
.read(getMangaChapterUrlProvider(
|
||||
modelManga: modelManga,
|
||||
index: index,
|
||||
index: chapterIndex,
|
||||
).future)
|
||||
.then((value) {
|
||||
if (value.urll.isNotEmpty) {
|
||||
|
|
@ -55,8 +64,6 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
"${path2.path}${modelManga.source} (${modelManga.lang!.toUpperCase()})/");
|
||||
final path3 = Directory(
|
||||
"${path2.path}${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
final path5 = Directory(
|
||||
"${path2.path}${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}");
|
||||
|
||||
if (!(await path1.exists())) {
|
||||
path1.create();
|
||||
|
|
@ -66,7 +73,7 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
File("${path1.path}" ".nomedia").create();
|
||||
}
|
||||
}
|
||||
|
||||
log(path2.path);
|
||||
if (!(await path2.exists())) {
|
||||
path2.create();
|
||||
}
|
||||
|
|
@ -76,9 +83,7 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
if (!(await path3.exists())) {
|
||||
path3.create();
|
||||
}
|
||||
if (!(await path5.exists())) {
|
||||
path5.create();
|
||||
}
|
||||
|
||||
if ((await path.exists())) {
|
||||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg").exists()) {
|
||||
} else {
|
||||
|
|
@ -124,34 +129,41 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
}
|
||||
if (tasks.isEmpty && urll.isNotEmpty) {
|
||||
final model = DownloadModel(
|
||||
modelManga: modelManga,
|
||||
chapterId: chapterId,
|
||||
mangaName: modelManga.name,
|
||||
chapterIndex: chapterIndex,
|
||||
succeeded: 0,
|
||||
failed: 0,
|
||||
index: index,
|
||||
chapterName: modelManga.chapters.toList()[chapterIndex].name!,
|
||||
mangaSource: modelManga.source,
|
||||
total: 0,
|
||||
isDownload: true,
|
||||
taskIds: urll,
|
||||
isStartDownload: false);
|
||||
|
||||
ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.put("${modelManga.chapters![index].name!}$index", model);
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).put(
|
||||
"${modelManga.chapters.toList()[chapterIndex].name!}$chapterIndex$chapterId",
|
||||
model);
|
||||
} else {
|
||||
await FileDownloader().downloadBatch(
|
||||
tasks,
|
||||
batchProgressCallback: (succeeded, failed) {
|
||||
final model = DownloadModel(
|
||||
modelManga: modelManga,
|
||||
succeeded: succeeded,
|
||||
failed: failed,
|
||||
index: index,
|
||||
total: tasks.length,
|
||||
isDownload: (succeeded == tasks.length) ? true : false,
|
||||
taskIds: urll,
|
||||
isStartDownload: true);
|
||||
|
||||
Hive.box<DownloadModel>(HiveConstant.hiveBoxDownloads)
|
||||
.put("${modelManga.chapters![index].name!}$index", model);
|
||||
chapterIndex: chapterIndex,
|
||||
mangaName: modelManga.name,
|
||||
succeeded: succeeded,
|
||||
failed: failed,
|
||||
chapterId: chapterId,
|
||||
total: tasks.length,
|
||||
isDownload: (succeeded == tasks.length) ? true : false,
|
||||
taskIds: urll,
|
||||
isStartDownload: true,
|
||||
chapterName: modelManga.chapters.toList()[chapterIndex].name!,
|
||||
mangaSource: modelManga.source,
|
||||
);
|
||||
Hive.box<DownloadModel>(HiveConstant.hiveBoxDownloads).put(
|
||||
"${modelManga.chapters.toList()[chapterIndex].name!}$chapterIndex$chapterId",
|
||||
model);
|
||||
},
|
||||
taskProgressCallback: (task, progress) async {
|
||||
if (progress == 1.0) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'download_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$downloadChapterHash() => r'982e5db78e716894f63b97598709e29098c3eb8f';
|
||||
String _$downloadChapterHash() => r'19ec35b1bc0db5ebbc91f5ddb456dcac93b840ab';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -43,11 +43,13 @@ class DownloadChapterFamily extends Family<AsyncValue<List<dynamic>>> {
|
|||
/// See also [downloadChapter].
|
||||
DownloadChapterProvider call({
|
||||
required ModelManga modelManga,
|
||||
required int index,
|
||||
required int chapterIndex,
|
||||
required int chapterId,
|
||||
}) {
|
||||
return DownloadChapterProvider(
|
||||
modelManga: modelManga,
|
||||
index: index,
|
||||
chapterIndex: chapterIndex,
|
||||
chapterId: chapterId,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +59,8 @@ class DownloadChapterFamily extends Family<AsyncValue<List<dynamic>>> {
|
|||
) {
|
||||
return call(
|
||||
modelManga: provider.modelManga,
|
||||
index: provider.index,
|
||||
chapterIndex: provider.chapterIndex,
|
||||
chapterId: provider.chapterId,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -81,12 +84,14 @@ class DownloadChapterProvider extends AutoDisposeFutureProvider<List<dynamic>> {
|
|||
/// See also [downloadChapter].
|
||||
DownloadChapterProvider({
|
||||
required this.modelManga,
|
||||
required this.index,
|
||||
required this.chapterIndex,
|
||||
required this.chapterId,
|
||||
}) : super.internal(
|
||||
(ref) => downloadChapter(
|
||||
ref,
|
||||
modelManga: modelManga,
|
||||
index: index,
|
||||
chapterIndex: chapterIndex,
|
||||
chapterId: chapterId,
|
||||
),
|
||||
from: downloadChapterProvider,
|
||||
name: r'downloadChapterProvider',
|
||||
|
|
@ -100,20 +105,23 @@ class DownloadChapterProvider extends AutoDisposeFutureProvider<List<dynamic>> {
|
|||
);
|
||||
|
||||
final ModelManga modelManga;
|
||||
final int index;
|
||||
final int chapterIndex;
|
||||
final int chapterId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is DownloadChapterProvider &&
|
||||
other.modelManga == modelManga &&
|
||||
other.index == index;
|
||||
other.chapterIndex == chapterIndex &&
|
||||
other.chapterId == chapterId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, modelManga.hashCode);
|
||||
hash = _SystemHash.combine(hash, index.hashCode);
|
||||
hash = _SystemHash.combine(hash, chapterIndex.hashCode);
|
||||
hash = _SystemHash.combine(hash, chapterId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ class _MangaChapterPageGalleryState
|
|||
1 !=
|
||||
widget.readerController
|
||||
.getModelManga()
|
||||
.chapters!
|
||||
.chapters
|
||||
.length
|
||||
? Theme.of(context)
|
||||
.textTheme
|
||||
|
|
|
|||
|
|
@ -101,39 +101,41 @@ class ReaderController extends _$ReaderController {
|
|||
void setMangaHistoryUpdate() {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
ref.watch(hiveBoxMangaHistoryProvider).put(
|
||||
'${getModelManga().lang}-${getModelManga().link}',
|
||||
MangaHistoryModel(
|
||||
date: DateTime.now().toString(), modelManga: getModelManga()));
|
||||
// ref.watch(hiveBoxMangaHistoryProvider).put(
|
||||
// '${getModelManga().lang}-${getModelManga().link}',
|
||||
// MangaHistoryModel(
|
||||
// date: DateTime.now().toString(), modelManga: getModelManga()));
|
||||
}
|
||||
}
|
||||
|
||||
void setChapterPageLastRead(int pageIndex) async {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
List<ModelChapters> chapter = getModelManga().chapters!;
|
||||
chapter[getChapterIndex()].lastPageRead = (pageIndex + 1).toString();
|
||||
getModelManga().save();
|
||||
}
|
||||
// if (!incognitoMode) {
|
||||
// List<ModelChapters> chapter = getModelManga().chapters!;
|
||||
// chapter[getChapterIndex()].lastPageRead = (pageIndex + 1).toString();
|
||||
// getModelManga().save();
|
||||
// }
|
||||
}
|
||||
|
||||
void setChapterBookmarked() {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
if (!incognitoMode) {
|
||||
final isBookmarked = getChapterBookmarked();
|
||||
List<ModelChapters> chapter = getModelManga().chapters!;
|
||||
chapter[getChapterIndex()].isBookmarked = !isBookmarked;
|
||||
getModelManga().save();
|
||||
}
|
||||
// if (!incognitoMode) {
|
||||
// final isBookmarked = getChapterBookmarked();
|
||||
// List<ModelChapters> chapter = getModelManga().chapters!;
|
||||
// chapter[getChapterIndex()].isBookmarked = !isBookmarked;
|
||||
// getModelManga().save();
|
||||
// }
|
||||
}
|
||||
|
||||
bool getChapterBookmarked() {
|
||||
return ref
|
||||
.watch(hiveBoxMangaProvider)
|
||||
.get('${getModelManga().lang}-${getModelManga().link}',
|
||||
defaultValue: getModelManga())!
|
||||
.chapters![getChapterIndex()]
|
||||
.isBookmarked;
|
||||
return true;
|
||||
|
||||
// ref
|
||||
// .watch(hiveBoxMangaProvider)
|
||||
// .get('${getModelManga().lang}-${getModelManga().link}',
|
||||
// defaultValue: getModelManga())!
|
||||
// .chapters![getChapterIndex()]
|
||||
// .isBookmarked;
|
||||
}
|
||||
|
||||
int getChapterIndex() {
|
||||
|
|
@ -188,6 +190,6 @@ class ReaderController extends _$ReaderController {
|
|||
}
|
||||
|
||||
String getChapterTitle() {
|
||||
return getModelManga().chapters![mangaReaderModel.index].name!;
|
||||
return getModelManga().chapters.toList()[mangaReaderModel.index].name!;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ class CurrentIndexProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$readerControllerHash() => r'8999132e4d6b64b2c652d641cbef9ae6e9175d0e';
|
||||
String _$readerControllerHash() => r'255b727a186844a75ea4b71f724142f3f09a1e9a';
|
||||
|
||||
abstract class _$ReaderController extends BuildlessAutoDisposeNotifier<void> {
|
||||
late final MangaReaderModel mangaReaderModel;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:grouped_list/grouped_list.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/views/manga/download/download_model.dart';
|
||||
import 'package:mangayomi/views/manga/download/model/download_model.dart';
|
||||
|
||||
class DownloadQueueScreen extends ConsumerWidget {
|
||||
const DownloadQueueScreen({super.key});
|
||||
|
|
@ -50,11 +50,10 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
),
|
||||
body: GroupedListView<DownloadModel, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => element.modelManga.source!,
|
||||
groupBy: (element) => element.mangaSource!,
|
||||
groupSeparatorBuilder: (String groupByValue) {
|
||||
final sourceQueueLength = entries
|
||||
.where(
|
||||
(element) => element.modelManga.source == groupByValue)
|
||||
.where((element) => element.mangaSource! == groupByValue)
|
||||
.toList()
|
||||
.length;
|
||||
return Padding(
|
||||
|
|
@ -80,7 +79,7 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
element.modelManga.name!,
|
||||
element.mangaName!,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
Text(
|
||||
|
|
@ -90,7 +89,7 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
],
|
||||
),
|
||||
Text(
|
||||
element.modelManga.chapters![element.index].name!,
|
||||
element.chapterName!,
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
@ -126,7 +125,7 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
await Future.delayed(
|
||||
const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
"${element.modelManga.chapters![element.index].name}${element.index}",
|
||||
"${element.chapterName}${element.chapterIndex}${element.chapterId}",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
@ -142,7 +141,7 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
);
|
||||
},
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.modelManga.source!.compareTo(item2.modelManga.source!),
|
||||
item1.mangaSource!.compareTo(item2.mangaSource!),
|
||||
order: GroupedListOrder.DESC,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/categories.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/views/more/settings/categoties/widgets/custom_textfield.dart';
|
||||
import 'package:random_string/random_string.dart';
|
||||
|
||||
class CategoriesScreen extends ConsumerStatefulWidget {
|
||||
const CategoriesScreen({super.key});
|
||||
|
|
@ -14,145 +13,153 @@ class CategoriesScreen extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
||||
List<CategoriesModel> entries = [];
|
||||
List<CategoriesModel> _entries = [];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Edit categories"),
|
||||
),
|
||||
body: ValueListenableBuilder<Box<CategoriesModel>>(
|
||||
valueListenable: ref.watch(hiveBoxCategoriesProvider).listenable(),
|
||||
builder: (context, value, child) {
|
||||
entries = value.values.toList();
|
||||
if (entries.isNotEmpty) {
|
||||
return ListView.builder(
|
||||
itemCount: entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(0),
|
||||
bottomRight: Radius.circular(0),
|
||||
topRight: Radius.circular(10),
|
||||
topLeft: Radius.circular(10)))),
|
||||
onPressed: () {
|
||||
_renameCategory(entries[index]);
|
||||
},
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
const Icon(Icons.label_outline_rounded),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(child: Text(entries[index].name))
|
||||
],
|
||||
)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: const [
|
||||
SizedBox(width: 10),
|
||||
Icon(Icons.arrow_drop_up_outlined),
|
||||
SizedBox(width: 10),
|
||||
Icon(Icons.arrow_drop_down_outlined)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
_renameCategory(entries[index]);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.mode_edit_outline_outlined)),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Delete category",
|
||||
),
|
||||
content: Text(
|
||||
"Do you wish to delete the category"
|
||||
' "${entries[index].name}"?'),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: const Text(
|
||||
"Cancel")),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.watch(
|
||||
hiveBoxCategoriesProvider)
|
||||
.delete(entries[
|
||||
body: StreamBuilder(
|
||||
stream: isar.categoriesModels
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
_entries = snapshot.data!;
|
||||
return ListView.builder(
|
||||
itemCount: _entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(0),
|
||||
bottomRight: Radius.circular(0),
|
||||
topRight: Radius.circular(10),
|
||||
topLeft: Radius.circular(10)))),
|
||||
onPressed: () {
|
||||
_renameCategory(_entries[index]);
|
||||
},
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
const Icon(Icons.label_outline_rounded),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(child: Text(_entries[index].name!))
|
||||
],
|
||||
)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: const [
|
||||
SizedBox(width: 10),
|
||||
Icon(Icons.arrow_drop_up_outlined),
|
||||
SizedBox(width: 10),
|
||||
Icon(Icons.arrow_drop_down_outlined)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
_renameCategory(_entries[index]);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.mode_edit_outline_outlined)),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Delete category",
|
||||
),
|
||||
content: Text(
|
||||
"Do you wish to delete the category"
|
||||
' "${_entries[index].name}"?'),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: const Text(
|
||||
"Cancel")),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed:
|
||||
() async {
|
||||
await isar
|
||||
.writeTxn(
|
||||
() async {
|
||||
await isar
|
||||
.categoriesModels
|
||||
.delete(_entries[
|
||||
index]
|
||||
.id
|
||||
.toString());
|
||||
.id!);
|
||||
});
|
||||
if (mounted) {
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: const Text(
|
||||
"OK",
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.delete_outlined))
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
}
|
||||
},
|
||||
child: const Text(
|
||||
"OK",
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.delete_outlined))
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"You have no categories. Tap the plus button to create one for organizing your library",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
_entries = [];
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"You have no categories. Tap the plus button to create one for organizing your library",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
bool isExist = false;
|
||||
|
|
@ -160,65 +167,67 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Add category",
|
||||
),
|
||||
content: CustomTextFormField(
|
||||
controller: controller,
|
||||
entries: entries,
|
||||
context: context,
|
||||
exist: (value) {
|
||||
setState(() {
|
||||
isExist = value;
|
||||
});
|
||||
},
|
||||
isExist: isExist,
|
||||
val: (val) {}),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text("Cancel")),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: controller.text.isEmpty || isExist
|
||||
? null
|
||||
: () {
|
||||
String randomId = randomNumeric(10);
|
||||
ref
|
||||
.watch(hiveBoxCategoriesProvider)
|
||||
.put(
|
||||
randomId,
|
||||
CategoriesModel(
|
||||
id: int.parse(randomId),
|
||||
return SizedBox(
|
||||
child: StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Add category",
|
||||
),
|
||||
content: CustomTextFormField(
|
||||
controller: controller,
|
||||
entries: _entries,
|
||||
context: context,
|
||||
exist: (value) {
|
||||
setState(() {
|
||||
isExist = value;
|
||||
});
|
||||
},
|
||||
isExist: isExist,
|
||||
val: (val) {}),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text("Cancel")),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed:
|
||||
controller.text.isEmpty || isExist
|
||||
? null
|
||||
: () async {
|
||||
await isar.writeTxn(() async {
|
||||
await isar.categoriesModels
|
||||
.put(CategoriesModel(
|
||||
name: controller.text,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color:
|
||||
controller.text.isEmpty || isExist
|
||||
? Theme.of(context)
|
||||
.primaryColor
|
||||
.withOpacity(0.2)
|
||||
: null),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
});
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color:
|
||||
controller.text.isEmpty || isExist
|
||||
? Theme.of(context)
|
||||
.primaryColor
|
||||
.withOpacity(0.2)
|
||||
: null),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
|
|
@ -249,7 +258,7 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||
),
|
||||
content: CustomTextFormField(
|
||||
controller: controller,
|
||||
entries: entries,
|
||||
entries: _entries,
|
||||
context: context,
|
||||
exist: (value) {
|
||||
setState(() {
|
||||
|
|
@ -257,7 +266,7 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||
});
|
||||
},
|
||||
isExist: isExist,
|
||||
name: category.name,
|
||||
name: category.name!,
|
||||
val: (val) {
|
||||
setState(() {
|
||||
isSameName = controller.text == category.name;
|
||||
|
|
@ -276,18 +285,19 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen> {
|
|||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed:
|
||||
controller.text.isEmpty || isExist || isSameName
|
||||
? null
|
||||
: () {
|
||||
ref.watch(hiveBoxCategoriesProvider).put(
|
||||
category.id.toString(),
|
||||
CategoriesModel(
|
||||
id: category.id,
|
||||
name: controller.text,
|
||||
));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onPressed: controller.text.isEmpty ||
|
||||
isExist ||
|
||||
isSameName
|
||||
? null
|
||||
: () async {
|
||||
await isar.writeTxn(() async {
|
||||
category.name = controller.text;
|
||||
await isar.categoriesModels.put(category);
|
||||
});
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"OK",
|
||||
style: TextStyle(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/model_manga.dart';
|
||||
import 'package:mangayomi/providers/hive_provider.dart';
|
||||
import 'package:mangayomi/services/get_manga_detail.dart';
|
||||
|
|
@ -24,7 +28,6 @@ class MangaImageCardWidget extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final manga = ref.watch(hiveBoxMangaProvider);
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
final modelManga = ModelManga(
|
||||
|
|
@ -40,16 +43,42 @@ class MangaImageCardWidget extends ConsumerWidget {
|
|||
lang: lang,
|
||||
dateAdded: null,
|
||||
lastUpdate: null,
|
||||
chapters: getMangaDetailModel!.chapters,
|
||||
categories: [],
|
||||
lastRead: '');
|
||||
if (manga.get('$lang-${getMangaDetailModel!.url}',
|
||||
defaultValue: null) ==
|
||||
null) {
|
||||
manga.put('$lang-${getMangaDetailModel!.url}', modelManga);
|
||||
}
|
||||
|
||||
context.push('/manga-reader/detail', extra: modelManga);
|
||||
final empty = await isar.modelMangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(getMangaDetailModel!.name)
|
||||
.sourceEqualTo(getMangaDetailModel!.source)
|
||||
.isEmpty();
|
||||
if (empty) {
|
||||
await isar.writeTxn(() async {
|
||||
await isar.modelMangas.put(modelManga);
|
||||
for (var i = 0; i < getMangaDetailModel!.chapters.length; i++) {
|
||||
final chapters = ModelChapters(
|
||||
name: getMangaDetailModel!.chapters[i].name,
|
||||
url: getMangaDetailModel!.chapters[i].url,
|
||||
dateUpload: getMangaDetailModel!.chapters[i].dateUpload,
|
||||
isBookmarked: false,
|
||||
scanlator: getMangaDetailModel!.chapters[i].scanlator,
|
||||
isRead: false,
|
||||
lastPageRead: '',
|
||||
mangaId: modelManga.id)
|
||||
..manga.value = modelManga;
|
||||
await isar.modelChapters.put(chapters);
|
||||
await chapters.manga.save();
|
||||
}
|
||||
});
|
||||
}
|
||||
final getMangaId = await isar.modelMangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(getMangaDetailModel!.name)
|
||||
.sourceEqualTo(getMangaDetailModel!.source)
|
||||
.findFirst();
|
||||
context.push('/manga-reader/detail', extra: getMangaId!.id);
|
||||
log("${getMangaId.id}");
|
||||
},
|
||||
child: CoverViewWidget(children: [
|
||||
cachedNetworkImage(
|
||||
|
|
|
|||
|
|
@ -7,12 +7,16 @@
|
|||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_js/flutter_js_plugin.h>
|
||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_js_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterJsPlugin");
|
||||
flutter_js_plugin_register_with_registrar(flutter_js_registrar);
|
||||
g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
|
||||
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_js
|
||||
isar_flutter_libs
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import Foundation
|
|||
|
||||
import flutter_inappwebview
|
||||
import flutter_js
|
||||
import isar_flutter_libs
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import sqflite
|
||||
|
|
@ -15,6 +16,7 @@ import url_launcher_macos
|
|||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
FlutterJsPlugin.register(with: registry.registrar(forPlugin: "FlutterJsPlugin"))
|
||||
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
|
|
|
|||
56
pubspec.lock
56
pubspec.lock
|
|
@ -266,6 +266,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
dartx:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dartx
|
||||
sha256: "45d7176701f16c5a5e00a4798791c1964bc231491b879369c818dd9a9c764871"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
dio:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -602,6 +610,30 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
isar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: isar
|
||||
sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
isar_flutter_libs:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: isar_flutter_libs
|
||||
sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
isar_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: isar_generator
|
||||
sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -642,14 +674,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
m_toast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: m_toast
|
||||
sha256: "9b9096625a58da18341ba7d46f38b23a21a0be723aab008e1b5cfff71980f881"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1079,6 +1103,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.16"
|
||||
time:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: time
|
||||
sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1215,6 +1247,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
xxh3:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xxh3
|
||||
sha256: a92b30944a9aeb4e3d4f3c3d4ddb3c7816ca73475cd603682c4f8149690f56d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ dependencies:
|
|||
draggable_menu: ^0.3.0
|
||||
fast_cached_network_image: ^1.2.0
|
||||
random_string: ^2.3.1
|
||||
isar: 3.1.0+1
|
||||
isar_flutter_libs: 3.1.0+1
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
|
@ -75,6 +77,7 @@ dev_dependencies:
|
|||
build_runner: ^2.3.3
|
||||
riverpod_generator: ^2.1.4
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
isar_generator: 3.1.0+1
|
||||
flutter_lints: ^2.0.1
|
||||
|
||||
flutter_launcher_icons:
|
||||
|
|
|
|||
|
|
@ -7,12 +7,15 @@
|
|||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_js/flutter_js_plugin.h>
|
||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlutterJsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterJsPlugin"));
|
||||
IsarFlutterLibsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_js
|
||||
isar_flutter_libs
|
||||
permission_handler_windows
|
||||
url_launcher_windows
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue