Skip to content

Commit 7744157

Browse files
committed
gallery url
1 parent 5dcae5e commit 7744157

30 files changed

+169
-130
lines changed

lib/src/exception/eh_parse_exception.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ class EHParseException implements Exception {
1111
}
1212
}
1313

14-
enum EHParseExceptionType { exceedLimit, unsupportedImagePageStyle, tagSetExceedLimit }
14+
enum EHParseExceptionType { exceedLimit, unsupportedImagePageStyle, tagSetExceedLimit, getMetaDataFailed }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class InternalException implements Exception {
2+
final String message;
3+
4+
InternalException({required this.message});
5+
}

lib/src/model/gallery.dart

+8-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:collection';
33
import 'package:jhentai/src/database/database.dart';
44
import 'package:jhentai/src/model/gallery_image.dart';
55
import 'package:jhentai/src/model/gallery_tag.dart';
6+
import 'package:jhentai/src/model/gallery_url.dart';
67

78
import '../service/archive_download_service.dart';
89
import '../service/gallery_download_service.dart';
@@ -19,7 +20,7 @@ class Gallery {
1920
bool isFavorite;
2021
int? favoriteTagIndex;
2122
String? favoriteTagName;
22-
String galleryUrl;
23+
GalleryUrl galleryUrl;
2324
LinkedHashMap<String, List<GalleryTag>> tags;
2425
String? language;
2526
String? uploader;
@@ -35,7 +36,7 @@ class Gallery {
3536
title: title,
3637
category: category,
3738
pageCount: pageCount!,
38-
galleryUrl: galleryUrl,
39+
galleryUrl: galleryUrl.url,
3940
uploader: uploader,
4041
publishTime: publishTime,
4142
downloadStatusIndex: DownloadStatus.downloading.index,
@@ -59,7 +60,7 @@ class Gallery {
5960
title: title,
6061
category: category,
6162
pageCount: pageCount!,
62-
galleryUrl: galleryUrl,
63+
galleryUrl: galleryUrl.url,
6364
uploader: uploader,
6465
size: size,
6566
coverUrl: cover.url,
@@ -107,7 +108,7 @@ class Gallery {
107108
'isFavorite': isFavorite,
108109
'favoriteTagIndex': favoriteTagIndex,
109110
'favoriteTagName': favoriteTagName,
110-
'galleryUrl': galleryUrl,
111+
'galleryUrl': galleryUrl.url,
111112
'tags': tags,
112113
'language': language,
113114
'uploader': uploader,
@@ -130,7 +131,7 @@ class Gallery {
130131
isFavorite: map['isFavorite'],
131132
favoriteTagIndex: map['favoriteTagIndex'],
132133
favoriteTagName: map['favoriteTagName'],
133-
galleryUrl: map['galleryUrl'],
134+
galleryUrl: GalleryUrl.parse(map['galleryUrl']) ,
134135
tags: LinkedHashMap.of(
135136
(map['tags'] as Map).map(
136137
(key, value) => MapEntry(
@@ -149,7 +150,7 @@ class Gallery {
149150

150151
@override
151152
String toString() {
152-
return 'Gallery{gid: $gid, token: $token, title: $title, category: $category, cover: $cover, pageCount: $pageCount, rating: $rating, hasRated: $hasRated, isFavorite: $isFavorite, favoriteTagIndex: $favoriteTagIndex, favoriteTagName: $favoriteTagName, galleryUrl: $galleryUrl, tags: $tags, language: $language, uploader: $uploader, publishTime: $publishTime, isExpunged: $isExpunged, isFilteredByLocalTag: $hasLocalFilteredTag}';
153+
return 'Gallery{gid: $gid, token: $token, title: $title, category: $category, cover: $cover, pageCount: $pageCount, rating: $rating, hasRated: $hasRated, isFavorite: $isFavorite, favoriteTagIndex: $favoriteTagIndex, favoriteTagName: $favoriteTagName, galleryUrl: ${galleryUrl.url}, tags: $tags, language: $language, uploader: $uploader, publishTime: $publishTime, isExpunged: $isExpunged, isFilteredByLocalTag: $hasLocalFilteredTag}';
153154
}
154155

155156
Gallery copyWith({
@@ -164,7 +165,7 @@ class Gallery {
164165
bool? isFavorite,
165166
int? favoriteTagIndex,
166167
String? favoriteTagName,
167-
String? galleryUrl,
168+
GalleryUrl? galleryUrl,
168169
LinkedHashMap<String, List<GalleryTag>>? tags,
169170
String? language,
170171
String? uploader,

lib/src/model/gallery_detail.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class GalleryDetail {
2626
List<GalleryThumbnail> thumbnails;
2727
int thumbnailsPageCount;
2828

29-
String? get newVersionGalleryUrl => childrenGallerys?.lastOrNull?.galleryUrl.url;
29+
GalleryUrl? get newVersionGalleryUrl => childrenGallerys?.lastOrNull?.galleryUrl;
3030

3131
GalleryDetail({
3232
required this.rawTitle,

lib/src/model/gallery_url.dart

+28
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'package:jhentai/src/exception/internal_exception.dart';
2+
13
class GalleryUrl {
24
final bool isEH;
35

@@ -21,5 +23,31 @@ class GalleryUrl {
2123
);
2224
}
2325

26+
static GalleryUrl parse(String url) {
27+
RegExp regExp = RegExp(r'https://e([-x])hentai\.org/g/(\d+)/([a-z0-9]{10})');
28+
Match? match = regExp.firstMatch(url);
29+
if (match == null) {
30+
throw InternalException(message: 'Parse gallery url failed, url:$url');
31+
}
32+
33+
return GalleryUrl(
34+
isEH: match.group(1) == '-',
35+
gid: int.parse(match.group(2)!),
36+
token: match.group(3)!,
37+
);
38+
}
39+
2440
String get url => isEH ? 'https://e-hentai.org/g/$gid/$token/' : 'https://exhentai.org/g/$gid/$token/';
41+
42+
GalleryUrl copyWith({
43+
bool? isEH,
44+
int? gid,
45+
String? token,
46+
}) {
47+
return GalleryUrl(
48+
isEH: isEH ?? this.isEH,
49+
gid: gid ?? this.gid,
50+
token: token ?? this.token,
51+
);
52+
}
2553
}

lib/src/network/eh_request.dart

+4-3
Original file line numberDiff line numberDiff line change
@@ -331,15 +331,16 @@ emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
331331
bool useCacheIfAvailable = true,
332332
required EHHtmlParser<T> parser,
333333
}) async {
334-
Response response = await _getWithErrorHandler(
334+
Response response = await _postWithErrorHandler(
335335
EHConsts.EHApi,
336-
queryParameters: {
336+
options: Options(contentType: Headers.jsonContentType),
337+
data: {
337338
'method': 'gdata',
338339
'gidlist': [
339340
[gid, token]
340341
],
342+
"namespace": 1,
341343
},
342-
options: useCacheIfAvailable ? CacheOptions.cacheOptions.toOptions() : CacheOptions.noCacheOptions.toOptions(),
343344
);
344345
return _parseResponse(response, parser);
345346
}

lib/src/pages/base/base_page_logic.dart

-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,6 @@ abstract class BasePageLogic extends GetxController with Scroll2TopLogicMixin {
340340
toRoute(
341341
Routes.details,
342342
arguments: {
343-
'gid': gallery.gid,
344343
'galleryUrl': gallery.galleryUrl,
345344
'gallery': gallery,
346345
},

lib/src/pages/details/comment/comment_page.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class _CommentPageState extends State<CommentPage> with LoginRequiredMixin {
7777
}
7878

7979
List<GalleryComment> newComments = await EHRequest.requestDetailPage(
80-
galleryUrl: DetailsPageLogic.current!.state.gallery!.galleryUrl,
80+
galleryUrl: DetailsPageLogic.current!.state.gallery!.galleryUrl.url,
8181
parser: EHSpiderParser.detailPage2Comments,
8282
useCacheIfAvailable: false,
8383
);
@@ -113,7 +113,7 @@ class _CommentPageState extends State<CommentPage> with LoginRequiredMixin {
113113
}
114114

115115
List<GalleryComment> newComments = await EHRequest.requestDetailPage(
116-
galleryUrl: DetailsPageLogic.current!.state.gallery!.galleryUrl,
116+
galleryUrl: DetailsPageLogic.current!.state.gallery!.galleryUrl.url,
117117
parser: EHSpiderParser.detailPage2Comments,
118118
useCacheIfAvailable: false,
119119
);

lib/src/pages/details/comment/eh_comment.dart

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ import 'package:flutter/material.dart';
66
import 'package:html/dom.dart' as dom;
77
import 'package:get/get.dart';
88
import 'package:jhentai/src/config/ui_config.dart';
9-
import 'package:jhentai/src/consts/eh_consts.dart';
109
import 'package:jhentai/src/extension/widget_extension.dart';
1110
import 'package:jhentai/src/mixin/login_required_logic_mixin.dart';
11+
import 'package:jhentai/src/model/gallery_url.dart';
1212
import 'package:jhentai/src/pages/details/details_page_logic.dart';
1313
import 'package:jhentai/src/pages/details/details_page_state.dart';
1414
import 'package:jhentai/src/routes/routes.dart';
15-
import 'package:jhentai/src/utils/convert_util.dart';
1615
import 'package:jhentai/src/utils/eh_spider_parser.dart';
1716
import 'package:jhentai/src/utils/toast_util.dart';
1817
import 'package:jhentai/src/widget/eh_comment_score_details_dialog.dart';
@@ -343,14 +342,15 @@ class _EHCommentTextBody extends StatelessWidget {
343342
return false;
344343
}
345344

346-
return element.children.any((child) => _containsImage(child));
345+
return element.children.any(_containsImage);
347346
}
348347

349348
Future<bool> _handleTapUrl(String url) async {
350-
if (url.startsWith(EHConsts.EHIndex + '/g') || url.startsWith(EHConsts.EXIndex + '/g')) {
349+
GalleryUrl? galleryUrl = GalleryUrl.tryParse(url);
350+
if (galleryUrl != null) {
351351
toRoute(
352352
Routes.details,
353-
arguments: {'gid': parseGalleryUrl2Gid(url), 'galleryUrl': url},
353+
arguments: {'galleryUrl': galleryUrl},
354354
offAllBefore: false,
355355
);
356356
return true;

lib/src/pages/details/details_page.dart

+5-8
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ class DetailsPage extends StatelessWidget with Scroll2TopPageMixin {
105105
}
106106

107107
return GetBuilder<ArchiveDownloadService>(
108-
id: '${ArchiveDownloadService.archiveStatusId}::${state.gid}',
108+
id: '${ArchiveDownloadService.archiveStatusId}::${state.galleryUrl.gid}',
109109
builder: (_) => GetBuilder<GalleryDownloadService>(
110-
id: '${Get.find<GalleryDownloadService>().galleryDownloadProgressId}::${state.gid}',
110+
id: '${Get.find<GalleryDownloadService>().galleryDownloadProgressId}::${state.galleryUrl.gid}',
111111
builder: (_) {
112-
GalleryDownloadProgress? downloadProgress = logic.galleryDownloadService.galleryDownloadInfos[state.gid]?.downloadProgress;
113-
ArchiveStatus? archiveStatus = Get.find<ArchiveDownloadService>().archiveDownloadInfos[state.gid]?.archiveStatus;
112+
GalleryDownloadProgress? downloadProgress = logic.galleryDownloadService.galleryDownloadInfos[state.galleryUrl.gid]?.downloadProgress;
113+
ArchiveStatus? archiveStatus = Get.find<ArchiveDownloadService>().archiveDownloadInfos[state.galleryUrl.gid]?.archiveStatus;
114114

115115
return PopupMenuButton(
116116
itemBuilder: (context) {
@@ -753,10 +753,7 @@ class DetailsPage extends StatelessWidget with Scroll2TopPageMixin {
753753
child: Text('thisGalleryHasANewVersion'.tr),
754754
onPressed: () => toRoute(
755755
Routes.details,
756-
arguments: {
757-
'gid': parseGalleryUrl2Gid(state.galleryDetails!.newVersionGalleryUrl!),
758-
'galleryUrl': state.galleryDetails!.newVersionGalleryUrl!
759-
},
756+
arguments: {'galleryUrl': state.galleryDetails!.newVersionGalleryUrl!},
760757
offAllBefore: false,
761758
preventDuplicates: false,
762759
),

lib/src/pages/details/details_page_logic.dart

+24-19
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,14 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
103103

104104
@override
105105
void onInit() {
106+
super.onInit();
107+
106108
if (Get.arguments is! Map) {
107109
return;
108110
}
109111

110-
state.gid = Get.arguments['gid'];
111112
state.galleryUrl = Get.arguments['galleryUrl'];
112113
state.gallery = Get.arguments['gallery'];
113-
114-
super.onInit();
115114
}
116115

117116
@override
@@ -156,6 +155,10 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
156155
if (enableLoadingState) {
157156
updateSafely([loadingStateId]);
158157
}
158+
159+
if (e.type == EHSiteExceptionType.galleryDeleted) {
160+
await _handleGalleryDeleted();
161+
}
159162
return;
160163
} on Error catch (e) {
161164
Log.error('Get Gallery Detail Failed', e, e.stackTrace);
@@ -183,6 +186,8 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
183186
SchedulerBinding.instance.scheduleTask(() => historyService.record(state.gallery), Priority.animation);
184187
}
185188

189+
Future<void> _handleGalleryDeleted() async {}
190+
186191
Future<void> loadMoreThumbnails() async {
187192
if (state.loadingThumbnailsState == LoadingState.loading) {
188193
return;
@@ -201,7 +206,7 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
201206
List<GalleryThumbnail> newThumbNails;
202207
try {
203208
newThumbNails = await EHRequest.requestDetailPage(
204-
galleryUrl: state.galleryUrl,
209+
galleryUrl: state.galleryUrl.url,
205210
thumbnailsPageIndex: state.nextPageIndexToLoadThumbnails,
206211
parser: EHSpiderParser.detailPage2Thumbnails,
207212
);
@@ -587,13 +592,13 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
587592
Log.info('Share gallery:${state.galleryUrl}');
588593

589594
if (GetPlatform.isDesktop) {
590-
await FlutterClipboard.copy(state.galleryUrl);
595+
await FlutterClipboard.copy(state.galleryUrl.url);
591596
toast('hasCopiedToClipboard'.tr);
592597
return;
593598
}
594599

595600
Share.share(
596-
state.galleryUrl,
601+
state.galleryUrl.url,
597602
sharePositionOrigin: Rect.fromLTWH(0, 0, fullScreenWidth, screenHeight * 2 / 3),
598603
);
599604
}
@@ -678,7 +683,7 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
678683
gid: state.gallery!.gid,
679684
token: state.gallery!.token,
680685
galleryTitle: state.gallery!.title,
681-
galleryUrl: state.galleryUrl,
686+
galleryUrl: state.galleryUrl.url,
682687
initialIndex: forceIndex ?? readIndexRecord,
683688
currentImageIndex: forceIndex ?? readIndexRecord,
684689
readProgressRecordStorageKey: storageKey,
@@ -703,7 +708,7 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
703708
gid: state.gallery!.gid,
704709
token: state.gallery!.token,
705710
galleryTitle: state.gallery!.title,
706-
galleryUrl: state.galleryUrl,
711+
galleryUrl: state.galleryUrl.url,
707712
initialIndex: forceIndex ?? readIndexRecord,
708713
currentImageIndex: forceIndex ?? readIndexRecord,
709714
readProgressRecordStorageKey: storageKey,
@@ -726,17 +731,17 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
726731

727732
/// 1. if redirect is enabled, try EH site first for EX link
728733
/// 2. if a gallery can't be found in EH site, it may be moved into EX site
729-
if (state.galleryUrl.contains(EHConsts.EXIndex)) {
734+
if (state.galleryUrl.url.contains(EHConsts.EXIndex)) {
730735
if (EHSetting.redirect2Eh.isTrue && !_galleryOnlyInExSite()) {
731-
firstLink = state.galleryUrl.replaceFirst(EHConsts.EXIndex, EHConsts.EHIndex);
732-
secondLink = state.galleryUrl;
736+
firstLink = state.galleryUrl.url.replaceFirst(EHConsts.EXIndex, EHConsts.EHIndex);
737+
secondLink = state.galleryUrl.url;
733738
} else {
734739
firstLink = null;
735-
secondLink = state.galleryUrl;
740+
secondLink = state.galleryUrl.url;
736741
}
737742
} else {
738-
firstLink = state.galleryUrl;
739-
secondLink = state.galleryUrl.replaceFirst(EHConsts.EHIndex, EHConsts.EXIndex);
743+
firstLink = state.galleryUrl.url;
744+
secondLink = state.galleryUrl.url.replaceFirst(EHConsts.EHIndex, EHConsts.EXIndex);
740745
}
741746

742747
/// if we can't find gallery via firstLink, try second link
@@ -749,10 +754,10 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
749754
parser: EHSpiderParser.detailPage2GalleryAndDetailAndApikey,
750755
useCacheIfAvailable: useCache,
751756
);
752-
state.gallery?.galleryUrl = state.galleryUrl = firstLink;
757+
state.gallery?.galleryUrl = state.galleryUrl = state.galleryUrl.copyWith(isEH: true);
753758
return galleryAndDetailAndApikey;
754759
} on EHSiteException catch (e) {
755-
Log.verbose('Can\'t find gallery, firstLink: $firstLink');
760+
Log.verbose('Can\'t find gallery, firstLink: $firstLink, reason: ${e.message}');
756761
firstException = e;
757762
}
758763
}
@@ -764,10 +769,10 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
764769
parser: EHSpiderParser.detailPage2GalleryAndDetailAndApikey,
765770
useCacheIfAvailable: useCache,
766771
);
767-
state.gallery?.galleryUrl = state.galleryUrl = secondLink;
772+
state.gallery?.galleryUrl = state.galleryUrl = state.galleryUrl.copyWith(isEH: false);
768773
return galleryAndDetailAndApikey;
769774
} on EHSiteException catch (e) {
770-
Log.verbose('Can\'t find gallery, secondLink: $secondLink');
775+
Log.verbose('Can\'t find gallery, secondLink: $secondLink, reason: ${e.message}');
771776
throw firstException ?? e;
772777
}
773778
}
@@ -854,6 +859,6 @@ class DetailsPageLogic extends GetxController with LoginRequiredMixin, Scroll2To
854859
}
855860

856861
void _removeCache() {
857-
EHRequest.removeCacheByGalleryUrlAndPage(state.galleryUrl, 0);
862+
EHRequest.removeCacheByGalleryUrlAndPage(state.galleryUrl.url, 0);
858863
}
859864
}

lib/src/pages/details/details_page_state.dart

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import 'package:jhentai/src/mixin/scroll_to_top_state_mixin.dart';
22
import 'package:jhentai/src/model/gallery.dart';
33
import 'package:jhentai/src/model/gallery_detail.dart';
4+
import 'package:jhentai/src/model/gallery_url.dart';
45
import 'package:jhentai/src/widget/loading_state_indicator.dart';
56

67
class DetailsPageState with Scroll2TopStateMixin {
78
/// initial param
8-
int? gid;
9+
late GalleryUrl galleryUrl;
910

1011
/// initial param
11-
late String galleryUrl;
12-
13-
/// initial param and may be updated after we get the gallery details
12+
/// may be null if we don't enter detail page from gallery list
13+
/// may be updated after we get the gallery details
1414
Gallery? gallery;
1515

1616
GalleryDetail? galleryDetails;

0 commit comments

Comments
 (0)