mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 15:57:25 +00:00
like a comic
This commit is contained in:
@@ -95,6 +95,8 @@ abstract class LoadingState<T extends StatefulWidget, S extends Object>
|
|||||||
|
|
||||||
Future<Res<S>> loadData();
|
Future<Res<S>> loadData();
|
||||||
|
|
||||||
|
void onDataLoaded() {}
|
||||||
|
|
||||||
Widget buildContent(BuildContext context, S data);
|
Widget buildContent(BuildContext context, S data);
|
||||||
|
|
||||||
Widget? buildFrame(BuildContext context, Widget child) => null;
|
Widget? buildFrame(BuildContext context, Widget child) => null;
|
||||||
@@ -118,6 +120,7 @@ abstract class LoadingState<T extends StatefulWidget, S extends Object>
|
|||||||
isLoading = false;
|
isLoading = false;
|
||||||
data = value.data;
|
data = value.data;
|
||||||
});
|
});
|
||||||
|
onDataLoaded();
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
@@ -3,7 +3,6 @@ library comic_source;
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@@ -45,6 +44,8 @@ typedef GetThumbnailLoadingConfigFunc = Map<String, dynamic> Function(
|
|||||||
|
|
||||||
typedef ComicThumbnailLoader = Future<Res<List<String>>> Function(String comicId, String? next);
|
typedef ComicThumbnailLoader = Future<Res<List<String>>> Function(String comicId, String? next);
|
||||||
|
|
||||||
|
typedef LikeOrUnlikeComicFunc = Future<Res<bool>> Function(String comicId, bool isLiking);
|
||||||
|
|
||||||
class ComicSource {
|
class ComicSource {
|
||||||
static final List<ComicSource> _sources = [];
|
static final List<ComicSource> _sources = [];
|
||||||
|
|
||||||
@@ -171,6 +172,8 @@ class ComicSource {
|
|||||||
|
|
||||||
final RegExp? idMatcher;
|
final RegExp? idMatcher;
|
||||||
|
|
||||||
|
final LikeOrUnlikeComicFunc? likeOrUnlikeComic;
|
||||||
|
|
||||||
Future<void> loadData() async {
|
Future<void> loadData() async {
|
||||||
var file = File("${App.dataPath}/comic_source/$key.data");
|
var file = File("${App.dataPath}/comic_source/$key.data");
|
||||||
if (await file.exists()) {
|
if (await file.exists()) {
|
||||||
@@ -229,7 +232,8 @@ class ComicSource {
|
|||||||
this.url,
|
this.url,
|
||||||
this.version,
|
this.version,
|
||||||
this.commentsLoader,
|
this.commentsLoader,
|
||||||
this.sendCommentFunc)
|
this.sendCommentFunc,
|
||||||
|
this.likeOrUnlikeComic)
|
||||||
: idMatcher = null;
|
: idMatcher = null;
|
||||||
|
|
||||||
ComicSource.unknown(this.key)
|
ComicSource.unknown(this.key)
|
||||||
@@ -252,7 +256,8 @@ class ComicSource {
|
|||||||
version = "",
|
version = "",
|
||||||
commentsLoader = null,
|
commentsLoader = null,
|
||||||
sendCommentFunc = null,
|
sendCommentFunc = null,
|
||||||
idMatcher = null;
|
idMatcher = null,
|
||||||
|
likeOrUnlikeComic = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountConfig {
|
class AccountConfig {
|
||||||
|
@@ -136,6 +136,7 @@ class ComicSourceParser {
|
|||||||
final favoriteData = _loadFavoriteData();
|
final favoriteData = _loadFavoriteData();
|
||||||
final commentsLoader = _parseCommentsLoader();
|
final commentsLoader = _parseCommentsLoader();
|
||||||
final sendCommentFunc = _parseSendCommentFunc();
|
final sendCommentFunc = _parseSendCommentFunc();
|
||||||
|
final likeFunc = _parseLikeFunc();
|
||||||
|
|
||||||
var source = ComicSource(
|
var source = ComicSource(
|
||||||
_name!,
|
_name!,
|
||||||
@@ -158,6 +159,7 @@ class ComicSourceParser {
|
|||||||
version ?? "1.0.0",
|
version ?? "1.0.0",
|
||||||
commentsLoader,
|
commentsLoader,
|
||||||
sendCommentFunc,
|
sendCommentFunc,
|
||||||
|
likeFunc,
|
||||||
);
|
);
|
||||||
|
|
||||||
await source.loadData();
|
await source.loadData();
|
||||||
@@ -654,4 +656,21 @@ class ComicSourceParser {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LikeOrUnlikeComicFunc? _parseLikeFunc() {
|
||||||
|
if (!_checkExists("comic.likeOrUnlikeComic")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (id, isLiking) async {
|
||||||
|
try {
|
||||||
|
await JsEngine().runCode("""
|
||||||
|
ComicSource.sources.$_key.comic.likeOrUnlikeComic(${jsonEncode(id)}, ${jsonEncode(isLiking)})
|
||||||
|
""");
|
||||||
|
return const Res(true);
|
||||||
|
} catch (e, s) {
|
||||||
|
Log.error("Network", "$e\n$s");
|
||||||
|
return Res.error(e.toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -86,6 +86,12 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
return comicSource!.loadComicInfo!(widget.id);
|
return comicSource!.loadComicInfo!(widget.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
onDataLoaded() {
|
||||||
|
isLiked = comic.isLiked ?? false;
|
||||||
|
isFavorite = comic.isFavorite ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
Iterable<Widget> buildTitle() sync* {
|
Iterable<Widget> buildTitle() sync* {
|
||||||
yield SliverAppbar(
|
yield SliverAppbar(
|
||||||
title: AnimatedOpacity(
|
title: AnimatedOpacity(
|
||||||
@@ -171,9 +177,9 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
_ActionButton(
|
_ActionButton(
|
||||||
icon: const Icon(Icons.favorite_border),
|
icon: const Icon(Icons.favorite_border),
|
||||||
activeIcon: const Icon(Icons.favorite),
|
activeIcon: const Icon(Icons.favorite),
|
||||||
isActive: data!.isLiked,
|
isActive: isLiked,
|
||||||
text: (data!.likesCount ??
|
text: (data!.likesCount ??
|
||||||
(comic.isLiked! ? 'Liked'.tl : 'Like'.tl))
|
(isLiked ? 'Liked'.tl : 'Like'.tl))
|
||||||
.toString(),
|
.toString(),
|
||||||
isLoading: isLiking,
|
isLoading: isLiking,
|
||||||
onPressed: likeOrUnlike,
|
onPressed: likeOrUnlike,
|
||||||
@@ -182,18 +188,16 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
_ActionButton(
|
_ActionButton(
|
||||||
icon: const Icon(Icons.bookmark_border),
|
icon: const Icon(Icons.bookmark_border),
|
||||||
activeIcon: const Icon(Icons.bookmark),
|
activeIcon: const Icon(Icons.bookmark),
|
||||||
isActive: (data!.isFavorite ?? false) || isAddToLocalFav,
|
isActive: isFavorite || isAddToLocalFav,
|
||||||
text: 'Favorite'.tl,
|
text: 'Favorite'.tl,
|
||||||
isLoading: isFavoriting,
|
onPressed: openFavPanel,
|
||||||
onPressed: favoriteOrUnfavorite,
|
|
||||||
iconColor: context.useTextColor(Colors.purple),
|
iconColor: context.useTextColor(Colors.purple),
|
||||||
),
|
),
|
||||||
if (comicSource.commentsLoader != null)
|
if (comicSource.commentsLoader != null)
|
||||||
_ActionButton(
|
_ActionButton(
|
||||||
icon: const Icon(Icons.comment),
|
icon: const Icon(Icons.comment),
|
||||||
text: (comic.commentsCount ?? 'Comments'.tl).toString(),
|
text: (comic.commentsCount ?? 'Comments'.tl).toString(),
|
||||||
isLoading: isFavoriting,
|
onPressed: showComments,
|
||||||
onPressed: favoriteOrUnfavorite,
|
|
||||||
iconColor: context.useTextColor(Colors.green),
|
iconColor: context.useTextColor(Colors.green),
|
||||||
),
|
),
|
||||||
_ActionButton(
|
_ActionButton(
|
||||||
@@ -397,13 +401,27 @@ abstract mixin class _ComicPageActions {
|
|||||||
|
|
||||||
bool isLiking = false;
|
bool isLiking = false;
|
||||||
|
|
||||||
void likeOrUnlike() {}
|
bool isLiked = false;
|
||||||
|
|
||||||
|
void likeOrUnlike() async {
|
||||||
|
if(isLiking) return;
|
||||||
|
isLiking = true;
|
||||||
|
update();
|
||||||
|
var res = await comicSource.likeOrUnlikeComic!(comic.id, isLiked ?? false);
|
||||||
|
if(res.error) {
|
||||||
|
App.rootContext.showMessage(message: res.errorMessage!);
|
||||||
|
} else {
|
||||||
|
isLiked = !isLiked;
|
||||||
|
}
|
||||||
|
isLiking = false;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
bool isAddToLocalFav = false;
|
bool isAddToLocalFav = false;
|
||||||
|
|
||||||
bool isFavoriting = false;
|
bool isFavorite = false;
|
||||||
|
|
||||||
void favoriteOrUnfavorite() {}
|
void openFavPanel() {}
|
||||||
|
|
||||||
void share() {}
|
void share() {}
|
||||||
|
|
||||||
@@ -421,6 +439,8 @@ abstract mixin class _ComicPageActions {
|
|||||||
void onTagTap(String tag, String namespace) {}
|
void onTagTap(String tag, String namespace) {}
|
||||||
|
|
||||||
void showMoreActions() {}
|
void showMoreActions() {}
|
||||||
|
|
||||||
|
void showComments() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ActionButton extends StatelessWidget {
|
class _ActionButton extends StatelessWidget {
|
||||||
@@ -460,7 +480,11 @@ class _ActionButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: onPressed,
|
onTap: () {
|
||||||
|
if(!(isLoading ?? false)) {
|
||||||
|
onPressed();
|
||||||
|
}
|
||||||
|
},
|
||||||
borderRadius: BorderRadius.circular(18),
|
borderRadius: BorderRadius.circular(18),
|
||||||
child: IconTheme.merge(
|
child: IconTheme.merge(
|
||||||
data: IconThemeData(size: 20, color: iconColor),
|
data: IconThemeData(size: 20, color: iconColor),
|
||||||
|
Reference in New Issue
Block a user