304 lines
9.4 KiB
Dart

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter_kinetra/kt_pages/kt_short_video/state.dart';
import 'package:get/get.dart';
import 'package:video_player/video_player.dart';
import '../../dio_cilent/kt_apis.dart';
import '../../dio_cilent/kt_request.dart';
import '../../kt_model/kt_video_detail_bean.dart';
import '../../kt_utils/kt_device_info_utils.dart';
import '../../kt_widgets/kt_status_widget.dart';
class VideoPlayLogic extends GetxController {
final state = VideoPlayState();
late final PageController pageController;
List<VideoPlayerController?> controllers = [];
int currentIndex = 0;
bool _disposed = false;
@override
void onInit() {
super.onInit();
pageController = PageController(initialPage: currentIndex);
}
@override
void onReady() {
super.onReady();
_disposed = false;
state.shortPlayId = Get.arguments['shortPlayId'];
state.videoId = Get.arguments['videoId'] ?? 0;
state.imageUrl = Get.arguments['imageUrl'] ?? '';
state.activityId = Get.arguments['activityId'];
state.isFromDiscover = Get.arguments['isFromDiscover'] ?? false;
fetchData();
}
@override
void onClose() {
_disposed = true;
clearCacheCtrl();
super.onClose();
}
clearCacheCtrl() {
for (var controller in controllers) {
controller?.pause();
controller?.dispose();
}
controllers.clear();
}
Future<void> fetchData({bool toPage = true}) async {
Map<String, dynamic> params = {
'short_play_id': state.shortPlayId,
"video_id": state.videoId,
};
if (state.activityId != null) {
params['activity_id'] = state.activityId;
}
clearCacheCtrl();
try {
// LottieLoading.show(Get.context!);
ApiResponse res = await KtHttpClient().request(
KtApis.getVideoDetails,
method: HttpMethod.get,
queryParameters: params,
);
if (res.success) {
state.loadStatus = KtLoadStatusType.loadSuccess;
state.video = VideoDetailBean.fromJson(res.data);
if (state.imageUrl == '') {
state.imageUrl = state.video!.shortPlayInfo?.imageUrl ?? '';
}
if (state.videoId == 0) {
state.videoId = state.video?.videoInfo?.shortPlayVideoId ?? 0;
}
state.episodeList = state.video?.episodeList ?? [];
if (toPage) currentIndex = (state.video?.videoInfo?.episode ?? 1) - 1;
// for (var video in state.episodeList) {
// if (video.isLock == true) {
// state.curUnlock = state.episodeList.indexOf(video);
// break;
// }
// }
// reportHistory();
controllers = List<VideoPlayerController?>.filled(
state.episodeList.length,
null,
growable: true,
);
// await _initializeController(currentIndex);
// _preloadAdjacentVideos();
// if(currentIndex != 0){
if (toPage) {
onPageChanged(
currentIndex,
isToggle: true,
isUploadHistorySeconds: false,
);
} else {
_initializeController(currentIndex);
}
// }
update();
} else {
state.loadStatus = KtLoadStatusType.loadFailed;
update();
}
// if (userLogic.state.userInfo.isVip == true) state.curUnlock = 9999;
update();
} catch (e) {
// LottieLoading.close();
state.loadStatus = KtLoadStatusType.loadFailed;
update();
}
}
void reportHistory() {
if (currentIndex < 0 || currentIndex >= state.episodeList.length) return;
Map<String, dynamic> params = {
"short_play_id": state.shortPlayId,
"video_id": state.episodeList[currentIndex].id,
};
KtHttpClient().request(KtApis.createHistory, data: params);
}
void reportActivity() {
Map<String, dynamic> params = {
'short_play_id': state.shortPlayId,
"short_play_video_id": state.episodeList[currentIndex].shortPlayVideoId,
"activity_id": state.activityId,
};
KtHttpClient().request(KtApis.activeAfterWatchingVideo, data: params);
}
// 切换剧集时处理视频状态
Future<void> onPageChanged(
int index, {
bool isToggle = false,
bool isUploadHistorySeconds = true,
int type = 0,
}) async {
// EasyThrottle.throttle('page-change', Duration(seconds: 3), () async {
debugPrint('--$type-to-index:$index');
if (index < 0 || index >= state.episodeList.length) return;
// 暂停当前视频
if (controllers[currentIndex]?.value.isPlaying ?? false) {
await controllers[currentIndex]?.pause();
// if (isUploadHistorySeconds) uploadHistorySeconds(controllers[currentIndex]?.value.position.inMilliseconds ?? 0);
}
if (controllers[currentIndex]?.value.isCompleted ?? false) {
// if (isUploadHistorySeconds) uploadHistorySeconds(0);
if (state.activityId != null) reportActivity();
}
if (isToggle) {
// loadStatusType = LoadStatusType.loading;
update();
await _initializeController(index);
// loadStatusType = LoadStatusType.loadSuccess;
update();
WidgetsBinding.instance.addPostFrameCallback((_) {
pageController.jumpToPage(index);
});
}
currentIndex = index;
// if (state.episodeList[index].isLock == true) {
// controllers[index]?.seekTo(Duration(seconds: 0));
// controllers[index]?.pause();
// update();
// // showUnlockDialog();
// //
// return;
// }
if (controllers[index] != null) {
// if (state.curUnlock > index || userLogic.state.userInfo.isVip == true) {
controllers[index]?.play();
// }
} else {
if (!isToggle) await _initializeController(index);
// if (state.curUnlock > index || userLogic.state.userInfo.isVip == true) {
controllers[index]?.play();
// }
}
controllers[index]?.setPlaybackSpeed(state.currentSpeed);
// updateHomeVideo();
// print('----curIndex:$currentIndex');
// 预加载新的相邻视频,并释放多余控制器
_preloadAdjacentVideos();
update();
reportHistory();
// });
}
// 释放非当前、前后的视频控制器,减少内存占用
void _releaseUnusedControllers() {
for (int i = 0; i < controllers.length; i++) {
if (i < currentIndex - 1 || i > currentIndex + 1) {
controllers[i]?.dispose();
controllers[i] = null;
}
}
}
// 初始化视频控制器
Future<void> _initializeController(int index) async {
if (index < 0 || index >= state.episodeList.length) return;
if (controllers[index] != null) return;
final episode = state.episodeList[index];
VideoPlayerController controller =
Platform.isAndroid && KtDeviceInfoUtil().osVersion == '10'
? VideoPlayerController.networkUrl(
Uri.parse(episode.videoUrl!),
formatHint: VideoFormat.hls,
viewType: VideoViewType.platformView,
)
: VideoPlayerController.networkUrl(
Uri.parse(episode.videoUrl!),
formatHint: VideoFormat.hls,
);
controllers[index] = controller;
try {
await controller.initialize();
// if (index == currentIndex && (episode.isLock == false || userLogic.state.userInfo.isVip == true)) {
if (index == currentIndex) {
controller.play();
update();
}
controller.setPlaybackSpeed(state.currentSpeed);
debugPrint('---seekTo:${episode.playSeconds}');
controller.addListener(() {
if (currentIndex == index && !_disposed) update();
if (currentIndex == state.episodeList.length - 1 &&
(controllers.last?.value.isCompleted ?? false)) {
// showRecommendDialog();
}
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 (currentIndex > 0) _initializeController(currentIndex - 1);
if (currentIndex < state.episodeList.length - 1) {
_initializeController(currentIndex + 1);
}
_releaseUnusedControllers();
}
Future<void> likeVideo() async {
if (state.video == null) return;
Map<String, dynamic> params = {
"short_play_id": state.video?.shortPlayInfo?.shortPlayId,
"video_id": state.episodeList[currentIndex].id,
};
if (state.video?.shortPlayInfo?.isCollect ?? false) {
await KtHttpClient().request(KtApis.deleteFavoriteVideo, data: params);
} else {
await KtHttpClient().request(KtApis.collectVideo, data: params);
}
state.video?.shortPlayInfo?.isCollect =
!(state.video?.shortPlayInfo?.isCollect ?? false);
// update(['video-like']);
// if (state.isFromDiscover) {
// try {
// final discoverLogic = Get.put(DiscoverLogic());
// discoverLogic.setCollectVideo(
// state.video!.shortPlayInfo.shortPlayId!,
// isCollect: state.video!.shortPlayInfo.isCollect!,
// );
// } catch (e) {
// debugPrint('---err:$e');
// }
// }
update();
}
}