mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-21 20:12:00 +00:00
add popular manga service , widget , manga home
This commit is contained in:
parent
92a03e8a5d
commit
c90b78831f
24 changed files with 1116 additions and 8 deletions
|
|
@ -47,7 +47,7 @@ android {
|
||||||
applicationId "com.kodjodevf.mangayomi"
|
applicationId "com.kodjodevf.mangayomi"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion 21
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|
|
||||||
7
lib/models/manga_type.dart
Normal file
7
lib/models/manga_type.dart
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
class MangaType {
|
||||||
|
String? lang;
|
||||||
|
bool? isFullData;
|
||||||
|
String? source;
|
||||||
|
MangaType(
|
||||||
|
{required this.isFullData, required this.lang, required this.source});
|
||||||
|
}
|
||||||
60
lib/models/model_manga.dart
Normal file
60
lib/models/model_manga.dart
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
|
part 'model_manga.g.dart';
|
||||||
|
|
||||||
|
@HiveType(typeId: 0)
|
||||||
|
class ModelManga extends HiveObject {
|
||||||
|
@HiveField(0)
|
||||||
|
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 = false;
|
||||||
|
|
||||||
|
@HiveField(8)
|
||||||
|
List<String>? chapterTitle;
|
||||||
|
|
||||||
|
@HiveField(9)
|
||||||
|
List<String>? chapterUrl;
|
||||||
|
|
||||||
|
@HiveField(10)
|
||||||
|
List<String>? chapterDate;
|
||||||
|
|
||||||
|
@HiveField(11)
|
||||||
|
String? source;
|
||||||
|
|
||||||
|
@HiveField(12)
|
||||||
|
String? lang;
|
||||||
|
|
||||||
|
ModelManga(
|
||||||
|
{required this.chapterDate,
|
||||||
|
required this.source,
|
||||||
|
required this.chapterTitle,
|
||||||
|
required this.chapterUrl,
|
||||||
|
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});
|
||||||
|
}
|
||||||
77
lib/models/model_manga.g.dart
Normal file
77
lib/models/model_manga.g.dart
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'model_manga.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// TypeAdapterGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class ModelMangaAdapter extends TypeAdapter<ModelManga> {
|
||||||
|
@override
|
||||||
|
final int typeId = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ModelManga read(BinaryReader reader) {
|
||||||
|
final numOfFields = reader.readByte();
|
||||||
|
final fields = <int, dynamic>{
|
||||||
|
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||||
|
};
|
||||||
|
return ModelManga(
|
||||||
|
chapterDate: (fields[10] as List?)?.cast<String>(),
|
||||||
|
source: fields[11] as String?,
|
||||||
|
chapterTitle: (fields[8] as List?)?.cast<String>(),
|
||||||
|
chapterUrl: (fields[9] as List?)?.cast<String>(),
|
||||||
|
author: fields[4] as String?,
|
||||||
|
favorite: fields[7] as bool,
|
||||||
|
genre: (fields[6] as List?)?.cast<String>(),
|
||||||
|
imageUrl: fields[2] as String?,
|
||||||
|
lang: fields[12] as String?,
|
||||||
|
link: fields[1] as String?,
|
||||||
|
name: fields[0] as String?,
|
||||||
|
status: fields[5] as String?,
|
||||||
|
description: fields[3] as String?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void write(BinaryWriter writer, ModelManga obj) {
|
||||||
|
writer
|
||||||
|
..writeByte(13)
|
||||||
|
..writeByte(0)
|
||||||
|
..write(obj.name)
|
||||||
|
..writeByte(1)
|
||||||
|
..write(obj.link)
|
||||||
|
..writeByte(2)
|
||||||
|
..write(obj.imageUrl)
|
||||||
|
..writeByte(3)
|
||||||
|
..write(obj.description)
|
||||||
|
..writeByte(4)
|
||||||
|
..write(obj.author)
|
||||||
|
..writeByte(5)
|
||||||
|
..write(obj.status)
|
||||||
|
..writeByte(6)
|
||||||
|
..write(obj.genre)
|
||||||
|
..writeByte(7)
|
||||||
|
..write(obj.favorite)
|
||||||
|
..writeByte(8)
|
||||||
|
..write(obj.chapterTitle)
|
||||||
|
..writeByte(9)
|
||||||
|
..write(obj.chapterUrl)
|
||||||
|
..writeByte(10)
|
||||||
|
..write(obj.chapterDate)
|
||||||
|
..writeByte(11)
|
||||||
|
..write(obj.source)
|
||||||
|
..writeByte(12)
|
||||||
|
..write(obj.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => typeId.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is ModelMangaAdapter &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
typeId == other.typeId;
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:mangayomi/models/manga_type.dart';
|
||||||
import 'package:mangayomi/views/browse/browse_screen.dart';
|
import 'package:mangayomi/views/browse/browse_screen.dart';
|
||||||
import 'package:mangayomi/views/general/general_screen.dart';
|
import 'package:mangayomi/views/general/general_screen.dart';
|
||||||
import 'package:mangayomi/views/history/history_screen.dart';
|
import 'package:mangayomi/views/history/history_screen.dart';
|
||||||
import 'package:mangayomi/views/library/library_screen.dart';
|
import 'package:mangayomi/views/library/library_screen.dart';
|
||||||
|
import 'package:mangayomi/views/manga/home/home.dart';
|
||||||
import 'package:mangayomi/views/more/more_screen.dart';
|
import 'package:mangayomi/views/more/more_screen.dart';
|
||||||
import 'package:mangayomi/views/updates/updates_screen.dart';
|
import 'package:mangayomi/views/updates/updates_screen.dart';
|
||||||
|
|
||||||
|
|
@ -70,6 +72,24 @@ class AsyncRouterNotifier extends ChangeNotifier {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
GoRoute(
|
||||||
|
path: "/mangaHome",
|
||||||
|
name: "mangaHome",
|
||||||
|
builder: (context, state) {
|
||||||
|
final mangaType = state.extra as MangaType?;
|
||||||
|
return MangaHomeScreen(
|
||||||
|
mangaType: mangaType!,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
final mangaType = state.extra as MangaType?;
|
||||||
|
return CustomTransition(
|
||||||
|
key: state.pageKey,
|
||||||
|
child: MangaHomeScreen(
|
||||||
|
mangaType: mangaType!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
150
lib/services/get_manga_detail.dart
Normal file
150
lib/services/get_manga_detail.dart
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:html/dom.dart' as dom;
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
part 'get_manga_detail.g.dart';
|
||||||
|
|
||||||
|
class GetMangaDetailModel {
|
||||||
|
List<String> genre = [];
|
||||||
|
List<String> detail = [];
|
||||||
|
List<String> chapterTitle = [];
|
||||||
|
List<String> chapterUrl = [];
|
||||||
|
List<String> chapterDate = [];
|
||||||
|
String? source;
|
||||||
|
String? url;
|
||||||
|
String? name;
|
||||||
|
String? image;
|
||||||
|
String? synopsys;
|
||||||
|
GetMangaDetailModel({
|
||||||
|
required this.genre,
|
||||||
|
required this.detail,
|
||||||
|
required this.chapterDate,
|
||||||
|
required this.chapterTitle,
|
||||||
|
required this.chapterUrl,
|
||||||
|
required this.image,
|
||||||
|
required this.synopsys,
|
||||||
|
required this.url,
|
||||||
|
required this.name,
|
||||||
|
required this.source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<GetMangaDetailModel> getMangaDetail(GetMangaDetailRef ref,
|
||||||
|
{required String image,
|
||||||
|
required String url,
|
||||||
|
required String name,
|
||||||
|
String lang = '',
|
||||||
|
required String source}) async {
|
||||||
|
List<String> genre = [];
|
||||||
|
List<String> detail = [];
|
||||||
|
List<String> chapterTitle = [];
|
||||||
|
List<String> chapterUrl = [];
|
||||||
|
List<String> chapterDate = [];
|
||||||
|
String? synopsys;
|
||||||
|
if (source == "mangahere") {
|
||||||
|
final response = await http.get(Uri.parse("http://www.mangahere.cc$url"),
|
||||||
|
headers: {
|
||||||
|
"Referer": "https://www.mangahere.cc/",
|
||||||
|
"Cookie": "isAdult=1"
|
||||||
|
});
|
||||||
|
dom.Document htmll = dom.Document.html(response.body);
|
||||||
|
|
||||||
|
if (htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div > div > div.detail-info-right > p.detail-info-right-title > span.detail-info-right-title-tip')
|
||||||
|
.isNotEmpty) {
|
||||||
|
final tt = htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div > div > div.detail-info-right > p.detail-info-right-title > span.detail-info-right-title-tip')
|
||||||
|
.map((e) => e.text.trim())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
detail.add(tt[0]);
|
||||||
|
} else {
|
||||||
|
detail.add("");
|
||||||
|
}
|
||||||
|
if (htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div > div > div.detail-info-right > p.detail-info-right-say > a')
|
||||||
|
.isNotEmpty) {
|
||||||
|
final tt = htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div > div > div.detail-info-right > p.detail-info-right-say > a')
|
||||||
|
.map((e) => e.text.trim())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
detail.add(tt[0]);
|
||||||
|
} else {
|
||||||
|
detail.add("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
'body > div > div > div.detail-info-right > p.detail-info-right-content')
|
||||||
|
.isNotEmpty) {
|
||||||
|
final tt = htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
'body > div > div > div.detail-info-right > p.detail-info-right-content')
|
||||||
|
.map((e) => e.text.trim())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
synopsys = tt.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htmll.querySelectorAll('ul > li > a').isNotEmpty) {
|
||||||
|
final udl = htmll
|
||||||
|
.querySelectorAll('ul > li > a ')
|
||||||
|
.where((e) => e.attributes.containsKey('href'))
|
||||||
|
.map((e) => e.attributes['href'])
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (var ok in udl) {
|
||||||
|
chapterUrl.add(ok!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (htmll.querySelectorAll('ul > li > a > div > p.title3').isNotEmpty) {
|
||||||
|
final tt = htmll
|
||||||
|
.querySelectorAll('ul > li > a > div > p.title3')
|
||||||
|
.map((e) => e.text.trim())
|
||||||
|
.toList();
|
||||||
|
for (var ok in tt) {
|
||||||
|
chapterTitle.add(ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (htmll.querySelectorAll('ul > li > a > div > p.title2').isNotEmpty) {
|
||||||
|
final tt = htmll
|
||||||
|
.querySelectorAll('ul > li > a > div > p.title2')
|
||||||
|
.map((e) => e.text.trim())
|
||||||
|
.toList();
|
||||||
|
for (var ok in tt) {
|
||||||
|
chapterDate.add(ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div > div > div.detail-info-right > p.detail-info-right-tag-list > a')
|
||||||
|
.isNotEmpty) {
|
||||||
|
final tt = htmll
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div > div > div.detail-info-right > p.detail-info-right-tag-list > a')
|
||||||
|
.map((e) => e.text.trim())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (var ok in tt) {
|
||||||
|
genre.add(ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GetMangaDetailModel(
|
||||||
|
chapterDate: chapterDate,
|
||||||
|
chapterTitle: chapterTitle,
|
||||||
|
chapterUrl: chapterUrl,
|
||||||
|
detail: detail,
|
||||||
|
genre: genre,
|
||||||
|
image: image,
|
||||||
|
synopsys: synopsys,
|
||||||
|
name: name,
|
||||||
|
url: url,
|
||||||
|
source: source);
|
||||||
|
}
|
||||||
146
lib/services/get_manga_detail.g.dart
Normal file
146
lib/services/get_manga_detail.g.dart
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'get_manga_detail.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$getMangaDetailHash() => r'f8a4047fc7d1661b6abdfcfa0786e0d78a20c8ed';
|
||||||
|
|
||||||
|
/// Copied from Dart SDK
|
||||||
|
class _SystemHash {
|
||||||
|
_SystemHash._();
|
||||||
|
|
||||||
|
static int combine(int hash, int value) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + value);
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finish(int hash) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = hash ^ (hash >> 11);
|
||||||
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GetMangaDetailRef = AutoDisposeFutureProviderRef<GetMangaDetailModel>;
|
||||||
|
|
||||||
|
/// See also [getMangaDetail].
|
||||||
|
@ProviderFor(getMangaDetail)
|
||||||
|
const getMangaDetailProvider = GetMangaDetailFamily();
|
||||||
|
|
||||||
|
/// See also [getMangaDetail].
|
||||||
|
class GetMangaDetailFamily extends Family<AsyncValue<GetMangaDetailModel>> {
|
||||||
|
/// See also [getMangaDetail].
|
||||||
|
const GetMangaDetailFamily();
|
||||||
|
|
||||||
|
/// See also [getMangaDetail].
|
||||||
|
GetMangaDetailProvider call({
|
||||||
|
required String image,
|
||||||
|
required String url,
|
||||||
|
required String name,
|
||||||
|
String lang = '',
|
||||||
|
required String source,
|
||||||
|
}) {
|
||||||
|
return GetMangaDetailProvider(
|
||||||
|
image: image,
|
||||||
|
url: url,
|
||||||
|
name: name,
|
||||||
|
lang: lang,
|
||||||
|
source: source,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GetMangaDetailProvider getProviderOverride(
|
||||||
|
covariant GetMangaDetailProvider provider,
|
||||||
|
) {
|
||||||
|
return call(
|
||||||
|
image: provider.image,
|
||||||
|
url: provider.url,
|
||||||
|
name: provider.name,
|
||||||
|
lang: provider.lang,
|
||||||
|
source: provider.source,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'getMangaDetailProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [getMangaDetail].
|
||||||
|
class GetMangaDetailProvider
|
||||||
|
extends AutoDisposeFutureProvider<GetMangaDetailModel> {
|
||||||
|
/// See also [getMangaDetail].
|
||||||
|
GetMangaDetailProvider({
|
||||||
|
required this.image,
|
||||||
|
required this.url,
|
||||||
|
required this.name,
|
||||||
|
this.lang = '',
|
||||||
|
required this.source,
|
||||||
|
}) : super.internal(
|
||||||
|
(ref) => getMangaDetail(
|
||||||
|
ref,
|
||||||
|
image: image,
|
||||||
|
url: url,
|
||||||
|
name: name,
|
||||||
|
lang: lang,
|
||||||
|
source: source,
|
||||||
|
),
|
||||||
|
from: getMangaDetailProvider,
|
||||||
|
name: r'getMangaDetailProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$getMangaDetailHash,
|
||||||
|
dependencies: GetMangaDetailFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
GetMangaDetailFamily._allTransitiveDependencies,
|
||||||
|
);
|
||||||
|
|
||||||
|
final String image;
|
||||||
|
final String url;
|
||||||
|
final String name;
|
||||||
|
final String lang;
|
||||||
|
final String source;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is GetMangaDetailProvider &&
|
||||||
|
other.image == image &&
|
||||||
|
other.url == url &&
|
||||||
|
other.name == name &&
|
||||||
|
other.lang == lang &&
|
||||||
|
other.source == source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, image.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, url.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, name.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, lang.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, source.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||||
59
lib/services/get_popular_manga.dart
Normal file
59
lib/services/get_popular_manga.dart
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:mangayomi/services/http_res_to_dom_html.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
part 'get_popular_manga.g.dart';
|
||||||
|
|
||||||
|
class GetMangaModel {
|
||||||
|
late List<String?> url;
|
||||||
|
late List<String?> name;
|
||||||
|
late List<String?> image;
|
||||||
|
GetMangaModel({
|
||||||
|
required this.name,
|
||||||
|
required this.url,
|
||||||
|
required this.image,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<GetMangaModel> getPopularManga(GetPopularMangaRef ref,
|
||||||
|
{required String source, required int page}) async {
|
||||||
|
List<String?> url = [];
|
||||||
|
List<String?> name = [];
|
||||||
|
List<String?> image = [];
|
||||||
|
|
||||||
|
//mangahere
|
||||||
|
if (source == "mangahere") {
|
||||||
|
final dom = await httpResToDom(url: 'https://www.mangahere.cc/ranking/');
|
||||||
|
if (dom
|
||||||
|
.querySelectorAll(
|
||||||
|
'body > div.container.weekrank.ranking > div > div > ul > li > a')
|
||||||
|
.isNotEmpty) {
|
||||||
|
url = dom
|
||||||
|
.querySelectorAll(
|
||||||
|
'body > div.container.weekrank.ranking > div > div > ul > li > a ')
|
||||||
|
.where((e) => e.attributes.containsKey('href'))
|
||||||
|
.map((e) => e.attributes['href'])
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
image = dom
|
||||||
|
.querySelectorAll(
|
||||||
|
' body > div.container.weekrank.ranking > div > div > ul > li > a > img')
|
||||||
|
.where((e) => e.attributes.containsKey('src'))
|
||||||
|
.where((e) => e.attributes['src']!.contains("cover"))
|
||||||
|
.map((e) => e.attributes['src'])
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
name = dom
|
||||||
|
.querySelectorAll(
|
||||||
|
'body > div.container.weekrank.ranking > div > div > ul > li > a ')
|
||||||
|
.where((e) => e.attributes.containsKey('title'))
|
||||||
|
.map((e) => e.attributes['title'])
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GetMangaModel(
|
||||||
|
name: name,
|
||||||
|
url: url,
|
||||||
|
image: image,
|
||||||
|
);
|
||||||
|
}
|
||||||
121
lib/services/get_popular_manga.g.dart
Normal file
121
lib/services/get_popular_manga.g.dart
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'get_popular_manga.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$getPopularMangaHash() => r'4ab45f760fe457710bb9d09c72faef2fc09261e2';
|
||||||
|
|
||||||
|
/// Copied from Dart SDK
|
||||||
|
class _SystemHash {
|
||||||
|
_SystemHash._();
|
||||||
|
|
||||||
|
static int combine(int hash, int value) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + value);
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finish(int hash) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = hash ^ (hash >> 11);
|
||||||
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef GetPopularMangaRef = AutoDisposeFutureProviderRef<GetMangaModel>;
|
||||||
|
|
||||||
|
/// See also [getPopularManga].
|
||||||
|
@ProviderFor(getPopularManga)
|
||||||
|
const getPopularMangaProvider = GetPopularMangaFamily();
|
||||||
|
|
||||||
|
/// See also [getPopularManga].
|
||||||
|
class GetPopularMangaFamily extends Family<AsyncValue<GetMangaModel>> {
|
||||||
|
/// See also [getPopularManga].
|
||||||
|
const GetPopularMangaFamily();
|
||||||
|
|
||||||
|
/// See also [getPopularManga].
|
||||||
|
GetPopularMangaProvider call({
|
||||||
|
required String source,
|
||||||
|
required int page,
|
||||||
|
}) {
|
||||||
|
return GetPopularMangaProvider(
|
||||||
|
source: source,
|
||||||
|
page: page,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
GetPopularMangaProvider getProviderOverride(
|
||||||
|
covariant GetPopularMangaProvider provider,
|
||||||
|
) {
|
||||||
|
return call(
|
||||||
|
source: provider.source,
|
||||||
|
page: provider.page,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'getPopularMangaProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [getPopularManga].
|
||||||
|
class GetPopularMangaProvider extends AutoDisposeFutureProvider<GetMangaModel> {
|
||||||
|
/// See also [getPopularManga].
|
||||||
|
GetPopularMangaProvider({
|
||||||
|
required this.source,
|
||||||
|
required this.page,
|
||||||
|
}) : super.internal(
|
||||||
|
(ref) => getPopularManga(
|
||||||
|
ref,
|
||||||
|
source: source,
|
||||||
|
page: page,
|
||||||
|
),
|
||||||
|
from: getPopularMangaProvider,
|
||||||
|
name: r'getPopularMangaProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$getPopularMangaHash,
|
||||||
|
dependencies: GetPopularMangaFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
GetPopularMangaFamily._allTransitiveDependencies,
|
||||||
|
);
|
||||||
|
|
||||||
|
final String source;
|
||||||
|
final int page;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is GetPopularMangaProvider &&
|
||||||
|
other.source == source &&
|
||||||
|
other.page == page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, source.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, page.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||||
7
lib/services/http_res_to_dom_html.dart
Normal file
7
lib/services/http_res_to_dom_html.dart
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import 'package:html/dom.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
Future<Document> httpResToDom({required String url}) async {
|
||||||
|
final response = await http.get(Uri.parse(url));
|
||||||
|
return Document.html(response.body);
|
||||||
|
}
|
||||||
33
lib/utils/cached_network.dart
Normal file
33
lib/utils/cached_network.dart
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Widget cachedNetworkImage(
|
||||||
|
{Map<String, String>? headers,
|
||||||
|
required String imageUrl,
|
||||||
|
required double? width,
|
||||||
|
required double? height,
|
||||||
|
required BoxFit? fit,
|
||||||
|
AlignmentGeometry? alignment}) {
|
||||||
|
if (kIsWeb) {
|
||||||
|
return Image.network(
|
||||||
|
imageUrl,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
alignment: alignment ?? Alignment.center,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return CachedNetworkImage(
|
||||||
|
httpHeaders: headers ?? {},
|
||||||
|
imageUrl: imageUrl,
|
||||||
|
fit: fit,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
errorWidget: (context, url, error) => const Icon(
|
||||||
|
Icons.error,
|
||||||
|
size: 50,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:mangayomi/models/manga_type.dart';
|
||||||
|
|
||||||
class SourcesScreen extends StatefulWidget {
|
class SourcesScreen extends StatefulWidget {
|
||||||
const SourcesScreen({super.key});
|
const SourcesScreen({super.key});
|
||||||
|
|
@ -13,7 +15,11 @@ class _SourcesScreenState extends State<SourcesScreen> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
context.push('/mangaHome',
|
||||||
|
extra: MangaType(
|
||||||
|
isFullData: true, lang: 'en', source: 'mangahere'));
|
||||||
|
},
|
||||||
leading: Container(
|
leading: Container(
|
||||||
height: 37,
|
height: 37,
|
||||||
width: 37,
|
width: 37,
|
||||||
|
|
@ -24,7 +30,8 @@ class _SourcesScreenState extends State<SourcesScreen> {
|
||||||
title: const Text('MangaHere'),
|
title: const Text('MangaHere'),
|
||||||
trailing: SizedBox(
|
trailing: SizedBox(
|
||||||
width: 110,
|
width: 110,
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: const [
|
children: const [
|
||||||
Text(
|
Text(
|
||||||
"Latest",
|
"Latest",
|
||||||
|
|
|
||||||
183
lib/views/manga/home/home.dart
Normal file
183
lib/views/manga/home/home.dart
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:mangayomi/models/manga_type.dart';
|
||||||
|
import 'package:mangayomi/services/get_manga_detail.dart';
|
||||||
|
import 'package:mangayomi/services/get_popular_manga.dart';
|
||||||
|
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||||
|
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||||
|
import 'package:mangayomi/views/widgets/gridview_widget.dart';
|
||||||
|
import 'package:mangayomi/views/widgets/manga_image_card_widget.dart';
|
||||||
|
|
||||||
|
class MangaHomeScreen extends ConsumerStatefulWidget {
|
||||||
|
final MangaType mangaType;
|
||||||
|
const MangaHomeScreen({required this.mangaType, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<MangaHomeScreen> createState() => _MangaHomeScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
||||||
|
bool _isLoading = false;
|
||||||
|
final ScrollController _scrollController = ScrollController();
|
||||||
|
int _length = 10;
|
||||||
|
int _page = 1;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final getManga = ref.watch(
|
||||||
|
getPopularMangaProvider(source: widget.mangaType.source!, page: _page));
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('${widget.mangaType.source}'),
|
||||||
|
actions: [],
|
||||||
|
),
|
||||||
|
body: getManga.when(
|
||||||
|
data: (data) {
|
||||||
|
_scrollController.addListener(() {
|
||||||
|
if (_scrollController.position.pixels ==
|
||||||
|
_scrollController.position.maxScrollExtent) {
|
||||||
|
if (!_isLoading) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.mangaType.isFullData!) {
|
||||||
|
Future.delayed(const Duration(seconds: 1)).then((value) {
|
||||||
|
_length = _length + 10;
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_page = _page + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ref
|
||||||
|
.watch(getPopularMangaProvider(
|
||||||
|
source: widget.mangaType.source!, page: _page)
|
||||||
|
.future)
|
||||||
|
.then(
|
||||||
|
(value) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
data.url.addAll(value.url);
|
||||||
|
data.name.addAll(value.name);
|
||||||
|
data.image.addAll(value.image);
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: GridViewWidget(
|
||||||
|
controller: _scrollController,
|
||||||
|
itemCount:
|
||||||
|
widget.mangaType.isFullData! ? _length : data.url.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == data.url.length - 1) {
|
||||||
|
return _buildProgressIndicator();
|
||||||
|
}
|
||||||
|
return MangaHomeImageCard(
|
||||||
|
url: data.url[index]!,
|
||||||
|
name: data.name[index]!,
|
||||||
|
image: data.image[index]!,
|
||||||
|
source: widget.mangaType.source!,
|
||||||
|
lang: widget.mangaType.lang!,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
error: (error, stackTrace) => const Center(child: Text("Error")),
|
||||||
|
loading: () => const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildProgressIndicator() {
|
||||||
|
return _isLoading
|
||||||
|
? const Center(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 100,
|
||||||
|
width: 200,
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MangaHomeImageCard extends ConsumerStatefulWidget {
|
||||||
|
final String image;
|
||||||
|
final String url;
|
||||||
|
final String name;
|
||||||
|
final String source;
|
||||||
|
final String lang;
|
||||||
|
const MangaHomeImageCard({
|
||||||
|
super.key,
|
||||||
|
required this.url,
|
||||||
|
required this.name,
|
||||||
|
required this.image,
|
||||||
|
required this.source,
|
||||||
|
required this.lang,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<MangaHomeImageCard> createState() => _MangaHomeImageCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MangaHomeImageCardState extends ConsumerState<MangaHomeImageCard>
|
||||||
|
with AutomaticKeepAliveClientMixin<MangaHomeImageCard> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
final getMangaDetail = ref.watch(getMangaDetailProvider(
|
||||||
|
source: widget.source,
|
||||||
|
image: widget.image,
|
||||||
|
name: widget.name,
|
||||||
|
url: widget.url,
|
||||||
|
));
|
||||||
|
|
||||||
|
return getMangaDetail.when(
|
||||||
|
data: (data) {
|
||||||
|
return MangaImageCardWidget(
|
||||||
|
getMangaDetailModel: data,
|
||||||
|
lang: widget.lang,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
loading: () => CoverViewWidget(children: [
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
child: Container(
|
||||||
|
color: Theme.of(context).cardColor,
|
||||||
|
width: 200,
|
||||||
|
height: 270,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
BottomTextWidget(text: widget.name)
|
||||||
|
]),
|
||||||
|
error: (error, stackTrace) => const Center(child: Text("Error")),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
||||||
36
lib/views/widgets/bottom_text_widget.dart
Normal file
36
lib/views/widgets/bottom_text_widget.dart
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class BottomTextWidget extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
const BottomTextWidget({super.key, required this.text});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.3), //New
|
||||||
|
offset: const Offset(0.5, 0.9),
|
||||||
|
blurRadius: 3.0)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13.0,
|
||||||
|
color: Colors.white,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(offset: Offset(0.5, 0.9), blurRadius: 3.0)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
lib/views/widgets/cover_view_widget.dart
Normal file
18
lib/views/widgets/cover_view_widget.dart
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
class CoverViewWidget extends StatelessWidget {
|
||||||
|
final List<Widget> children;
|
||||||
|
const CoverViewWidget({super.key, required this.children});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
child: Stack(
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
lib/views/widgets/gridview_widget.dart
Normal file
27
lib/views/widgets/gridview_widget.dart
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class GridViewWidget extends StatelessWidget {
|
||||||
|
final ScrollController? controller;
|
||||||
|
final int? itemCount;
|
||||||
|
final Widget? Function(BuildContext, int) itemBuilder;
|
||||||
|
const GridViewWidget(
|
||||||
|
{super.key,
|
||||||
|
this.controller,
|
||||||
|
required this.itemCount,
|
||||||
|
required this.itemBuilder});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
child: GridView.builder(
|
||||||
|
controller: controller,
|
||||||
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
|
maxCrossAxisExtent: 220,
|
||||||
|
mainAxisExtent: 280,
|
||||||
|
),
|
||||||
|
itemCount: itemCount,
|
||||||
|
itemBuilder: itemBuilder),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
lib/views/widgets/manga_image_card_widget.dart
Normal file
45
lib/views/widgets/manga_image_card_widget.dart
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:mangayomi/services/get_manga_detail.dart';
|
||||||
|
import 'package:mangayomi/utils/cached_network.dart';
|
||||||
|
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||||
|
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||||
|
|
||||||
|
class MangaImageCardWidget extends ConsumerStatefulWidget {
|
||||||
|
final String lang;
|
||||||
|
final bool isLoading;
|
||||||
|
|
||||||
|
final GetMangaDetailModel? getMangaDetailModel;
|
||||||
|
|
||||||
|
const MangaImageCardWidget({
|
||||||
|
required this.lang,
|
||||||
|
super.key,
|
||||||
|
this.isLoading = false,
|
||||||
|
required this.getMangaDetailModel,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<MangaImageCardWidget> createState() =>
|
||||||
|
_MangaImageCardWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MangaImageCardWidgetState extends ConsumerState<MangaImageCardWidget> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () async {},
|
||||||
|
child: CoverViewWidget(children: [
|
||||||
|
cachedNetworkImage(
|
||||||
|
headers: {
|
||||||
|
"Referer": "https://www.mangahere.cc/",
|
||||||
|
"Cookie": "isAdult=1"
|
||||||
|
},
|
||||||
|
imageUrl: widget.getMangaDetailModel!.image!,
|
||||||
|
width: 200,
|
||||||
|
height: 270,
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
BottomTextWidget(text: widget.getMangaDetailModel!.name!)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <flutter_js/flutter_js_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
flutter_js
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,12 @@
|
||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import flutter_js
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import sqflite
|
import sqflite
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
FlutterJsPlugin.register(with: registry.registrar(forPlugin: "FlutterJsPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
106
pubspec.lock
106
pubspec.lock
|
|
@ -5,18 +5,26 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
sha256: a36ec4843dc30ea6bf652bf25e3448db6c5e8bcf4aa55f063a5d1dad216d8214
|
sha256: "98d1d33ed129b372846e862de23a0fc365745f4d7b5e786ce667fcbbb7ac5c07"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "58.0.0"
|
version: "55.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
sha256: cc4242565347e98424ce9945c819c192ec0838cb9d1f6aa4a97cc96becbc5b27
|
sha256: "881348aed9b0b425882c97732629a6a31093c8ff20fc4b3b03fb9d3d50a3a126"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.10.0"
|
version: "5.7.1"
|
||||||
|
analyzer_plugin:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer_plugin
|
||||||
|
sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.11.2"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -145,6 +153,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.2"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.5"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -185,6 +201,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.2"
|
||||||
|
csslib:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: csslib
|
||||||
|
sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.17.2"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -193,6 +217,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.5"
|
||||||
|
custom_lint:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: custom_lint
|
||||||
|
sha256: "32648ef4f1dda618d98a22bc958fa79d479895891061e63338bec510b67e821a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.2"
|
||||||
|
custom_lint_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: custom_lint_core
|
||||||
|
sha256: cc20ce83432675abcc109b766aad2e420946eaeecc32ffd34bada389cdaa9a74
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.2"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -254,6 +294,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.0"
|
version: "3.3.0"
|
||||||
|
flutter_js:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_js
|
||||||
|
sha256: "86922b593f80512dfe72586aab826123708992ecd07476349828e9893d7cbaff"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.0"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
|
@ -280,6 +328,14 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
freezed_annotation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: freezed_annotation
|
||||||
|
sha256: aeac15850ef1b38ee368d4c53ba9a847e900bb2c53a4db3f6881cbb3cb684338
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
frontend_server_client:
|
frontend_server_client:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -344,8 +400,16 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
html:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: html
|
||||||
|
sha256: "79d498e6d6761925a34ee5ea8fa6dfef38607781d2fa91e37523474282af55cb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.15.2"
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482"
|
sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482"
|
||||||
|
|
@ -576,6 +640,30 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.2"
|
||||||
|
riverpod_analyzer_utils:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: riverpod_analyzer_utils
|
||||||
|
sha256: "7c2d4de69ba06107c3d7f1b3f43dc3fbdcb2f666b480560af654b4eb89af0d6d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
|
riverpod_annotation:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: riverpod_annotation
|
||||||
|
sha256: c0f51b3fc5a0cefcbcddb35a10ad542d6c38919c081a25279045158ac7955cfb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
riverpod_generator:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: riverpod_generator
|
||||||
|
sha256: "2c08a6fbbe80d489f1c5208e5358bfdd4d612f1777c47fdb9ff91bb7a2670529"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.4"
|
||||||
rxdart:
|
rxdart:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -685,6 +773,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.0"
|
||||||
|
sync_http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sync_http
|
||||||
|
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.1"
|
||||||
synchronized:
|
synchronized:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,10 @@ dependencies:
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
hive_generator: ^2.0.0
|
hive_generator: ^2.0.0
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
|
http: ^0.13.5
|
||||||
|
riverpod_annotation: ^2.0.2
|
||||||
|
html: ^0.15.2
|
||||||
|
flutter_js: ^0.6.0
|
||||||
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
|
|
@ -47,6 +51,7 @@ dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
build_runner: ^2.3.3
|
build_runner: ^2.3.3
|
||||||
|
riverpod_generator: ^2.1.4
|
||||||
|
|
||||||
# The "flutter_lints" package below contains a set of recommended lints to
|
# The "flutter_lints" package below contains a set of recommended lints to
|
||||||
# encourage good coding practices. The lint set provided by the package is
|
# encourage good coding practices. The lint set provided by the package is
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <flutter_js/flutter_js_plugin.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
FlutterJsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FlutterJsPlugin"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
flutter_js
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue