Files
2026-09-15 15:44:13 +07:00

211 lines
6.2 KiB
Dart

import 'package:hgdj/hj_model/list_base_model.dart';
import 'dart:async';
import 'package:get/get.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/hj_page/live/live_service.dart';
import 'package:hgdj/hj_utils/date_time_util.dart';
import 'package:hgdj/tools_base/event_bus/event_bus_util.dart';
import 'package:hgdj/tools_base/event_bus/events.dart';
import 'package:hgdj/tools_base/toast.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:video_player/video_player.dart';
import 'package:hgdj/hj_utils/video_view_type.dart';
import '../../alert/video/share_media_dialog.dart';
import '../mine/mine_vip/mine_charge_vip_page.dart';
import 'live_model.dart';
//直播详情
class LiveDetailLogic extends GetxController {
LiveAnchor? anchor; //直播
int currentPage = 1;
bool loading = true; //是否在加载推荐列表
bool loadingUserInfo = true; //加载用户会员信息等
List<LiveAnchor> recommendList = []; //
RefreshController? controller; //由 pullYsRefresh 的 onInit 注入,组件负责释放
VideoPlayerController? playerController;
bool initedVideoController = false; //视频控制器是否加载
RxBool isLoading = true.obs; //是否在切换视频
//视频真实比例, 竖屏的比例,采用最大高度400,横屏的比例,保持原有比例
//是否是竖向视频
double? aspectRatio = 16 / 9; //0.75
bool get isVerticalVideo => (aspectRatio ?? 1) > 1;
bool isDispose = false;
//判断播放权限
bool get canWatchLive =>
DateTimeUtil.isExpireDate(globalStore.meInfo?.broadcastExpire);
LiveDetailLogic({this.anchor});
StreamSubscription? _pauseVideoSub;
@override
void onInit() {
super.onInit();
// 耳机/蓝牙断开、来电中断时暂停,防止外放泄露
_pauseVideoSub =
eventBus.on<PauseVideoEvent>((_) => playerController?.pause());
}
@override
void onReady() async {
super.onReady();
Future.wait([globalStore.updateUserInfo(), loadData(initVideo: false)])
.then(
(value) {
update(); //接口调用成功刷新一次直播状态
loadingUserInfo = false;
initPlayer();
},
);
loadrecommendAnchors();
}
@override
void onClose() async {
isDispose = true;
_pauseVideoSub?.cancel();
playerDispose();
super.onClose();
}
playerDispose() {
if (playerController != null) {
initedVideoController = false;
playerController?.removeListener(_listenerCallback);
playerController?.pause();
playerController?.dispose();
playerController = null;
}
}
initPlayer({bool isRetry = false}) async {
if (anchor?.url != null && anchor?.url?.isNotEmpty == true) {
playerController = PlayerFactory.network(anchor?.url);
try {
await playerController?.initialize();
if (isRetry)
confirmPlatformView(); // 仅重试成功(同视频 textureView 挂、platformView 放出)才落本地
playerController?.addListener(_listenerCallback);
if (isDispose) {
playerController?.pause();
playerController?.dispose();
return;
}
initedVideoController = true;
aspectRatio = playerController?.value.aspectRatio ?? 16 / 9;
update();
if (canWatchLive) playerController?.play();
} catch (e) {
playerController?.dispose();
// 首次芯片解码/渲染报错:仅内存切 platformView 重试,成功后才落本地
if (isDecoderError(e) && switchToPlatformView()) {
initPlayer(isRetry: true);
return;
}
//播放器初始化失败,强制设置为离线
anchor?.isOnline = false;
update(['player']);
}
} else {
anchor?.isOnline = false;
update();
}
}
//添加监听
_listenerCallback() {
isLoading.value = playerController?.value.isBuffering == true;
}
//获取直播详情
Future loadData({bool initVideo = true}) async {
LiveAnchor? result =
await LiveService.getLiveAnchorDetail(id: anchor?.id ?? '');
controller?.refreshCompleted();
if (result != null) {
//不需要赋值图片url,因为图片随时在变,防止图片闪动
anchor?.isOnline = result.isOnline;
anchor?.url = result.url;
anchor?.viewCount = result.viewCount;
if (initVideo) initPlayer();
} else {
anchor?.isOnline = false;
}
}
//直播推荐列表
loadrecommendAnchors({int pageNum = 1}) async {
ListBaseModel<LiveAnchor>? liveMainModels =
await LiveService.getLiveAnchorRecom(
country: anchor?.country ?? '',
pageNumber: pageNum,
pageSize: 20,
);
loading = false;
if (liveMainModels != null) {
currentPage = pageNum;
if (currentPage == 1) recommendList.clear();
if (liveMainModels.list != null &&
liveMainModels.list?.isNotEmpty == true) {
recommendList.addAll(liveMainModels.list ?? []);
}
}
controller?.refreshCompleted();
update(['recommend']);
liveMainModels?.hasNext == true
? controller?.loadComplete()
: controller?.loadNoData();
}
loadMoreData() => loadrecommendAnchors(pageNum: currentPage + 1);
//切换直播
onChangeLiveAction(LiveAnchor change) {
if (change.id == anchor?.id) {
showToast('当前在此直播间哦~');
return;
}
anchor = change;
if (playerController != null) {
final old = playerController;
old?.pause();
isLoading.value = true;
playerController?.removeListener(_listenerCallback);
}
initedVideoController = false;
if (anchor?.vidWidth != 0 && anchor?.vidHeight != 0) {
aspectRatio = (anchor?.vidWidth ?? 1) / (anchor?.vidHeight ?? 1);
} else {
aspectRatio = 16 / 9;
}
update();
loadData();
}
//跳转充值
onChargeAction() async {
Get.to(MineChargeVipPage(), preventDuplicates: false);
await globalStore.updateUserInfo();
//true表示支付成功
if (canWatchLive) update();
}
//分享
onShareAction() {
VideoModel videoModel = VideoModel()..cover = anchor?.coverImg;
Get.dialog(ShareMediaDialog(videoModel: videoModel, needDecrypt: false),
useSafeArea: false);
}
}