feature: pinned , last used source + fix
This commit is contained in:
parent
bc47bf00f0
commit
dfd82b32f6
19 changed files with 586 additions and 214 deletions
|
|
@ -94,7 +94,7 @@ class Settings {
|
|||
this.dateFormat = "M/d/y",
|
||||
this.relativeTimesTamps = 2,
|
||||
this.flexSchemeColorIndex = 2,
|
||||
this.themeIsDark = true,
|
||||
this.themeIsDark = false,
|
||||
this.incognitoMode = false,
|
||||
this.chapterPageUrlsList,
|
||||
this.showPagesNumber = true,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class Source {
|
|||
|
||||
bool? isAdded;
|
||||
|
||||
bool? isPinned;
|
||||
|
||||
bool? isNsfw;
|
||||
|
||||
@enumerated
|
||||
|
|
@ -27,6 +29,8 @@ class Source {
|
|||
|
||||
bool? isCloudflare;
|
||||
|
||||
bool? lastUsed;
|
||||
|
||||
String? dateFormat;
|
||||
|
||||
String? dateFormatLocale;
|
||||
|
|
@ -47,6 +51,8 @@ class Source {
|
|||
this.isNsfw = false,
|
||||
this.isFullData = false,
|
||||
this.isCloudflare = false,
|
||||
this.isPinned = false,
|
||||
this.lastUsed = false,
|
||||
this.apiUrl = "",
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,23 +62,33 @@ const SourceSchema = CollectionSchema(
|
|||
name: r'isNsfw',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'lang': PropertySchema(
|
||||
r'isPinned': PropertySchema(
|
||||
id: 9,
|
||||
name: r'isPinned',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'lang': PropertySchema(
|
||||
id: 10,
|
||||
name: r'lang',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'lastUsed': PropertySchema(
|
||||
id: 11,
|
||||
name: r'lastUsed',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'logoUrl': PropertySchema(
|
||||
id: 10,
|
||||
id: 12,
|
||||
name: r'logoUrl',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'sourceName': PropertySchema(
|
||||
id: 11,
|
||||
id: 13,
|
||||
name: r'sourceName',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'typeSource': PropertySchema(
|
||||
id: 12,
|
||||
id: 14,
|
||||
name: r'typeSource',
|
||||
type: IsarType.byte,
|
||||
enumMap: _SourcetypeSourceEnumValueMap,
|
||||
|
|
@ -164,10 +174,12 @@ void _sourceSerialize(
|
|||
writer.writeBool(offsets[6], object.isCloudflare);
|
||||
writer.writeBool(offsets[7], object.isFullData);
|
||||
writer.writeBool(offsets[8], object.isNsfw);
|
||||
writer.writeString(offsets[9], object.lang);
|
||||
writer.writeString(offsets[10], object.logoUrl);
|
||||
writer.writeString(offsets[11], object.sourceName);
|
||||
writer.writeByte(offsets[12], object.typeSource.index);
|
||||
writer.writeBool(offsets[9], object.isPinned);
|
||||
writer.writeString(offsets[10], object.lang);
|
||||
writer.writeBool(offsets[11], object.lastUsed);
|
||||
writer.writeString(offsets[12], object.logoUrl);
|
||||
writer.writeString(offsets[13], object.sourceName);
|
||||
writer.writeByte(offsets[14], object.typeSource.index);
|
||||
}
|
||||
|
||||
Source _sourceDeserialize(
|
||||
|
|
@ -187,11 +199,13 @@ Source _sourceDeserialize(
|
|||
isCloudflare: reader.readBoolOrNull(offsets[6]),
|
||||
isFullData: reader.readBoolOrNull(offsets[7]),
|
||||
isNsfw: reader.readBoolOrNull(offsets[8]),
|
||||
lang: reader.readStringOrNull(offsets[9]),
|
||||
logoUrl: reader.readStringOrNull(offsets[10]),
|
||||
sourceName: reader.readStringOrNull(offsets[11]),
|
||||
isPinned: reader.readBoolOrNull(offsets[9]),
|
||||
lang: reader.readStringOrNull(offsets[10]),
|
||||
lastUsed: reader.readBoolOrNull(offsets[11]),
|
||||
logoUrl: reader.readStringOrNull(offsets[12]),
|
||||
sourceName: reader.readStringOrNull(offsets[13]),
|
||||
typeSource:
|
||||
_SourcetypeSourceValueEnumMap[reader.readByteOrNull(offsets[12])] ??
|
||||
_SourcetypeSourceValueEnumMap[reader.readByteOrNull(offsets[14])] ??
|
||||
TypeSource.single,
|
||||
);
|
||||
return object;
|
||||
|
|
@ -223,12 +237,16 @@ P _sourceDeserializeProp<P>(
|
|||
case 8:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 9:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 10:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 11:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
case 12:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 13:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 14:
|
||||
return (_SourcetypeSourceValueEnumMap[reader.readByteOrNull(offset)] ??
|
||||
TypeSource.single) as P;
|
||||
default:
|
||||
|
|
@ -1128,6 +1146,32 @@ extension SourceQueryFilter on QueryBuilder<Source, Source, QFilterCondition> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> isPinnedIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'isPinned',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> isPinnedIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'isPinned',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> isPinnedEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'isPinned',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> langIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
|
|
@ -1273,6 +1317,32 @@ extension SourceQueryFilter on QueryBuilder<Source, Source, QFilterCondition> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> lastUsedIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'lastUsed',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> lastUsedIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'lastUsed',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> lastUsedEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'lastUsed',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterFilterCondition> logoUrlIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
|
|
@ -1732,6 +1802,18 @@ extension SourceQuerySortBy on QueryBuilder<Source, Source, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> sortByIsPinned() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isPinned', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> sortByIsPinnedDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isPinned', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> sortByLang() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'lang', Sort.asc);
|
||||
|
|
@ -1744,6 +1826,18 @@ extension SourceQuerySortBy on QueryBuilder<Source, Source, QSortBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> sortByLastUsed() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'lastUsed', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> sortByLastUsedDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'lastUsed', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> sortByLogoUrl() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'logoUrl', Sort.asc);
|
||||
|
|
@ -1902,6 +1996,18 @@ extension SourceQuerySortThenBy on QueryBuilder<Source, Source, QSortThenBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> thenByIsPinned() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isPinned', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> thenByIsPinnedDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'isPinned', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> thenByLang() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'lang', Sort.asc);
|
||||
|
|
@ -1914,6 +2020,18 @@ extension SourceQuerySortThenBy on QueryBuilder<Source, Source, QSortThenBy> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> thenByLastUsed() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'lastUsed', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> thenByLastUsedDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'lastUsed', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QAfterSortBy> thenByLogoUrl() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'logoUrl', Sort.asc);
|
||||
|
|
@ -2011,6 +2129,12 @@ extension SourceQueryWhereDistinct on QueryBuilder<Source, Source, QDistinct> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QDistinct> distinctByIsPinned() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'isPinned');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QDistinct> distinctByLang(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
|
@ -2018,6 +2142,12 @@ extension SourceQueryWhereDistinct on QueryBuilder<Source, Source, QDistinct> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QDistinct> distinctByLastUsed() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'lastUsed');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, Source, QDistinct> distinctByLogoUrl(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
|
@ -2100,12 +2230,24 @@ extension SourceQueryProperty on QueryBuilder<Source, Source, QQueryProperty> {
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, bool?, QQueryOperations> isPinnedProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'isPinned');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, String?, QQueryOperations> langProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'lang');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, bool?, QQueryOperations> lastUsedProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'lastUsed');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Source, String?, QQueryOperations> logoUrlProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'logoUrl');
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mangayomi/modules/browse/extension/providers/refresh_source_list_data.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/modules/browse/extension/extension_screen.dart';
|
||||
import 'package:mangayomi/modules/browse/extension/refresh_source_list_data.dart';
|
||||
import 'package:mangayomi/modules/browse/migrate_screen.dart';
|
||||
import 'package:mangayomi/modules/browse/sources/sources_screen.dart';
|
||||
import 'package:mangayomi/modules/library/search_text_form_field.dart';
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class ExtensionScreen extends ConsumerWidget {
|
|||
Text(
|
||||
groupByValue,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w300, fontSize: 12),
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ refreshSourceListData(RefreshSourceListDataRef ref) {
|
|||
..typeSource = source.typeSource
|
||||
..isFullData = source.isFullData
|
||||
..lang = source.lang
|
||||
..isNsfw = source.isNsfw
|
||||
..sourceName = source.sourceName);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ part of 'refresh_source_list_data.dart';
|
|||
// **************************************************************************
|
||||
|
||||
String _$refreshSourceListDataHash() =>
|
||||
r'f77838cebad50f030d2038d07584199b4509f407';
|
||||
r'c6ab103b0519d79afc8530ab7027a988203de5d3';
|
||||
|
||||
/// See also [refreshSourceListData].
|
||||
@ProviderFor(refreshSourceListData)
|
||||
|
|
@ -3,12 +3,14 @@ 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/manga.dart';
|
||||
import 'package:mangayomi/services/get_manga_detail.dart';
|
||||
import 'package:mangayomi/services/search_manga.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/sources/service.dart';
|
||||
import 'package:mangayomi/sources/source_list.dart';
|
||||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/modules/library/search_text_form_field.dart';
|
||||
|
|
@ -31,7 +33,7 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sourceList = ref.watch(onlyIncludePinnedSourceStateProvider)
|
||||
? isar.sources.filter().isAddedEqualTo(true).findAllSync()
|
||||
? isar.sources.filter().isPinnedEqualTo(true).findAllSync()
|
||||
: sourcesList;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -62,7 +64,7 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
|||
children: [
|
||||
for (var i = 0; i < sourceList.length; i++)
|
||||
SizedBox(
|
||||
height: 230,
|
||||
height: 260,
|
||||
child: SourceSearchScreen(
|
||||
query: query,
|
||||
source: sourceList[i],
|
||||
|
|
@ -91,7 +93,7 @@ class SourceSearchScreen extends ConsumerWidget {
|
|||
.watch(searchMangaProvider(source: source.sourceName!, query: query));
|
||||
return Scaffold(
|
||||
body: SizedBox(
|
||||
height: 240,
|
||||
height: 260,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
|
|
@ -175,43 +177,93 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
|||
pushToMangaReaderDetail(
|
||||
context: context, getManga: data, lang: widget.lang);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 90,
|
||||
child: Column(children: [
|
||||
cachedNetworkImage(
|
||||
headers: ref.watch(headersProvider(source: data.source!)),
|
||||
imageUrl: data.imageUrl!,
|
||||
width: 80,
|
||||
height: 120,
|
||||
fit: BoxFit.fill),
|
||||
BottomTextWidget(
|
||||
fontSize: 12.0,
|
||||
text: widget.manga.name!,
|
||||
isLoading: true,
|
||||
isComfortableGrid: true,
|
||||
)
|
||||
]),
|
||||
),
|
||||
child: StreamBuilder(
|
||||
stream: isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(widget.lang)
|
||||
.nameEqualTo(data.name)
|
||||
.sourceEqualTo(data.source)
|
||||
.favoriteEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Stack(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Column(children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
child: cachedNetworkImage(
|
||||
headers: ref.watch(
|
||||
headersProvider(source: data.source!)),
|
||||
imageUrl: data.imageUrl!,
|
||||
width: 100,
|
||||
height: 140,
|
||||
fit: BoxFit.fill),
|
||||
),
|
||||
BottomTextWidget(
|
||||
fontSize: 12.0,
|
||||
text: widget.manga.name!,
|
||||
isLoading: true,
|
||||
isComfortableGrid: true,
|
||||
)
|
||||
]),
|
||||
),
|
||||
Container(
|
||||
width: 100,
|
||||
height: 140,
|
||||
color: snapshot.hasData && snapshot.data!.isNotEmpty
|
||||
? Colors.black.withOpacity(0.7)
|
||||
: null,
|
||||
),
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty)
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor(context),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"In library",
|
||||
style: TextStyle(fontSize: 10),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
loading: () => SizedBox(
|
||||
width: 60,
|
||||
child: Column(children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
child: Container(
|
||||
color: Theme.of(context).cardColor,
|
||||
width: 80,
|
||||
height: 120,
|
||||
loading: () => Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: SizedBox(
|
||||
width: 100,
|
||||
child: Column(children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
child: Container(
|
||||
color: Theme.of(context).cardColor,
|
||||
width: 100,
|
||||
height: 140,
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomTextWidget(
|
||||
fontSize: 12.0,
|
||||
text: widget.manga.name!,
|
||||
isLoading: true,
|
||||
isComfortableGrid: true,
|
||||
)
|
||||
]),
|
||||
BottomTextWidget(
|
||||
fontSize: 12.0,
|
||||
text: widget.manga.name!,
|
||||
isLoading: true,
|
||||
isComfortableGrid: true,
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
error: (error, stackTrace) => Center(child: Text(error.toString())),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/manga_type.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/modules/browse/sources/widgets/source_list_tile.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||
|
||||
|
|
@ -15,124 +14,156 @@ class SourcesScreen extends ConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: StreamBuilder(
|
||||
stream: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.isAddedEqualTo(true)
|
||||
.and()
|
||||
.isActiveEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text("Empty"));
|
||||
}
|
||||
final entries = snapshot.data!
|
||||
.where((element) => ref.watch(showNSFWStateProvider)
|
||||
? true
|
||||
: element.isNsfw == false)
|
||||
.toList();
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => completeLang(element.lang!.toLowerCase()),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
groupByValue,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w300, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
context.push('/mangaHome',
|
||||
extra: MangaType(
|
||||
isFullData: element.isFullData,
|
||||
lang: element.lang,
|
||||
source: element.sourceName));
|
||||
},
|
||||
leading: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.secondaryHeaderColor
|
||||
.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child:
|
||||
// element.logoUrl!.isEmpty
|
||||
// ?
|
||||
const Icon(Icons.source_outlined)
|
||||
// : CachedNetworkImage(
|
||||
// httpHeaders: ref.watch(
|
||||
// headersProvider(source: element.sourceName!)),
|
||||
// imageUrl: element.logoUrl!,
|
||||
// fit: BoxFit.contain,
|
||||
// width: 37,
|
||||
// height: 37,
|
||||
// errorWidget: (context, url, error) {
|
||||
// return const SizedBox(
|
||||
// width: 37,
|
||||
// height: 37,
|
||||
// child: Center(
|
||||
// child: Icon(Icons.source_outlined),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Text(
|
||||
completeLang(element.lang!.toLowerCase()),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w300, fontSize: 12),
|
||||
),
|
||||
if (element.isNsfw!)
|
||||
Row(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
StreamBuilder(
|
||||
stream: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.isAddedEqualTo(true)
|
||||
.and()
|
||||
.isActiveEqualTo(true)
|
||||
.and()
|
||||
.lastUsedEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text(""));
|
||||
}
|
||||
final entries = snapshot.data!
|
||||
.where((element) => ref.watch(showNSFWStateProvider)
|
||||
? true
|
||||
: element.isNsfw == false)
|
||||
.toList();
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => "",
|
||||
groupSeparatorBuilder: (String groupByValue) =>
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 2,
|
||||
),
|
||||
Text(
|
||||
"18+",
|
||||
"Last used",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w300,
|
||||
fontSize: 10,
|
||||
color: Colors.redAccent
|
||||
.withBlue(5)
|
||||
.withOpacity(0.8)),
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
title: Text(element.sourceName!),
|
||||
trailing: const SizedBox(
|
||||
width: 110,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.push_pin_outlined,
|
||||
color: Colors.black,
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.sourceName!.compareTo(item2.sourceName!),
|
||||
order: GroupedListOrder.ASC,
|
||||
);
|
||||
}),
|
||||
);
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
return SourceListTile(
|
||||
source: element,
|
||||
);
|
||||
},
|
||||
shrinkWrap: true,
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.sourceName!.compareTo(item2.sourceName!),
|
||||
order: GroupedListOrder.ASC,
|
||||
);
|
||||
}),
|
||||
StreamBuilder(
|
||||
stream: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.isAddedEqualTo(true)
|
||||
.and()
|
||||
.isActiveEqualTo(true)
|
||||
.and()
|
||||
.isPinnedEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text(""));
|
||||
}
|
||||
final entries = snapshot.data!
|
||||
.where((element) => ref.watch(showNSFWStateProvider)
|
||||
? true
|
||||
: element.isNsfw == false)
|
||||
.toList();
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => "",
|
||||
groupSeparatorBuilder: (String groupByValue) =>
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Pinned",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
return SourceListTile(
|
||||
source: element,
|
||||
);
|
||||
},
|
||||
shrinkWrap: true,
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.sourceName!.compareTo(item2.sourceName!),
|
||||
order: GroupedListOrder.ASC,
|
||||
);
|
||||
}),
|
||||
StreamBuilder(
|
||||
stream: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.isAddedEqualTo(true)
|
||||
.and()
|
||||
.isActiveEqualTo(true)
|
||||
.and()
|
||||
.isPinnedEqualTo(false)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text("Empty"));
|
||||
}
|
||||
final entries = snapshot.data!
|
||||
.where((element) => ref.watch(showNSFWStateProvider)
|
||||
? true
|
||||
: element.isNsfw == false)
|
||||
.toList();
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) =>
|
||||
completeLang(element.lang!.toLowerCase()),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
groupByValue,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
return SourceListTile(
|
||||
source: element,
|
||||
);
|
||||
},
|
||||
shrinkWrap: true,
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.sourceName!.compareTo(item2.sourceName!),
|
||||
order: GroupedListOrder.ASC,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
95
lib/modules/browse/sources/widgets/source_list_tile.dart
Normal file
95
lib/modules/browse/sources/widgets/source_list_tile.dart
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/manga_type.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
|
||||
class SourceListTile extends StatelessWidget {
|
||||
final Source source;
|
||||
const SourceListTile({super.key, required this.source});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
final sources = isar.sources.filter().idIsNotNull().findAllSync();
|
||||
isar.writeTxnSync(() {
|
||||
for (var src in sources) {
|
||||
isar.sources
|
||||
.putSync(src..lastUsed = src.id == source.id ? true : false);
|
||||
}
|
||||
});
|
||||
|
||||
context.push('/mangaHome',
|
||||
extra: MangaType(
|
||||
isFullData: source.isFullData,
|
||||
lang: source.lang,
|
||||
source: source.sourceName));
|
||||
},
|
||||
leading: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child:
|
||||
// source.logoUrl!.isEmpty
|
||||
// ?
|
||||
const Icon(Icons.source_outlined)
|
||||
// : CachedNetworkImage(
|
||||
// httpHeaders: ref.watch(
|
||||
// headersProvider(source: source.sourceName!)),
|
||||
// imageUrl: source.logoUrl!,
|
||||
// fit: BoxFit.contain,
|
||||
// width: 37,
|
||||
// height: 37,
|
||||
// errorWidget: (context, url, error) {
|
||||
// return const SizedBox(
|
||||
// width: 37,
|
||||
// height: 37,
|
||||
// child: Center(
|
||||
// child: Icon(Icons.source_outlined),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Text(
|
||||
completeLang(source.lang!.toLowerCase()),
|
||||
style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 12),
|
||||
),
|
||||
if (source.isNsfw!)
|
||||
Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 2,
|
||||
),
|
||||
Text(
|
||||
"18+",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w300,
|
||||
fontSize: 10,
|
||||
color: Colors.redAccent.withBlue(5).withOpacity(0.8)),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
title: Text(source.sourceName!),
|
||||
trailing: IconButton(
|
||||
onPressed: () {
|
||||
isar.writeTxnSync(() =>
|
||||
isar.sources.putSync(source..isPinned = !source.isPinned!));
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.push_pin_outlined,
|
||||
color: source.isPinned! ? primaryColor(context) : null,
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,13 +16,13 @@ class DarkModeButton extends ConsumerStatefulWidget {
|
|||
class _DarkModeButtonState extends ConsumerState<DarkModeButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isLight = ref.watch(themeModeStateProvider);
|
||||
bool isDark = ref.watch(themeModeStateProvider);
|
||||
return SwitchListTile(
|
||||
onChanged: (value) {
|
||||
if (value) {
|
||||
ref.read(themeModeStateProvider.notifier).setLightTheme();
|
||||
} else {
|
||||
ref.read(themeModeStateProvider.notifier).setDarkTheme();
|
||||
} else {
|
||||
ref.read(themeModeStateProvider.notifier).setLightTheme();
|
||||
}
|
||||
},
|
||||
title: const Text(
|
||||
|
|
@ -30,10 +30,10 @@ class _DarkModeButtonState extends ConsumerState<DarkModeButton> {
|
|||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(
|
||||
isLight ? 'Off' : 'On',
|
||||
!isDark ? 'Off' : 'On',
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
value: isLight,
|
||||
value: !isDark,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:mangayomi/models/manga.dart';
|
|||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/sources/service.dart';
|
||||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/modules/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/modules/widgets/cover_view_widget.dart';
|
||||
|
|
@ -30,16 +31,50 @@ class MangaImageCardWidget extends ConsumerWidget {
|
|||
pushToMangaReaderDetail(
|
||||
context: context, getManga: getMangaDetail!, lang: lang);
|
||||
},
|
||||
child: CoverViewWidget(children: [
|
||||
cachedNetworkImage(
|
||||
headers:
|
||||
ref.watch(headersProvider(source: getMangaDetail!.source!)),
|
||||
imageUrl: getMangaDetail!.imageUrl!,
|
||||
width: 200,
|
||||
height: 270,
|
||||
fit: BoxFit.cover),
|
||||
BottomTextWidget(text: getMangaDetail!.name!)
|
||||
]),
|
||||
child: StreamBuilder(
|
||||
stream: isar.mangas
|
||||
.filter()
|
||||
.langEqualTo(lang)
|
||||
.nameEqualTo(getMangaDetail!.name)
|
||||
.sourceEqualTo(getMangaDetail!.source)
|
||||
.favoriteEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
return CoverViewWidget(children: [
|
||||
cachedNetworkImage(
|
||||
headers: ref
|
||||
.watch(headersProvider(source: getMangaDetail!.source!)),
|
||||
imageUrl: getMangaDetail!.imageUrl!,
|
||||
width: 200,
|
||||
height: 270,
|
||||
fit: BoxFit.cover),
|
||||
Container(
|
||||
color: snapshot.hasData && snapshot.data!.isNotEmpty
|
||||
? Colors.black.withOpacity(0.7)
|
||||
: null,
|
||||
),
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty)
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor(context),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"In library",
|
||||
style: TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
BottomTextWidget(text: getMangaDetail!.name!)
|
||||
]);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ Future<String> cloudflareBypassHtml(CloudflareBypassHtmlRef ref,
|
|||
}
|
||||
return false;
|
||||
});
|
||||
await Future.delayed(Duration(seconds: 10));
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
html = await controller.evaluateJavascript(
|
||||
source:
|
||||
"window.document.getElementsByTagName('html')[0].outerHTML;");
|
||||
|
|
|
|||
|
|
@ -84,19 +84,11 @@ List<Source> _madaraSourcesList = [
|
|||
dateFormat: "MMMM dd, yyyy",
|
||||
dateFormatLocale: "tr",
|
||||
),
|
||||
Source(
|
||||
sourceName: "Comictoon",
|
||||
baseUrl: "https://comictoonthaith-new.com",
|
||||
lang: "th",
|
||||
typeSource: TypeSource.madara,
|
||||
logoUrl: '',
|
||||
dateFormat: "MMMMM dd, yyyy",
|
||||
dateFormatLocale: "th",
|
||||
),
|
||||
|
||||
Source(
|
||||
sourceName: "CookieToon",
|
||||
baseUrl: "https://cookietoon.online",
|
||||
lang: "pt-BR",
|
||||
lang: "pt-br",
|
||||
typeSource: TypeSource.madara,
|
||||
logoUrl: '',
|
||||
dateFormat: "dd/MM/yyyy",
|
||||
|
|
@ -105,7 +97,7 @@ List<Source> _madaraSourcesList = [
|
|||
Source(
|
||||
sourceName: "Drope Scan",
|
||||
baseUrl: "https://dropescan.com",
|
||||
lang: "pt-BR",
|
||||
lang: "pt-br",
|
||||
typeSource: TypeSource.madara,
|
||||
logoUrl: '',
|
||||
dateFormat: "dd/MM/yyyy",
|
||||
|
|
@ -123,7 +115,7 @@ List<Source> _madaraSourcesList = [
|
|||
Source(
|
||||
sourceName: "Final Scans",
|
||||
baseUrl: "https://finalscans.com",
|
||||
lang: "pt-BR",
|
||||
lang: "pt-br",
|
||||
typeSource: TypeSource.madara,
|
||||
logoUrl: '',
|
||||
isNsfw: true,
|
||||
|
|
@ -190,7 +182,7 @@ List<Source> _madaraSourcesList = [
|
|||
Source(
|
||||
sourceName: "Kami Sama Explorer",
|
||||
baseUrl: "https://leitor.kamisama.com.br",
|
||||
lang: "pt-BR",
|
||||
lang: "pt-br",
|
||||
typeSource: TypeSource.madara,
|
||||
logoUrl: '',
|
||||
dateFormat: "dd 'de' MMMM 'de' yyyy",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const logoUrl =
|
|||
'https://comick.app/_next/image?url=%2Fstatic%2Ficons%2Funicorn-64.png&w=144&q=75';
|
||||
const apiUrl = 'https://api.comick.fun';
|
||||
const baseUrl = 'https://comick.app';
|
||||
|
||||
const isNsfw = true;
|
||||
List<Source> get comickSourcesList => _comickSourcesList;
|
||||
List<Source> _comickSourcesList = [
|
||||
Source(
|
||||
|
|
@ -15,6 +15,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -24,6 +25,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -33,6 +35,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -42,6 +45,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -51,6 +55,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -60,6 +65,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -69,6 +75,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -78,6 +85,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -87,6 +95,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -96,6 +105,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -105,6 +115,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -114,6 +125,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -123,6 +135,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -132,6 +145,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -141,6 +155,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -150,6 +165,7 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
Source(
|
||||
sourceName: 'Comick',
|
||||
|
|
@ -159,5 +175,6 @@ List<Source> _comickSourcesList = [
|
|||
typeSource: TypeSource.comick,
|
||||
logoUrl: logoUrl,
|
||||
dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
isNsfw: isNsfw,
|
||||
dateFormatLocale: "en"),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -103,18 +103,18 @@ class Comick extends MangaYomiServices {
|
|||
required AutoDisposeFutureProviderRef ref}) async {
|
||||
final response = await ref.watch(httpGetProvider(
|
||||
url:
|
||||
'https://api.comick.fun/search?q=${query.trim()}&tachiyomi=true&page=1',
|
||||
'${getMangaAPIUrl(source)}/v1.0/search?q=${query.trim()}&tachiyomi=true&limit=50&page=1',
|
||||
source: source,
|
||||
resDom: false)
|
||||
.future) as String?;
|
||||
var popularManga = jsonDecode(response!) as List;
|
||||
var popularMangaList =
|
||||
popularManga.map((e) => MangaSearchModelComick.fromJson(e)).toList();
|
||||
var search = jsonDecode(response!) as List;
|
||||
var searchList =
|
||||
search.map((e) => MangaSearchModelComick.fromJson(e)).toList();
|
||||
|
||||
for (var popular in popularMangaList) {
|
||||
url.add("/comic/${popular.slug}");
|
||||
name.add(popular.title);
|
||||
image.add(popular.coverUrl);
|
||||
for (var search in searchList) {
|
||||
url.add("/comic/${search.hid}#");
|
||||
name.add(search.title);
|
||||
image.add(search.coverUrl);
|
||||
}
|
||||
|
||||
return mangaRes();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class MangaSearchModelComick {
|
|||
title = json['title'];
|
||||
|
||||
slug = json['slug'];
|
||||
hid = json['hid'];
|
||||
|
||||
coverUrl = json['cover_url'];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,10 +212,12 @@ class MangaKawaii extends MangaYomiServices {
|
|||
}
|
||||
return pageUrls;
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<List<GetManga?>> getLatestUpdatesManga({required String source, required int page, required AutoDisposeFutureProviderRef ref}) {
|
||||
// TODO: implement getLatestUpdatesManga
|
||||
Future<List<GetManga?>> getLatestUpdatesManga(
|
||||
{required String source,
|
||||
required int page,
|
||||
required AutoDisposeFutureProviderRef ref}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue