241 lines
6.8 KiB
Dart
241 lines
6.8 KiB
Dart
import 'package:flutter_kinetra/kt_pages/kt_explore/state.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:easy_refresh/easy_refresh.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
import '../../dio_cilent/kt_apis.dart';
|
|
import '../../dio_cilent/kt_request.dart';
|
|
import '../../kt_model/kt_short_video_bean.dart';
|
|
import '../../kt_widgets/kt_status_widget.dart';
|
|
|
|
class KtExploreLogic extends GetxController {
|
|
final state = KtExploreState();
|
|
final EasyRefreshController refreshCtrl = EasyRefreshController(
|
|
controlFinishLoad: true,
|
|
);
|
|
final PageController pageController = PageController(viewportFraction: .95);
|
|
final int preloadRange = 1;
|
|
bool isRefresh = false;
|
|
|
|
@override
|
|
void onReady() {
|
|
super.onReady();
|
|
fetchDiscoverList();
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
super.onClose();
|
|
clearController();
|
|
refreshCtrl.dispose();
|
|
pageController.dispose();
|
|
}
|
|
|
|
clearController() {
|
|
for (var item in state.controllers) {
|
|
item?.pause();
|
|
item?.dispose();
|
|
}
|
|
state.controllers.clear();
|
|
}
|
|
|
|
fetchDiscoverList({bool refresh = false}) async {
|
|
state.loadStatus = KtLoadStatusType.loading;
|
|
|
|
if (refresh) {
|
|
isRefresh = true;
|
|
state.curIndex = 1;
|
|
state.videoList.clear();
|
|
clearController();
|
|
}
|
|
|
|
if (refresh) refreshCtrl.finishLoad();
|
|
try {
|
|
ApiResponse res = await KtHttpClient().request(
|
|
KtApis.getRecommands,
|
|
queryParameters: {'current_page': state.curIndex, 'page_size': 20},
|
|
method: HttpMethod.get,
|
|
);
|
|
if (refresh) {
|
|
isRefresh = false;
|
|
update();
|
|
}
|
|
|
|
if (res.success) {
|
|
state.loadStatus = KtLoadStatusType.loadSuccess;
|
|
List<KtShortVideoBean> list = [
|
|
...res.data['list'].map((item) => KtShortVideoBean.fromJson(item)),
|
|
];
|
|
state.videoList.addAll(list);
|
|
// if (videoId == -1) {
|
|
// video = state.videoList.first;
|
|
// videoId = state.videoList.first.id ?? -1;
|
|
// }
|
|
state.controllers = List<VideoPlayerController?>.filled(
|
|
state.videoList.length,
|
|
null,
|
|
growable: true,
|
|
);
|
|
|
|
if (state.videoList.isNotEmpty && state.curIndex == 1) {
|
|
state.currentPage = 0;
|
|
_initializeController(0);
|
|
}
|
|
update();
|
|
} else {
|
|
if (refresh) refreshCtrl.finishRefresh(IndicatorResult.fail);
|
|
state.loadStatus = KtLoadStatusType.loadFailed;
|
|
}
|
|
} catch (e) {
|
|
if (refresh) {
|
|
isRefresh = false;
|
|
update();
|
|
}
|
|
state.loadStatus = KtLoadStatusType.loadFailed;
|
|
}
|
|
update();
|
|
}
|
|
|
|
// 切换剧集时处理视频状态
|
|
Future<void> onPageChanged(int index, {bool isToggle = false}) async {
|
|
if (index < 0 || index >= state.videoList.length) return;
|
|
|
|
// 暂停当前视频
|
|
if (state.controllers[state.currentPage]?.value.isPlaying ?? false) {
|
|
await state.controllers[state.currentPage]?.pause();
|
|
}
|
|
|
|
state.currentPage = index;
|
|
if (isToggle) {
|
|
// loadStatusType = LoadStatusType.loading;
|
|
// update();
|
|
|
|
await _initializeController(index);
|
|
// loadStatusType = LoadStatusType.loadSuccess;
|
|
update();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
pageController.jumpToPage(index);
|
|
});
|
|
}
|
|
if (state.controllers[index] != null) {
|
|
state.controllers[index]?.play();
|
|
} else {
|
|
if (!isToggle) await _initializeController(index);
|
|
state.controllers[index]?.play();
|
|
}
|
|
// 预加载新的相邻视频,并释放多余控制器
|
|
_preloadAdjacentVideos();
|
|
update();
|
|
// });
|
|
}
|
|
|
|
// 释放非当前、前后的视频控制器,减少内存占用
|
|
void _releaseUnusedControllers() {
|
|
for (int i = 0; i < state.controllers.length; i++) {
|
|
if (i < state.currentPage - 1 || i > state.currentPage + 1) {
|
|
state.controllers[i]?.dispose();
|
|
state.controllers[i] = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 初始化视频控制器
|
|
Future<void> _initializeController(int index) async {
|
|
if (index < 0 || index >= state.videoList.length) return;
|
|
if (state.controllers[index] != null) return;
|
|
final episode = state.videoList[index];
|
|
final controller = VideoPlayerController.networkUrl(
|
|
Uri.parse(episode.videoInfo!.videoUrl!),
|
|
formatHint: VideoFormat.hls,
|
|
);
|
|
|
|
state.controllers[index] = controller;
|
|
|
|
try {
|
|
await controller.initialize();
|
|
if (index == state.currentPage) {
|
|
controller.play();
|
|
update();
|
|
}
|
|
controller.addListener(() {
|
|
if (state.currentPage == index) update();
|
|
|
|
if (controller.value.isCompleted && !controller.value.isBuffering) {
|
|
onPageChanged(index + 1, isToggle: true);
|
|
}
|
|
});
|
|
} catch (e) {
|
|
// 可根据需要处理异常
|
|
// UserUtil().reportErrorEvent(
|
|
// 'video initialize failed',
|
|
// UserUtil.videoError,
|
|
// errMsg: e.toString(),
|
|
// payData: episode.toJson(),
|
|
// shortPlayId: episode.shortPlayId ?? 0,
|
|
// shortPlayVideoId: episode.shortPlayVideoId ?? 0,
|
|
// );
|
|
debugPrint('---err:$e');
|
|
}
|
|
}
|
|
|
|
// 预加载相邻视频
|
|
void _preloadAdjacentVideos() {
|
|
if (state.currentPage > 0) _initializeController(state.currentPage - 1);
|
|
if (state.currentPage < state.videoList.length - 1) {
|
|
_initializeController(state.currentPage + 1);
|
|
}
|
|
_releaseUnusedControllers();
|
|
}
|
|
|
|
likeVideo(KtShortVideoBean video) {
|
|
if (video.isCollect ?? false) {
|
|
video.collectTotal = video.collectTotal! - 1;
|
|
if (video.collectTotal! < 0) {
|
|
video.collectTotal = 0;
|
|
}
|
|
KtHttpClient().request(
|
|
KtApis.deleteFavoriteVideo,
|
|
data: {
|
|
"short_play_id": video.shortPlayId,
|
|
"video_id": video.videoInfo!.id,
|
|
},
|
|
);
|
|
} else {
|
|
video.collectTotal = video.collectTotal! + 1;
|
|
KtHttpClient().request(
|
|
KtApis.collectVideo,
|
|
data: {
|
|
"short_play_id": video.shortPlayId,
|
|
"video_id": video.videoInfo!.id,
|
|
},
|
|
);
|
|
}
|
|
video.isCollect = !(video.isCollect ?? false);
|
|
update();
|
|
}
|
|
|
|
KtShortVideoBean get curVideo => state.videoList[state.currentPage];
|
|
|
|
setCollectVideo(int shortPlayId, {bool isCollect = true}) {
|
|
KtShortVideoBean? video = state.videoList.firstWhereOrNull(
|
|
(item) => item.shortPlayId == shortPlayId,
|
|
);
|
|
if (video == null) return;
|
|
video.isCollect = isCollect;
|
|
video.collectTotal = video.collectTotal! + (isCollect ? 1 : -1);
|
|
update();
|
|
}
|
|
|
|
//
|
|
// Future<void> onRefresh() async {
|
|
// state.currentPage = 0;
|
|
// state.curIndex = 1;
|
|
// // clearController();
|
|
// // update();
|
|
// WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
// await fetchDiscoverList(refresh: true);
|
|
// });
|
|
// }
|
|
}
|