211 lines
6.2 KiB
Dart
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);
|
|
}
|
|
}
|