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); } }