132 lines
3.7 KiB
Dart
132 lines
3.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:hgdj/hj_utils/const.dart';
|
|
import 'package:hgdj/tools_base/toast.dart';
|
|
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
|
|
|
import '../../hj_model/cartoon_media_info.dart';
|
|
import '../../hj_utils/api_service/acg_service.dart';
|
|
import '../../hj_utils/history_util.dart';
|
|
import '../../routers/jump_router.dart';
|
|
import 'audio_player_bottomsheet.dart';
|
|
import 'text_novel_read_page.dart';
|
|
import 'voice_novel_read_page.dart';
|
|
import 'widget/acg_source_manager.dart';
|
|
|
|
class NovelDetailLogic extends GetxController {
|
|
String id;
|
|
CartoonMediaInfo? model;
|
|
final recommends = [];
|
|
int page = 1;
|
|
RefreshController? refreshCtr;
|
|
|
|
bool showHeader = true;
|
|
double showOffset = 100;
|
|
|
|
late ACGSourceManager manager;
|
|
late ScrollController scrollCtr = ScrollController()
|
|
..addListener(() {
|
|
if (scrollCtr.offset <= showOffset) {
|
|
if (!showHeader) {
|
|
showHeader = true;
|
|
update(['header']);
|
|
}
|
|
} else {
|
|
if (showHeader) {
|
|
showHeader = false;
|
|
update(['header']);
|
|
}
|
|
}
|
|
});
|
|
NovelDetailLogic(this.id) : manager = ACGSourceManager(id);
|
|
|
|
@override
|
|
void onReady() async {
|
|
super.onReady();
|
|
// 先拿详情(含 freeEpisode),再拉子集,才能正确标记前 N 集免费
|
|
await fetchDetailData();
|
|
update();
|
|
manager.fetchAllEpisodes();
|
|
fetchRecommendData();
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
scrollCtr.dispose(); //修复泄漏
|
|
// manager 由页面的 ChangeNotifierProvider(create:) 在卸载时 dispose,本类不再重复释放
|
|
// refreshCtr 由 CustomRefreshView 创建并 dispose,本类只持引用,绝不能再 dispose
|
|
super.onClose();
|
|
}
|
|
|
|
Future fetchDetailData() async {
|
|
final result = await ACGService.getMediaInfo(id);
|
|
if (result != null) {
|
|
model = result;
|
|
manager.mediaInfo = result;
|
|
HistoryUtil.insert(model!, MediaStyle.Novel);
|
|
} else {
|
|
model = CartoonMediaInfo();
|
|
}
|
|
}
|
|
|
|
// 获取相关推荐
|
|
Future fetchRecommendData() async {
|
|
final result = await ACGService.comicsRecommendList(page, 12,
|
|
tagId: model?.tagDetails?.firstOrNull?.id ?? '', mediaType: 'text');
|
|
if (result != null) {
|
|
page += 1;
|
|
recommends.addAll(result.list ?? []);
|
|
}
|
|
result?.hasNext ?? false
|
|
? refreshCtr?.loadComplete()
|
|
: refreshCtr?.loadNoData();
|
|
update();
|
|
}
|
|
|
|
// 打开所有章节
|
|
episodesBottomSheet() async {
|
|
final result = await Get.bottomSheet(AudioPlayerBottomSheet(
|
|
model?.title ?? '',
|
|
allAudiobooks: manager.allEpisodes,
|
|
currentPlayIndex: manager.index,
|
|
unit: model?.unit,
|
|
hasPermission: model?.hasPermission ?? false,
|
|
));
|
|
if (result != null) {
|
|
gotoPlay(index: result as int);
|
|
}
|
|
}
|
|
|
|
gotoPlay({int index = 0}) async {
|
|
final mediaSubType = model?.mediaSubType ?? -1;
|
|
final opm = await manager
|
|
.getEpisodeHasPermisson(index); //通过时内部已切集,不必再 changeEpisodesIndex
|
|
if (opm != null) {
|
|
//0-默认文本小说 1-有声小说
|
|
if (mediaSubType == 0) {
|
|
Get.to(() => TextNovelReadPage(manager: manager),
|
|
preventDuplicates: false);
|
|
} else if (mediaSubType == 1) {
|
|
Get.to(
|
|
() => VoiceNovelReadPage(
|
|
manager: manager,
|
|
id: id,
|
|
index: index,
|
|
title: model?.title ?? '',
|
|
),
|
|
opaque: false,
|
|
preventDuplicates: false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 跳转
|
|
jumpToOtherPage(CartoonMediaInfo info) {
|
|
if (model?.id == info.id) {
|
|
showToast('您当前正在观看此媒体');
|
|
return;
|
|
}
|
|
pushToCartoonPage(info);
|
|
}
|
|
}
|