mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 15:57:25 +00:00
Show read button if loading fails.
This commit is contained in:
@@ -7,6 +7,7 @@ class NetworkError extends StatelessWidget {
|
|||||||
this.retry,
|
this.retry,
|
||||||
this.withAppbar = true,
|
this.withAppbar = true,
|
||||||
this.buttonText,
|
this.buttonText,
|
||||||
|
this.action,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String message;
|
final String message;
|
||||||
@@ -17,6 +18,8 @@ class NetworkError extends StatelessWidget {
|
|||||||
|
|
||||||
final String? buttonText;
|
final String? buttonText;
|
||||||
|
|
||||||
|
final Widget? action;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var cfe = CloudflareException.fromString(message);
|
var cfe = CloudflareException.fromString(message);
|
||||||
@@ -67,9 +70,16 @@ class NetworkError extends StatelessWidget {
|
|||||||
child: Text('Verify'.tl),
|
child: Text('Verify'.tl),
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
FilledButton(
|
Row(
|
||||||
onPressed: retry,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
child: Text(buttonText ?? 'Retry'.tl),
|
children: [
|
||||||
|
if (action != null)
|
||||||
|
action!.paddingRight(8),
|
||||||
|
FilledButton(
|
||||||
|
onPressed: retry,
|
||||||
|
child: Text(buttonText ?? 'Retry'.tl),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -77,8 +77,10 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onReadEnd() {
|
void onReadEnd() {
|
||||||
history ??=
|
history ??= HistoryManager().find(
|
||||||
HistoryManager().find(widget.id, ComicType(widget.sourceKey.hashCode));
|
widget.id,
|
||||||
|
ComicType(widget.sourceKey.hashCode),
|
||||||
|
);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +95,32 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildError() {
|
||||||
|
final isDownloaded = LocalManager().isDownloaded(
|
||||||
|
widget.id,
|
||||||
|
ComicType.fromKey(widget.sourceKey),
|
||||||
|
);
|
||||||
|
Widget? action;
|
||||||
|
if (isDownloaded) {
|
||||||
|
action = FilledButton.tonal(
|
||||||
|
child: Text("Read".tl),
|
||||||
|
onPressed: () {
|
||||||
|
final localComic = LocalManager().find(
|
||||||
|
widget.id,
|
||||||
|
ComicType.fromKey(widget.sourceKey),
|
||||||
|
);
|
||||||
|
if (localComic == null) {
|
||||||
|
context.showMessage(message: "Local comic not found".tl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
localComic.read();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return NetworkError(message: error!, retry: retry, action: action);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
scrollController.addListener(onScroll);
|
scrollController.addListener(onScroll);
|
||||||
@@ -114,7 +142,8 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
ComicDetails get comic => data!;
|
ComicDetails get comic => data!;
|
||||||
|
|
||||||
void onScroll() {
|
void onScroll() {
|
||||||
var offset = scrollController.position.pixels -
|
var offset =
|
||||||
|
scrollController.position.pixels -
|
||||||
scrollController.position.minScrollExtent;
|
scrollController.position.minScrollExtent;
|
||||||
var showFAB = offset > 0;
|
var showFAB = offset > 0;
|
||||||
if (showFAB != this.showFAB) {
|
if (showFAB != this.showFAB) {
|
||||||
@@ -145,9 +174,11 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
floatingActionButton: showFAB
|
floatingActionButton: showFAB
|
||||||
? FloatingActionButton(
|
? FloatingActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
scrollController.animateTo(0,
|
scrollController.animateTo(
|
||||||
duration: const Duration(milliseconds: 200),
|
0,
|
||||||
curve: Curves.ease);
|
duration: const Duration(milliseconds: 200),
|
||||||
|
curve: Curves.ease,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.arrow_upward),
|
child: const Icon(Icons.arrow_upward),
|
||||||
)
|
)
|
||||||
@@ -164,7 +195,9 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
buildThumbnails(),
|
buildThumbnails(),
|
||||||
buildRecommend(),
|
buildRecommend(),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: EdgeInsets.only(bottom: context.padding.bottom + 80), // Add additional padding for FAB
|
padding: EdgeInsets.only(
|
||||||
|
bottom: context.padding.bottom + 80,
|
||||||
|
), // Add additional padding for FAB
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -190,12 +223,9 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
initialPage: history?.page,
|
initialPage: history?.page,
|
||||||
initialChapter: history?.ep,
|
initialChapter: history?.ep,
|
||||||
initialChapterGroup: history?.group,
|
initialChapterGroup: history?.group,
|
||||||
history: history ??
|
history:
|
||||||
History.fromModel(
|
history ??
|
||||||
model: localComic,
|
History.fromModel(model: localComic, ep: 0, page: 0),
|
||||||
ep: 0,
|
|
||||||
page: 0,
|
|
||||||
),
|
|
||||||
author: localComic.subTitle ?? '',
|
author: localComic.subTitle ?? '',
|
||||||
tags: localComic.tags,
|
tags: localComic.tags,
|
||||||
);
|
);
|
||||||
@@ -215,8 +245,10 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
widget.id,
|
widget.id,
|
||||||
ComicType(widget.sourceKey.hashCode),
|
ComicType(widget.sourceKey.hashCode),
|
||||||
);
|
);
|
||||||
history =
|
history = HistoryManager().find(
|
||||||
HistoryManager().find(widget.id, ComicType(widget.sourceKey.hashCode));
|
widget.id,
|
||||||
|
ComicType(widget.sourceKey.hashCode),
|
||||||
|
);
|
||||||
return comicSource.loadComicInfo!(widget.id);
|
return comicSource.loadComicInfo!(widget.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,11 +257,7 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
isLiked = comic.isLiked ?? false;
|
isLiked = comic.isLiked ?? false;
|
||||||
isFavorite = comic.isFavorite ?? false;
|
isFavorite = comic.isFavorite ?? false;
|
||||||
if (comic.chapters == null) {
|
if (comic.chapters == null) {
|
||||||
isDownloaded = LocalManager().isDownloaded(
|
isDownloaded = LocalManager().isDownloaded(comic.id, comic.comicType, 0);
|
||||||
comic.id,
|
|
||||||
comic.comicType,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +270,9 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: showMoreActions, icon: const Icon(Icons.more_horiz))
|
onPressed: showMoreActions,
|
||||||
|
icon: const Icon(Icons.more_horiz),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -288,8 +318,10 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
children: [
|
children: [
|
||||||
SelectableText(comic.title, style: ts.s18),
|
SelectableText(comic.title, style: ts.s18),
|
||||||
if (comic.subTitle != null)
|
if (comic.subTitle != null)
|
||||||
SelectableText(comic.subTitle!, style: ts.s14)
|
SelectableText(
|
||||||
.paddingVertical(4),
|
comic.subTitle!,
|
||||||
|
style: ts.s14,
|
||||||
|
).paddingVertical(4),
|
||||||
Text(
|
Text(
|
||||||
(ComicSource.find(comic.sourceKey)?.name) ?? '',
|
(ComicSource.find(comic.sourceKey)?.name) ?? '',
|
||||||
style: ts.s12,
|
style: ts.s12,
|
||||||
@@ -338,10 +370,11 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
icon: const Icon(Icons.favorite_border),
|
icon: const Icon(Icons.favorite_border),
|
||||||
activeIcon: const Icon(Icons.favorite),
|
activeIcon: const Icon(Icons.favorite),
|
||||||
isActive: isLiked,
|
isActive: isLiked,
|
||||||
text: ((data!.likesCount != null)
|
text:
|
||||||
? (data!.likesCount! + (isLiked ? 1 : 0))
|
((data!.likesCount != null)
|
||||||
: (isLiked ? 'Liked'.tl : 'Like'.tl))
|
? (data!.likesCount! + (isLiked ? 1 : 0))
|
||||||
.toString(),
|
: (isLiked ? 'Liked'.tl : 'Like'.tl))
|
||||||
|
.toString(),
|
||||||
isLoading: isLiking,
|
isLoading: isLiking,
|
||||||
onPressed: likeOrUnlike,
|
onPressed: likeOrUnlike,
|
||||||
iconColor: context.useTextColor(Colors.red),
|
iconColor: context.useTextColor(Colors.red),
|
||||||
@@ -383,9 +416,11 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: hasHistory
|
child: hasHistory
|
||||||
? FilledButton(
|
? FilledButton(
|
||||||
onPressed: continueRead, child: Text("Continue".tl))
|
onPressed: continueRead,
|
||||||
|
child: Text("Continue".tl),
|
||||||
|
)
|
||||||
: FilledButton(onPressed: read, child: Text("Read".tl)),
|
: FilledButton(onPressed: read, child: Text("Read".tl)),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
).paddingHorizontal(16).paddingVertical(8),
|
).paddingHorizontal(16).paddingVertical(8),
|
||||||
if (history != null)
|
if (history != null)
|
||||||
@@ -412,19 +447,20 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
var epName = "E$ep";
|
var epName = "E$ep";
|
||||||
String? groupName;
|
String? groupName;
|
||||||
try {
|
try {
|
||||||
if (group == null){
|
if (group == null) {
|
||||||
epName = comic.chapters!.titles.elementAt(
|
epName = comic.chapters!.titles.elementAt(
|
||||||
math.min(ep - 1, comic.chapters!.length - 1),
|
math.min(ep - 1, comic.chapters!.length - 1),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
groupName = comic.chapters!.groups.elementAt(group - 1);
|
groupName = comic.chapters!.groups.elementAt(
|
||||||
|
group - 1,
|
||||||
|
);
|
||||||
epName = comic.chapters!
|
epName = comic.chapters!
|
||||||
.getGroupByIndex(group - 1)
|
.getGroupByIndex(group - 1)
|
||||||
.values
|
.values
|
||||||
.elementAt(ep - 1);
|
.elementAt(ep - 1);
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch(e) {
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
text = groupName == null
|
text = groupName == null
|
||||||
@@ -453,9 +489,7 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
return SliverLazyToBoxAdapter(
|
return SliverLazyToBoxAdapter(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(title: Text("Description".tl)),
|
||||||
title: Text("Description".tl),
|
|
||||||
),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: SelectableText(comic.description!).fixWidth(double.infinity),
|
child: SelectableText(comic.description!).fixWidth(double.infinity),
|
||||||
@@ -539,10 +573,7 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: color, borderRadius: borderRadius),
|
||||||
color: color,
|
|
||||||
borderRadius: borderRadius,
|
|
||||||
),
|
|
||||||
child: Text(text).padding(padding),
|
child: Text(text).padding(padding),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -552,13 +583,13 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
if (int.tryParse(time) != null) {
|
if (int.tryParse(time) != null) {
|
||||||
var t = int.tryParse(time);
|
var t = int.tryParse(time);
|
||||||
if (t! > 1000000000000) {
|
if (t! > 1000000000000) {
|
||||||
return DateTime.fromMillisecondsSinceEpoch(t)
|
return DateTime.fromMillisecondsSinceEpoch(
|
||||||
.toString()
|
t,
|
||||||
.substring(0, 19);
|
).toString().substring(0, 19);
|
||||||
} else {
|
} else {
|
||||||
return DateTime.fromMillisecondsSinceEpoch(t * 1000)
|
return DateTime.fromMillisecondsSinceEpoch(
|
||||||
.toString()
|
t * 1000,
|
||||||
.substring(0, 19);
|
).toString().substring(0, 19);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (time.contains('T') || time.contains('Z')) {
|
if (time.contains('T') || time.contains('Z')) {
|
||||||
@@ -583,17 +614,11 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(title: Text("Information".tl)),
|
||||||
title: Text("Information".tl),
|
|
||||||
),
|
|
||||||
if (comic.stars != null)
|
if (comic.stars != null)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
StarRating(
|
StarRating(value: comic.stars!, size: 24, onTap: starRating),
|
||||||
value: comic.stars!,
|
|
||||||
size: 24,
|
|
||||||
onTap: starRating,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(comic.stars!.toStringAsFixed(2)),
|
Text(comic.stars!.toStringAsFixed(2)),
|
||||||
],
|
],
|
||||||
@@ -671,24 +696,19 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
|||||||
if (comic.recommend == null || comic.recommend!.isEmpty) {
|
if (comic.recommend == null || comic.recommend!.isEmpty) {
|
||||||
return const SliverPadding(padding: EdgeInsets.zero);
|
return const SliverPadding(padding: EdgeInsets.zero);
|
||||||
}
|
}
|
||||||
return SliverMainAxisGroup(slivers: [
|
return SliverMainAxisGroup(
|
||||||
SliverToBoxAdapter(
|
slivers: [
|
||||||
child: ListTile(
|
SliverToBoxAdapter(child: ListTile(title: Text("Related".tl))),
|
||||||
title: Text("Related".tl),
|
SliverGridComics(comics: comic.recommend!),
|
||||||
),
|
],
|
||||||
),
|
);
|
||||||
SliverGridComics(comics: comic.recommend!),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildComments() {
|
Widget buildComments() {
|
||||||
if (comic.comments == null || comic.comments!.isEmpty) {
|
if (comic.comments == null || comic.comments!.isEmpty) {
|
||||||
return const SliverPadding(padding: EdgeInsets.zero);
|
return const SliverPadding(padding: EdgeInsets.zero);
|
||||||
}
|
}
|
||||||
return _CommentsPart(
|
return _CommentsPart(comments: comic.comments!, showMore: showComments);
|
||||||
comments: comic.comments!,
|
|
||||||
showMore: showComments,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -792,20 +812,21 @@ class _SelectDownloadChapterState extends State<_SelectDownloadChapter> {
|
|||||||
itemCount: widget.eps.length,
|
itemCount: widget.eps.length,
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
title: Text(widget.eps[i]),
|
title: Text(widget.eps[i]),
|
||||||
value: selected.contains(i) ||
|
value:
|
||||||
widget.downloadedEps.contains(i),
|
selected.contains(i) || widget.downloadedEps.contains(i),
|
||||||
onChanged: widget.downloadedEps.contains(i)
|
onChanged: widget.downloadedEps.contains(i)
|
||||||
? null
|
? null
|
||||||
: (v) {
|
: (v) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selected.contains(i)) {
|
if (selected.contains(i)) {
|
||||||
selected.remove(i);
|
selected.remove(i);
|
||||||
} else {
|
} else {
|
||||||
selected.add(i);
|
selected.add(i);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -813,9 +834,7 @@ class _SelectDownloadChapterState extends State<_SelectDownloadChapter> {
|
|||||||
height: 50,
|
height: 50,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
top: BorderSide(
|
top: BorderSide(color: context.colorScheme.outlineVariant),
|
||||||
color: context.colorScheme.outlineVariant,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -880,8 +899,12 @@ class _ComicPageLoadingPlaceHolder extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget buildContainer(double? width, double? height,
|
Widget buildContainer(
|
||||||
{Color? color, double? radius}) {
|
double? width,
|
||||||
|
double? height, {
|
||||||
|
Color? color,
|
||||||
|
double? radius,
|
||||||
|
}) {
|
||||||
return Container(
|
return Container(
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
@@ -923,13 +946,9 @@ class _ComicPageLoadingPlaceHolder extends StatelessWidget {
|
|||||||
if (context.width < changePoint)
|
if (context.width < changePoint)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: buildContainer(null, 36, radius: 18)),
|
||||||
child: buildContainer(null, 36, radius: 18),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(child: buildContainer(null, 36, radius: 18)),
|
||||||
child: buildContainer(null, 36, radius: 18),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
).paddingHorizontal(16),
|
).paddingHorizontal(16),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
@@ -938,7 +957,7 @@ class _ComicPageLoadingPlaceHolder extends StatelessWidget {
|
|||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 2.4,
|
strokeWidth: 2.4,
|
||||||
).fixHeight(24).fixWidth(24),
|
).fixHeight(24).fixWidth(24),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -948,11 +967,7 @@ class _ComicPageLoadingPlaceHolder extends StatelessWidget {
|
|||||||
Widget child;
|
Widget child;
|
||||||
if (cover != null) {
|
if (cover != null) {
|
||||||
child = AnimatedImage(
|
child = AnimatedImage(
|
||||||
image: CachedImageProvider(
|
image: CachedImageProvider(cover!, sourceKey: sourceKey, cid: cid),
|
||||||
cover!,
|
|
||||||
sourceKey: sourceKey,
|
|
||||||
cid: cid,
|
|
||||||
),
|
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: double.infinity,
|
height: double.infinity,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
@@ -512,6 +512,18 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (selectedComics.length == 1)
|
||||||
|
MenuEntry(
|
||||||
|
icon: Icons.chrome_reader_mode_outlined,
|
||||||
|
text: "Read".tl,
|
||||||
|
onClick: () {
|
||||||
|
final c = selectedComics.keys.first as FavoriteItem;
|
||||||
|
App.rootContext.to(() => ReaderWithLoading(
|
||||||
|
id: c.id,
|
||||||
|
sourceKey: c.sourceKey,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user