Commit 22485f1c authored by Alex朱枝文's avatar Alex朱枝文

直播流程更改

parent 771b73e1
......@@ -37,6 +37,8 @@
04129E862CD0C8490072F87B /* YHAliYunLogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04129E852CD0C8490072F87B /* YHAliYunLogManager.swift */; };
041390692C1081FA0098CB8A /* YHFileListEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041390682C1081FA0098CB8A /* YHFileListEmptyView.swift */; };
0413A9AD2CFB086A00304BC6 /* YHSimpleAudienceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0413A9AC2CFB086A00304BC6 /* YHSimpleAudienceVC.swift */; };
0413A9AF2CFE2C8200304BC6 /* YHMainChannelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0413A9AE2CFE2C8200304BC6 /* YHMainChannelDelegate.swift */; };
0413A9B12CFFDB9A00304BC6 /* YHCategoryDropdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0413A9B02CFFDB9A00304BC6 /* YHCategoryDropdownView.swift */; };
0414708B2C88627B00B7B688 /* YHButlerServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0414708A2C88627B00B7B688 /* YHButlerServiceManager.swift */; };
0414708E2C895A9300B7B688 /* YHButlerServiceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0414708D2C895A9300B7B688 /* YHButlerServiceViewModel.swift */; };
041470922C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041470912C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift */; };
......@@ -1110,6 +1112,8 @@
04129E852CD0C8490072F87B /* YHAliYunLogManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAliYunLogManager.swift; sourceTree = "<group>"; };
041390682C1081FA0098CB8A /* YHFileListEmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHFileListEmptyView.swift; sourceTree = "<group>"; };
0413A9AC2CFB086A00304BC6 /* YHSimpleAudienceVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHSimpleAudienceVC.swift; sourceTree = "<group>"; };
0413A9AE2CFE2C8200304BC6 /* YHMainChannelDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHMainChannelDelegate.swift; sourceTree = "<group>"; };
0413A9B02CFFDB9A00304BC6 /* YHCategoryDropdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHCategoryDropdownView.swift; sourceTree = "<group>"; };
0414708A2C88627B00B7B688 /* YHButlerServiceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHButlerServiceManager.swift; sourceTree = "<group>"; };
0414708D2C895A9300B7B688 /* YHButlerServiceViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHButlerServiceViewModel.swift; sourceTree = "<group>"; };
041470912C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGalaxyManagerTipsItemView.swift; sourceTree = "<group>"; };
......@@ -2977,6 +2981,7 @@
isa = PBXGroup;
children = (
04564D792CF8CEF0004456E4 /* YHPlayerManager.swift */,
0413A9AE2CFE2C8200304BC6 /* YHMainChannelDelegate.swift */,
04564D482CF385D9004456E4 /* YHBasePlayerViewController.swift */,
04564D4A2CF389DD004456E4 /* YHLivePlayerViewController.swift */,
04564D6B2CF6C414004456E4 /* YHLivePlayerViewController+Api.swift */,
......@@ -3003,6 +3008,7 @@
04564D7D2CF8D03D004456E4 /* YHFloatingWindow.swift */,
04013E412CFADF6B001A8E40 /* YHShareAlertView.swift */,
04013E452CFDA9AD001A8E40 /* YHLiveShopView.swift */,
0413A9B02CFFDB9A00304BC6 /* YHCategoryDropdownView.swift */,
);
path = V;
sourceTree = "<group>";
......@@ -6666,6 +6672,7 @@
04256E172C75BD2700A37BA4 /* YHVisaPaymentTipsCell.swift in Sources */,
045EEEAA2B9F171A0022A143 /* YHWorkExampleViewController.swift in Sources */,
04256E1F2C7618A800A37BA4 /* YHAppointWarmTipsCell.swift in Sources */,
0413A9B12CFFDB9A00304BC6 /* YHCategoryDropdownView.swift in Sources */,
04256E132C75BD2700A37BA4 /* YHPayMemberContentItems.swift in Sources */,
A5FD63C12B62616D00D1D9DA /* YHInformationPerfectModel.swift in Sources */,
044F395C2CB8D58A007CA277 /* YHVisaRenewalPayInfoBaseCell.swift in Sources */,
......@@ -6818,6 +6825,7 @@
04FD85742C219CFD00BEF9C5 /* YHMatchResultListViewController.swift in Sources */,
045EEEB72B9F171A0022A143 /* YHWorkItemAddView.swift in Sources */,
0430E65C2C744187000511E2 /* YHAdopterCardModel.swift in Sources */,
0413A9AF2CFE2C8200304BC6 /* YHMainChannelDelegate.swift in Sources */,
04358E0E2C78395200811928 /* YHHKPlaceInfoCell.swift in Sources */,
A5ACE9372B4564F7002C94D2 /* YHBaseUrlManager.swift in Sources */,
04EA230A2BB5172F009DA928 /* YHDocumentPromptTableViewCell.swift in Sources */,
......
......@@ -277,9 +277,7 @@ extension YHLifeViewController: UICollectionViewDelegate, UICollectionViewDataSo
return
}
let item = self.viewModel.liveArr[indexPath.row]
// YHPlayerManager.shared.enterLive(from: nil, id: item.id, url: item.pull_url, title: item.live_title, roomId: item.room_id)
//let url = "https://pull-flv-l13.douyincdn.com/stage/stream-116307521507688888_ld5.flv?expire=1733728207&sign=cef0df720ef0dbe3126675d72dcacec2&major_anchor_level=common&abr_pts=-800&_session_id=037-2024120215100750CB84D802B8201D3D81.1733123408338.51633&rsi=1"
let playbackInfo = YHPlayerManager.PlaybackInfo(id: item.id, url: item.pull_url, title: item.live_title, roomId: item.room_id, isLive: true, scene: .fullscreen)
let playbackInfo = YHPlayerManager.PlaybackInfo(id: item.id, url: item.pull_url, title: item.live_title, roomId: item.room_id, uid: UInt(item.id), isLive: true, scene: .fullscreen)
YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo)
}
}
......
......@@ -141,7 +141,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// // TODO: - alex测试
// if index == 1 {
// let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
// let playbackInfo = YHPlayerManager.PlaybackInfo(id: 40, url: "https://pull-flv-l13.douyincdn.com/stage/stream-116307521507688888_ld5.flv?expire=1733728207&sign=cef0df720ef0dbe3126675d72dcacec2&major_anchor_level=common&abr_pts=-800&_session_id=037-2024120215100750CB84D802B8201D3D81.1733123408338.51633&rsi=1", title: nil, roomId: nil, isLive: true, scene: .fullscreen)
// let playbackInfo = YHPlayerManager.PlaybackInfo(id: 40, url: "https://pull-flv-f1-admin.douyincdn.com/thirdgame/stream-7443723341506054922_md.flv?keeptime=00093a80&wsSecret=cf2c048a5bceb7669e37b229e807c0e2&wsTime=674d82e7&major_anchor_level=common&abr_pts=-800&select_mode=score&_session_id=037-2024120217503167B9DF9F03DF6401DE50.1733133032147.26047&rsi=1", title: nil, roomId: nil, isLive: true, scene: .fullscreen)
// YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, playbackInfo: playbackInfo)
// return
// }
......@@ -222,20 +222,20 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// live_type 播放类型:1 展示最新直播,2指定直播,3 指定录播
// live_pull_url 直播拉流链接
// video_url 视频链接
// recorded_cate_id 录播分类id
// recorded_cate_id 录播分类id token: String? = nil, channelId
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
let playbackInfo = YHPlayerManager.PlaybackInfo(id: model.live_id, url: model.live_pull_url, title: nil, roomId: nil, isLive: true, scene: .fullscreen)
let playbackInfo = YHPlayerManager.PlaybackInfo(id: model.live_id, url: model.live_pull_url, title: nil, roomId: nil, token: model.token, channelId: model.rtmp_channel, uid: UInt(model.live_id), isLive: true, scene: .fullscreen)
YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, playbackInfo: playbackInfo)
printLog("跳转直播")
case 101://录播
printLog("跳转录播")
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
let playbackInfo = YHPlayerManager.PlaybackInfo(id: model.live_id, url: model.video_url, title: nil, roomId: nil, isLive: false, scene: .fullscreen)
let playbackInfo = YHPlayerManager.PlaybackInfo(id: model.live_id, url: model.video_url, title: nil, roomId: nil, uid: nil, isLive: false, scene: .fullscreen)
YHPlayerManager.shared.enterVOD(from: cell?.bannerImagV, playbackInfo: playbackInfo)
case 102://图片直播
printLog("跳转录播")
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
let playbackInfo = YHPlayerManager.PlaybackInfo(id: model.live_id, url: model.live_pull_url, title: nil, roomId: nil, isLive: true, scene: .fullscreen)
let playbackInfo = YHPlayerManager.PlaybackInfo(id: model.live_id, url: model.live_pull_url, title: nil, roomId: nil, token: model.token, channelId: model.rtmp_channel, uid: UInt(model.live_id), isLive: true, scene: .fullscreen)
YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, playbackInfo: playbackInfo)
case 0://0 不需要跳转
printLog("0 不需要跳转")
......@@ -271,7 +271,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// if let cell = cell as? YHHomeBannerCollectionViewCell {
// if index == 1 {
//
// let playbackInfo = YHPlayerManager.PlaybackInfo(id: 40, url: "https://pull-flv-l13.douyincdn.com/stage/stream-116307521507688888_ld5.flv?expire=1733728207&sign=cef0df720ef0dbe3126675d72dcacec2&major_anchor_level=common&abr_pts=-800&_session_id=037-2024120215100750CB84D802B8201D3D81.1733123408338.51633&rsi=1", title: nil, roomId: nil, isLive: true, scene: .banner)
// let playbackInfo = YHPlayerManager.PlaybackInfo(id: 40, url: "https://pull-flv-f1-admin.douyincdn.com/thirdgame/stream-7443723341506054922_md.flv?keeptime=00093a80&wsSecret=cf2c048a5bceb7669e37b229e807c0e2&wsTime=674d82e7&major_anchor_level=common&abr_pts=-800&select_mode=score&_session_id=037-2024120217503167B9DF9F03DF6401DE50.1733133032147.26047&rsi=1", title: nil, roomId: nil, isLive: true, scene: .banner)
// YHPlayerManager.shared.enterBanner(playbackInfo: playbackInfo, inView: cell.bannerImagV)
//
// } else {
......
......@@ -257,8 +257,8 @@ class YHSelectLookTableViewCell: UITableViewCell {
flagLabel.isHidden = false
}
let a: ASAttributedString = .init("¥", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor.mainTextColor))
let b: ASAttributedString = .init("\(dataSource.price) ", .font(UIFont.PFSC_R(ofSize: 20)),.foreground(UIColor.mainTextColor))
let c: ASAttributedString = .init(\(dataSource.linePrice)", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
let b: ASAttributedString = .init("\(dataSource.linePrice) ", .font(UIFont.PFSC_R(ofSize: 20)),.foreground(UIColor.mainTextColor))
let c: ASAttributedString = .init(\(dataSource.price)", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
self.subTitleLabel.attributed.text = a + b + c
itemView.removeSubviews()
var i = 0
......
......@@ -94,7 +94,7 @@ extension YHSelectLookView: UICollectionViewDelegate, UICollectionViewDataSource
return
}
let item = items[indexPath.row]
let playbackInfo = YHPlayerManager.PlaybackInfo(id: item.id, url: item.pull_url, title: item.live_title, roomId: item.room_id, isLive: true, scene: .fullscreen)
let playbackInfo = YHPlayerManager.PlaybackInfo(id: item.id, url: item.pull_url, title: item.live_title, roomId: item.room_id, uid: UInt(item.id), isLive: true, scene: .fullscreen)
YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo)
}
}
......
......@@ -28,7 +28,7 @@ class YHBasePlayerViewController: YHBaseViewController {
lazy var playerView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.backgroundColor = .black
return view
}()
......@@ -57,12 +57,18 @@ class YHBasePlayerViewController: YHBaseViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
// navigationController?.setNavigationBarHidden(true, animated: animated)
gk_navBarAlpha = 0
gk_navigationBar.isHidden = true
view.backgroundColor = .black
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
// navigationController?.setNavigationBarHidden(false, animated: animated)
gk_navBarAlpha = 1
gk_navigationBar.isHidden = false
view.backgroundColor = .black
controlsAutoHideTimer?.invalidate()
controlsAutoHideTimer = nil
}
......@@ -76,12 +82,10 @@ class YHBasePlayerViewController: YHBaseViewController {
gk_navBarAlpha = 0
gk_navigationBar.isHidden = true
view.backgroundColor = .black
view.addSubview(containerView)
containerView.addSubview(playerView)
containerView.addSubview(controlView)
containerView.addSubview(topBarView)
setupConstraints()
}
......
......@@ -16,6 +16,8 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
private var roomId: String?
private let messageQueue = DispatchQueue(label: "com.livePlayerRoom.messageQueue")
let viewModel = YHLiveSalesViewModel()
private var goodsListView: YHLiveShopView?
private var isLiveStateOn: Bool = false
private var listMaxWidth: CGFloat {
return KScreenWidth * 248.0 / 375.0
......@@ -43,6 +45,24 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
return view
}()
private lazy var liveStateVC: YHLiveStateViewController = {
let vc = YHLiveStateViewController()
vc.shareEvent = { [weak self] in
self?.shareLive()
}
vc.closeEvent = { [weak self] in
self?.closeLive()
}
vc.backHomeEvent = { [weak self] in
self?.closeLive()
UIViewController.current?.navigationController?.popToRootViewController(animated: false)
goTabBarBy(tabType: .home)
}
return vc
}()
// MARK: - Initialization
init(id: Int, url: String? = nil, title: String? = nil, roomId: String? = nil) {
self.liveId = id
......@@ -51,9 +71,6 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
// 隐藏播控UI
controlView.isHidden = true
player?.delegate = self // 设置播放器代理
if let url = url {
play(url: url, title: title)
}
if let roomId = roomId {
setupChatRoom(roomId: roomId)
}
......@@ -66,6 +83,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
modalPresentationStyle = .fullScreen
setupLiveUI()
setupLiveNotifications()
setupData()
......@@ -97,15 +115,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
topBarView.closeButtonClickEvent = { [weak self] in
self?.quitChatRoom()
self?.leaveLiveRoom()
YHPlayerManager.shared.stop(type: .main)
if let navigationController = self?.navigationController {
navigationController.popViewController(animated: true)
} else {
self?.dismiss(animated: true)
}
self?.closeLive()
}
topBarView.zoomButtonClickEvent = { [weak self] in
self?.enterFloating()
}
......@@ -113,6 +125,33 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
topBarView.shareButtonClickEvent = { [weak self] in
self?.shareLive()
}
bottomInputBar.giftButtonClickEvent = { [weak self] in
self?.showGoods()
}
}
private func setupStateViewController() {
isLiveStateOn = true
// 1. 添加子控制器
// addChild(liveStateVC)
view.addSubview(liveStateVC.view)
view.bringSubviewToFront(liveStateVC.view)
liveStateVC.view.isUserInteractionEnabled = true
// 2. 使用SnapKit设置约束
liveStateVC.view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
// 3. 通知子控制器已被添加到父控制器
// liveStateVC.didMove(toParent: self)
}
// 移除子控制器
private func removeStateViewController() {
isLiveStateOn = false
// liveStateVC.willMove(toParent: nil)
liveStateVC.view.removeFromSuperview()
// liveStateVC.removeFromParent()
}
private func setupData() {
......@@ -131,24 +170,37 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
}
private func handleLiveDetailSuccess(_ liveDetail: YHLiveDetailModel) {
private func handleLiveDetailSuccess(_ liveDetail: YHLiveDetailModel, needJoinIMRoom: Bool = true, needJoinLiveChannel: Bool = true) {
// 更新顶部栏信息
topBarView.setupTopBarView(
headUrl: liveDetail.avatar,
nickname: liveDetail.hxNickname,
count: liveDetail.access_num
)
// 如果没有预设URL,使用接口返回的URL播放
if currentPlayingURL == nil {
play(url: liveDetail.pullUrl)
playbackInfo?.channelId = liveDetail.rtmp_channel
playbackInfo?.token = liveDetail.token
if needJoinLiveChannel {
if !liveDetail.rtmp_channel.isEmpty, !liveDetail.token.isEmpty, let uid = playbackInfo?.uid, let player = player {
player.setPlayView(playerView)
YHPlayerManager.shared.joinChannel(for: player, token: liveDetail.token, channelId: liveDetail.rtmp_channel, uid: uid)
} else if currentPlayingURL == nil, !liveDetail.pullUrl.isEmpty {
play(url: liveDetail.pullUrl) // 如果没有预设URL,使用接口返回的URL播放
}
}
// 如果没有预设roomId,使用接口返回的roomId
if roomId == nil {
if roomId == nil, needJoinIMRoom {
roomId = liveDetail.roomId
setupChatRoom(roomId: liveDetail.roomId)
}
bottomInputBar.updateGiftCount(liveDetail.goods.count)
if liveDetail.getLiveState() != .onLive {
if !isLiveStateOn {
setupStateViewController()
}
liveStateVC.setupData(liveDetail: liveDetail)
} else {
removeStateViewController()
}
}
private func setupChatRoom(roomId: String) {
......@@ -180,6 +232,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
NotificationCenter.default.addObserver(self, selector: #selector(didLoginYH), name: YhConstant.YhNotification.didLoginSuccessNotifiction, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didLogOutYH), name: YhConstant.YhNotification.didLogoutSuccessNotifiction, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didJoinedOfUid), name: Notification.Name("com.YHPlayerManager.didJoinedOfUid"), object: nil)
}
// MARK: - Public Methods
......@@ -194,6 +247,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
guard let playbackInfo = playbackInfo else {
return
}
//player?.setPlayViewNull()
YHPlayerManager.shared.enterFloating(from: self, playbackInfo: playbackInfo)
}
......@@ -243,6 +297,16 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
}
private func closeLive() {
quitChatRoom()
leaveLiveRoom()
//YHPlayerManager.shared.stop(type: .main)
if let player = player {
YHPlayerManager.shared.leaveChannel(for: player)
}
dismiss(animated: true)
}
private func shareLive() {
guard let liveModel = viewModel.liveDetailModel else {
return
......@@ -250,6 +314,47 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
YHShareAlertView.show(image: liveModel.live_image, title: "@" + liveModel.account, subMessage: liveModel.live_title, linkUrl: liveModel.live_h5_url, isLive: true)
}
private func showGoods() {
let list = viewModel.liveDetailModel?.goods ?? []
let view = YHLiveShopView.show { [weak self] index in
guard list.count > index else {
return
}
let model = list[index]
self?.gotoH5GoodsDetail(id: model.id)
}
view.dataSource = list
view.closeEvent = { [weak self] in
self?.goodsListView = nil
}
goodsListView = view
}
private func gotoH5GoodsDetail(id: Int) {
var url = YHBaseUrlManager.shared.curH5URL() + "superAppBridge.html#/goods/sales-detail" + "?id=\(id)"
if YHLoginManager.shared.isLogin() {
let token = YHLoginManager.shared.h5Token
let urlHasParam = String.hasQueryParameters(urlString: url)
if urlHasParam {
url = url + "&param=" + token
} else {
url = url + "?param=" + token
}
}
var tUrl = url
if !url.contains("navigationH=") {
tUrl = url + "?navigationH=\(k_Height_NavigationtBarAndStatuBar)"
if url.contains("?") {
tUrl = url + "&navigationH=\(k_Height_NavigationtBarAndStatuBar)"
}
}
let vc = YHH5WebViewVC()
vc.url = tUrl
vc.isHideNavigationBar = false
goodsListView?.dismiss()
navigationController?.pushViewController(vc)
}
// MARK: - Message Handling
private func handleMessageInput(text: String, controller: YHMessageInputViewController) {
guard checkLogin(),
......@@ -298,6 +403,17 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
// MARK: - Notification Handlers
@objc private func didJoinedOfUid() {
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = playbackInfo?.uid ?? 0
videoCanvas.view = playerView
videoCanvas.renderMode = .fit
videoCanvas.backgroundColor = 0x000000
let ret = YHPlayerManager.shared.agoraKit.setupRemoteVideo(videoCanvas)
printLog(ret)
}
@objc private func didChatManagerReceiveMessages(_ note: Notification) {
guard let messages = note.object as? [EMChatMessage],
let message = messages.first,
......@@ -305,6 +421,40 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
return
}
appendHistoryMessages(messages)
messages.forEach { message in
if let body = message.body as? EMCustomMessageBody, let event = body.event, let roomCustomEvent = YHChatRoomCustomEvent(rawValue: event) {
DispatchQueue.main.async {
self.updateLiveDetailWith(event: roomCustomEvent)
}
}
}
}
private func updateLiveDetailWith(event: YHChatRoomCustomEvent) {
viewModel.getLiveDetail(id: liveId) { [weak self] liveDetail, error in
guard let self = self else { return }
if let liveDetail = liveDetail {
switch event {
case .liveStart:
self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: true)
case .liveEnd:
self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: false)
case .livePause:
self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: false)
case .liveResume:
self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: false)
case .liveGoodsRefresh:
self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: false)
self.goodsListView?.dataSource = liveDetail.goods
}
} else {
printLog("YHLivePlayerViewController: 请求失败")
if let errorMsg = error?.errorMsg, !errorMsg.isEmpty {
YHHUD.flash(message: errorMsg)
}
return
}
}
}
@objc private func didLoginYH() {
......
......@@ -12,9 +12,14 @@ enum YHLiveState: Int {
case start = 0
case stop = 1
case end = 2
case onLive = 3
}
class YHLiveStateViewController: YHBaseViewController {
var bgLogoImageView: UIImageView!
var bgView: UIView!
var blurEffect: UIBlurEffect!
var blurView: UIVisualEffectView!
var closeButton: UIButton!
var shareButton: UIButton!
var logImageView: UIImageView!
......@@ -24,15 +29,62 @@ class YHLiveStateViewController: YHBaseViewController {
var getCodeButton: UIButton!
var state: YHLiveState = .start
var shareEvent: (() -> Void)?
var closeEvent: (() -> Void)?
var backHomeEvent: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
setView()
updateData(state)
//updateData(state)
}
func setupData(liveDetail: YHLiveDetailModel) {
if let url = URL(string: liveDetail.avatar) {
bgLogoImageView.kf.setImage(with: url, placeholder: UIImage(named: "global_default_image"))
logImageView.kf.setImage(with: url, placeholder: UIImage(named: "global_default_image"))
} else {
bgLogoImageView.image = UIImage(named: "global_default_image")
logImageView.image = UIImage(named: "global_default_image")
}
loginTitleLabel.text = liveDetail.hxNickname
updateData(liveDetail)
}
func setView() {
view.backgroundColor = UIColor(hex: 0x000000, alpha: 0.6)
view.backgroundColor = .black
bgLogoImageView = {
let view = UIImageView(frame: view.bounds)
view.contentMode = .scaleAspectFill
return view
}()
view.addSubview(bgLogoImageView)
bgLogoImageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
bgView = {
let view = UIView(frame: view.bounds)
view.backgroundColor = UIColor(hex: 0x000000, alpha: 0.85)
return view
}()
view.addSubview(bgView)
bgView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
blurEffect = {
return UIBlurEffect(style: .dark)
}()
blurView = {
let view = UIVisualEffectView(effect: blurEffect)
view.frame = view.bounds
view.alpha = 0.5
return view
}()
view.addSubview(blurView)
blurView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
closeButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "live_close"), for: .normal)
......@@ -49,7 +101,7 @@ class YHLiveStateViewController: YHBaseViewController {
shareButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "live_share"), for: .normal)
button.addTarget(self, action: #selector(close), for: .touchUpInside)
button.addTarget(self, action: #selector(share), for: .touchUpInside)
return button
}()
view.addSubview(shareButton)
......@@ -74,7 +126,7 @@ class YHLiveStateViewController: YHBaseViewController {
loginTitleLabel = {
let label = UILabel()
label.text = "优才E老师"
//label.text = "优才E老师"
label.font = UIFont.PFSC_M(ofSize: 16)
label.textColor = UIColor.white
label.textAlignment = .center
......@@ -151,15 +203,21 @@ class YHLiveStateViewController: YHBaseViewController {
}
}
@objc func share() {
shareEvent?()
}
@objc func close() {
dismiss(animated: true)
closeEvent?()
// dismiss(animated: true)
}
func updateData(_ type: YHLiveState) {
func updateData(_ liveDetail: YHLiveDetailModel) {
let type = liveDetail.getLiveState()
switch type {
case .start:
loginSubTitleLabel.text = "直播暂未开始"
messageLabel.text = "预计6月28日18:00开始~"
messageLabel.text = "预计\(liveDetail.start_time)开始~"
getCodeButton.isHidden = true
case .stop:
loginSubTitleLabel.text = "主播离开了"
......@@ -169,10 +227,12 @@ class YHLiveStateViewController: YHBaseViewController {
loginSubTitleLabel.text = "直播已结束"
messageLabel.text = "直播已结束,去首页逛逛吧~"
getCodeButton.isHidden = false
case .onLive:
break
}
}
@objc func backHome() {
backHomeEvent?()
}
}
//
// YHMainChannelDelegate.swift
// galaxy
//
// Created by alexzzw on 2024/12/3.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import AgoraRtcKit
import UIKit
// MARK: - Channel Delegates
class YHMainChannelDelegate: NSObject, AgoraRtcEngineDelegate {
var channelId: String?
weak var player: YHPlayer?
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) {
printLog("main channel: local user join room \(channelId ?? ""): \(uid) \(elapsed)ms")
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
guard let channelId = channelId,
let player = player,
let view = player.currentPlayView else { return }
printLog("main channel: remote user join room \(channelId): \(uid) \(elapsed)ms")
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.view = view
videoCanvas.renderMode = .fit
engine.setupRemoteVideo(videoCanvas)
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) {
printLog("main channel: remote user left: \(uid) reason \(reason)")
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.view = nil
videoCanvas.renderMode = .hidden
engine.setupRemoteVideo(videoCanvas)
}
}
class YHSecondaryChannelDelegate: NSObject, AgoraRtcEngineDelegate {
var channelId: String?
weak var player: YHPlayer?
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) {
printLog("secondary channel: local user join room \(channelId ?? ""): \(uid) \(elapsed)ms")
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
guard let channelId = channelId,
let player = player,
let view = player.currentPlayView else { return }
printLog("secondary channel: remote user join room \(channelId): \(uid) \(elapsed)ms")
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.view = view
videoCanvas.renderMode = .fit
let connection = AgoraRtcConnection()
connection.channelId = channelId
connection.localUid = player.currentUid ?? 0
engine.setupRemoteVideoEx(videoCanvas, connection: connection)
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) {
guard let channelId = channelId,
let player = player else { return }
printLog("secondary channel: remote user left: \(uid) reason \(reason)")
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.view = nil
videoCanvas.renderMode = .hidden
let connection = AgoraRtcConnection()
connection.channelId = channelId
connection.localUid = player.currentUid ?? 0
engine.setupRemoteVideoEx(videoCanvas, connection: connection)
}
}
......@@ -6,6 +6,119 @@
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
//import AgoraRtcKit
//import Foundation
//
//// MARK: - 播放器类型
//
//enum YHPlayerType {
// case main
// case secondary
//}
//
//protocol YHPlayerDelegate: AnyObject {
// func player(_ player: YHPlayer, didChangedToState state: AgoraMediaPlayerState, reason: AgoraMediaPlayerReason)
// func player(_ player: YHPlayer, didChangedToPosition position: Int)
// func player(_ player: YHPlayer, didReceiveVideoSize size: CGSize)
//}
//
//// MARK: - 播放器实例封装
//
//class YHPlayer {
// weak var delegate: YHPlayerDelegate?
// let type: YHPlayerType
// var playerKit: AgoraRtcMediaPlayerProtocol?
// weak var agoraKit: AgoraRtcEngineKit?
//
// private(set) var currentURL: String?
// weak var currentPlayView: UIView?
// private(set) var currentTitle: String?
// private(set) var currentChannelId: String?
// private(set) var currentUid: UInt?
// private(set) var isJoined: Bool = false
//
// var isMuted: Bool {
// get { playerKit?.getMute() ?? false }
// set { playerKit?.mute(newValue) }
// }
//
// init(type: YHPlayerType, playerKit: AgoraRtcMediaPlayerProtocol?, agoraKit: AgoraRtcEngineKit?) {
// self.type = type
// self.playerKit = playerKit
// self.agoraKit = agoraKit
// // 基础设置
// playerKit?.setLoopCount(-1)
// }
//
// func setPlayView(_ view: UIView?) {
// currentPlayView = view
// playerKit?.setRenderMode(.fit)
// playerKit?.setView(view)
// }
//
// func setJoinInfo(channelId: String, uid: UInt) {
// currentChannelId = channelId
// currentUid = uid
// isJoined = true
// }
//
// func clearJoinInfo() {
// currentChannelId = nil
// currentUid = nil
// isJoined = false
// }
//
// func play(url: String, title: String? = nil) {
// currentURL = url
// currentTitle = title
// let mediaSource = AgoraMediaSource()
// mediaSource.url = url
// mediaSource.autoPlay = true
// let result = playerKit?.open(with: mediaSource)
// if result == 0 {
// playerKit?.play()
// }
// }
//
// func stop() {
// playerKit?.stop()
// currentPlayView = nil
// currentURL = nil
// currentTitle = nil
// }
//
// func pause() {
// playerKit?.pause()
// }
//
// func resume() {
// playerKit?.play()
// }
//
// func reset() {
// stop()
// setPlayView(nil)
// delegate = nil
// }
//
// func releasePlayer() {
// reset()
// playerKit = nil
// }
//
// func getPosition() -> Int {
// return playerKit?.getPosition() ?? 0
// }
//
// func getDuration() -> Int {
// return playerKit?.getDuration() ?? 0
// }
//
// func getPlayState() -> AgoraMediaPlayerState {
// return playerKit?.getPlayerState() ?? .idle
// }
//}
import AgoraRtcKit
import Foundation
......@@ -23,35 +136,109 @@ protocol YHPlayerDelegate: AnyObject {
// MARK: - 播放器实例封装
class YHPlayer {
// 持有一个固定的播放视图
private lazy var playerContentView: UIView = {
let view = UIView()
view.backgroundColor = .black
return view
}()
weak var delegate: YHPlayerDelegate?
let type: YHPlayerType
var playerKit: AgoraRtcMediaPlayerProtocol?
weak var agoraKit: AgoraRtcEngineKit?
private(set) var currentURL: String?
weak var currentPlayView: UIView?
private(set) var currentTitle: String?
private(set) var currentChannelId: String?
private(set) var currentToken: String?
private(set) var currentUid: UInt?
private(set) var isJoined: Bool = false
// 保存最后的播放信息用于恢复
private var lastPlaybackInfo: (url: String?, title: String?)?
var isMuted: Bool {
get { playerKit?.getMute() ?? false }
set { playerKit?.mute(newValue) }
}
init(type: YHPlayerType, playerKit: AgoraRtcMediaPlayerProtocol?) {
init(type: YHPlayerType, playerKit: AgoraRtcMediaPlayerProtocol?, agoraKit: AgoraRtcEngineKit?) {
self.type = type
self.playerKit = playerKit
self.agoraKit = agoraKit
// 基础设置
playerKit?.setLoopCount(-1) // 循环播放
playerKit?.setLoopCount(-1)
}
// func setPlayViewNull() {
// let hideVideoCanvas = AgoraRtcVideoCanvas()
// hideVideoCanvas.uid = currentUid ?? 0
// hideVideoCanvas.view = nil
// hideVideoCanvas.renderMode = .hidden
// agoraKit?.setupRemoteVideo(hideVideoCanvas)
// }
func setPlayView(_ view: UIView?) {
// 保存旧的视图用于动画
// let oldView = currentPlayView
// 设置新的视图
currentPlayView = view
playerKit?.setView(view)
playerKit?.setRenderMode(.fit)
// if let view = view, let uid = currentUid, let channelId = currentChannelId {
// if type == .secondary {
// // 副播放器需要使用 Ex 方法
// let videoCanvas = AgoraRtcVideoCanvas()
// videoCanvas.view = view
// videoCanvas.renderMode = .fit
// videoCanvas.uid = uid
// let connection = AgoraRtcConnection()
// connection.channelId = channelId
// connection.localUid = uid
// agoraKit?.setupRemoteVideoEx(videoCanvas, connection: connection)
// } else {
// let hideVideoCanvas = AgoraRtcVideoCanvas()
// hideVideoCanvas.uid = uid
// hideVideoCanvas.view = nil
// hideVideoCanvas.renderMode = .hidden
// agoraKit?.setupRemoteVideo(hideVideoCanvas)
// DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
// // 主播放器使用普通方法
// let videoCanvas = AgoraRtcVideoCanvas()
// videoCanvas.view = view
// videoCanvas.renderMode = .fit
// videoCanvas.uid = uid
// self.agoraKit?.setupRemoteVideo(videoCanvas)
// })
//
// }
// }
}
func setJoinInfo(token: String, channelId: String, uid: UInt) {
currentToken = token
currentChannelId = channelId
currentUid = uid
isJoined = true
}
func clearJoinInfo() {
currentToken = nil
currentChannelId = nil
currentUid = nil
isJoined = false
currentPlayView = nil
currentURL = nil
currentTitle = nil
}
func play(url: String, title: String? = nil) {
currentURL = url
currentTitle = title
lastPlaybackInfo = (url, title) // 保存播放信息
let mediaSource = AgoraMediaSource()
mediaSource.url = url
mediaSource.autoPlay = true
......@@ -63,9 +250,11 @@ class YHPlayer {
func stop() {
playerKit?.stop()
clearJoinInfo()
currentPlayView = nil
currentURL = nil
currentTitle = nil
// 保留 lastPlaybackInfo 用于恢复
}
func pause() {
......@@ -73,13 +262,39 @@ class YHPlayer {
}
func resume() {
if playerKit?.getPlayerState() == .paused {
playerKit?.resume()
} else {
playerKit?.play()
}
}
func resume(withNewView view: UIView) {
// 设置新的播放视图
setPlayView(view)
// 如果有频道信息,通知 Manager 重新加入频道
if let token = currentToken,
let channelId = currentChannelId,
let uid = currentUid {
YHPlayerManager.shared.joinChannel(for: self,
token: token,
channelId: channelId,
uid: uid)
}
// 如果有上次的播放信息,重新播放
if let lastInfo = lastPlaybackInfo,
let url = lastInfo.url {
play(url: url, title: lastInfo.title)
}
}
func reset() {
stop()
setPlayView(nil)
delegate = nil
lastPlaybackInfo = nil
}
func releasePlayer() {
......@@ -87,6 +302,8 @@ class YHPlayer {
playerKit = nil
}
// MARK: - Playback Info
func getPosition() -> Int {
return playerKit?.getPosition() ?? 0
}
......@@ -98,4 +315,35 @@ class YHPlayer {
func getPlayState() -> AgoraMediaPlayerState {
return playerKit?.getPlayerState() ?? .idle
}
// MARK: - Seeking
func seek(to position: Int) {
playerKit?.seek(toPosition: position)
}
// MARK: - Volume Control
func setVolume(_ volume: Int32) {
playerKit?.adjustPlayoutVolume(volume)
}
// MARK: - Playback Speed
func setPlaybackSpeed(_ speed: Double) {
playerKit?.setPlaybackSpeed(Int32(speed * 100))
}
}
// MARK: - Factory Methods
extension YHPlayer {
static func createMainPlayer(playerKit: AgoraRtcMediaPlayerProtocol?,
agoraKit: AgoraRtcEngineKit?) -> YHPlayer {
return YHPlayer(type: .main, playerKit: playerKit, agoraKit: agoraKit)
}
static func createSecondaryPlayer(playerKit: AgoraRtcMediaPlayerProtocol?,
agoraKit: AgoraRtcEngineKit?) -> YHPlayer {
return YHPlayer(type: .secondary, playerKit: playerKit, agoraKit: agoraKit)
}
}
......@@ -15,25 +15,39 @@ class YHPlayerManager: NSObject {
// MARK: - Types
enum PlaybackScene: Int {
case fullscreen // 直播间/点播页
case floating // 小窗
case banner // banner
case fullscreen
case floating
case banner
}
struct PlaybackInfo: Equatable {
let id: Int
let url: String?
let title: String?
let roomId: String?
var url: String?
var title: String?
var roomId: String?
var token: String?
var channelId: String?
var uid: UInt?
let isLive: Bool
var scene: PlaybackScene
var playerType: YHPlayerType
init(id: Int, url: String? = nil, title: String? = nil, roomId: String? = nil, isLive: Bool, scene: PlaybackScene = .fullscreen) {
init(id: Int,
url: String? = nil,
title: String? = nil,
roomId: String? = nil,
token: String? = nil,
channelId: String? = nil,
uid: UInt? = nil,
isLive: Bool,
scene: PlaybackScene = .fullscreen) {
self.id = id
self.url = url
self.title = title
self.roomId = roomId
self.token = token
self.channelId = channelId
self.uid = uid
self.isLive = isLive
self.scene = scene
playerType = .main
......@@ -48,28 +62,41 @@ class YHPlayerManager: NSObject {
static let shared = YHPlayerManager()
private var agoraKit: AgoraRtcEngineKit!
var agoraKit: AgoraRtcEngineKit!
private var mainChannelDelegate: YHMainChannelDelegate?
private var secondaryChannelDelegate: YHSecondaryChannelDelegate?
private var activePlayers: [YHPlayerType: YHPlayer] = [:]
private var currentPlaybackInfo: [YHPlayerType: PlaybackInfo] = [:]
private var floatingWindow: YHFloatingWindow?
// 转场动画相关
private var transitionSourceView: UIView?
// MARK: - Initialization
override private init() {
super.init()
setupChannelDelegates()
setupAgoraKit()
}
private func setupChannelDelegates() {
mainChannelDelegate = YHMainChannelDelegate()
secondaryChannelDelegate = YHSecondaryChannelDelegate()
}
private func setupAgoraKit() {
let config = AgoraRtcEngineConfig()
config.appId = YhConstant.AgoraRtcKit.appId
config.areaCode = .global
config.channelProfile = .liveBroadcasting
agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: mainChannelDelegate)
// Enable video
agoraKit.enableVideo()
// Set client role as audience
let options = AgoraClientRoleOptions()
options.audienceLatencyLevel = .lowLatency
agoraKit.setClientRole(.audience, options: options)
// Set audio route to speaker
agoraKit.setDefaultAudioRouteToSpeakerphone(true)
}
// MARK: - Basic Playback Control
......@@ -110,6 +137,32 @@ class YHPlayerManager: NSObject {
return activePlayers[type]
}
// MARK: - Resource Management
func cleanupOnExit() {
// 停止所有播放
activePlayers.forEach { $0.value.stop() }
// 释放副播放器
releasePlayer(.secondary)
// 清理播放信息
currentPlaybackInfo.removeAll()
floatingWindow?.dismiss()
floatingWindow = nil
// 重置主播放器
if let mainPlayer = activePlayers[.main] {
mainPlayer.reset()
}
}
deinit {
activePlayers.forEach { $0.value.releasePlayer() }
activePlayers.removeAll()
AgoraRtcEngineKit.destroy()
}
// MARK: - Player Management
private func player(for type: YHPlayerType) -> YHPlayer {
......@@ -123,11 +176,14 @@ class YHPlayerManager: NSObject {
}
private func createPlayer(for type: YHPlayerType) -> YHPlayer {
guard let playerKit = agoraKit.createMediaPlayer(with: self) else {
//fatalError("Failed to create media player")
return YHPlayer(type: type, playerKit: nil)
let playerKit = agoraKit.createMediaPlayer(with: self)
let player = YHPlayer(type: type, playerKit: playerKit, agoraKit: agoraKit)
// 设置对应的 delegate
if type == .main {
mainChannelDelegate?.player = player
} else {
secondaryChannelDelegate?.player = player
}
let player = YHPlayer(type: type, playerKit: playerKit)
return player
}
......@@ -148,6 +204,65 @@ class YHPlayerManager: NSObject {
}
}
// 加入频道的逻辑移到 PlayerManager
func joinChannel(for player: YHPlayer,
token: String,
channelId: String,
uid: UInt) {
let option = AgoraRtcChannelMediaOptions()
option.publishCameraTrack = false
option.publishMicrophoneTrack = false
option.autoSubscribeVideo = true
option.autoSubscribeAudio = true
option.clientRoleType = .audience
if player.type == .secondary {
let connection = AgoraRtcConnection()
connection.channelId = channelId
connection.localUid = uid
secondaryChannelDelegate?.channelId = channelId
let result = agoraKit.joinChannelEx(byToken: token,
connection: connection,
delegate: secondaryChannelDelegate,
mediaOptions: option)
if result == 0 {
player.setJoinInfo(token: token, channelId: channelId, uid: uid)
}
} else {
mainChannelDelegate?.channelId = channelId
let result = agoraKit.joinChannel(byToken: token,
channelId: channelId,
uid: uid,
mediaOptions: option,
joinSuccess: nil)
if result == 0 {
player.setJoinInfo(token: token, channelId: channelId, uid: uid)
}
}
}
func leaveChannel(for player: YHPlayer) {
guard let channelId = player.currentChannelId,
let uid = player.currentUid else { return }
if player.type == .secondary {
let connection = AgoraRtcConnection()
connection.channelId = channelId
connection.localUid = uid
//agoraKit.disableVideo()
//agoraKit.disableAudio()
agoraKit.leaveChannelEx(connection)
//AgoraRtcEngineKit.destroy()
} else {
//agoraKit.disableVideo()
//agoraKit.disableAudio()
agoraKit.leaveChannel(nil)
//AgoraRtcEngineKit.destroy()
}
player.clearJoinInfo()
}
// MARK: - Scene Management
func enterVOD(from sourceView: UIView?, playbackInfo: PlaybackInfo) {
......@@ -161,7 +276,7 @@ class YHPlayerManager: NSObject {
if playbackInfo.scene == .banner,
let bannerPlayer = activePlayers[.secondary] {
startPosition = bannerPlayer.getPosition()
releasePlayer(.secondary)
bannerPlayer.stop()
}
let playerVC = YHVODPlayerViewController(id: playbackInfo.id, url: playbackInfo.url, title: playbackInfo.title)
......@@ -176,6 +291,10 @@ class YHPlayerManager: NSObject {
// 关闭小窗
exitFloating()
if let url = playbackInfo.url {
player.play(url: url, title: playbackInfo.title)
}
present(playerVC, from: sourceView)
}
......@@ -187,10 +306,14 @@ class YHPlayerManager: NSObject {
// 如果是从banner跳转,释放副播放器
if playbackInfo.scene == .banner {
releasePlayer(.secondary)
activePlayers[.secondary]?.pause()
}
let playerVC = YHLivePlayerViewController(id: playbackInfo.id, url: playbackInfo.url, title: playbackInfo.title, roomId: playbackInfo.roomId)
let playerVC = YHLivePlayerViewController(id: playbackInfo.id,
url: nil,
title: playbackInfo.title,
roomId: playbackInfo.roomId)
let navVC = YHNavigationController(rootViewController: playerVC)
currentPlaybackInfo[playerType] = updatedInfo
let player = player(for: playerType)
......@@ -201,23 +324,54 @@ class YHPlayerManager: NSObject {
// 关闭小窗
exitFloating()
present(playerVC, from: sourceView)
// 加入频道
if let token = playbackInfo.token,
let channelId = playbackInfo.channelId, let uid = playbackInfo.uid, !token.isEmpty, !channelId.isEmpty {
joinChannel(for: player, token: token, channelId: channelId, uid: uid)
} else if let url = playbackInfo.url, url.count > 0 {
player.play(url: url, title: playbackInfo.title)
}
present(navVC, from: sourceView)
}
func enterFloating(from viewController: UIViewController? = nil, playbackInfo: PlaybackInfo) {
guard let window = UIApplication.shared.keyWindow else { return }
guard let window = UIApplication.shared.yhKeyWindow() else { return }
let playerType = determinePlayerType(for: .floating)
let player = player(for: playerType)
let player: YHPlayer// = player(for: playerType)
var updatedInfo = playbackInfo
updatedInfo.scene = .floating
updatedInfo.playerType = playerType
currentPlaybackInfo[playerType] = updatedInfo
if let url = playbackInfo.url {
// 检查是否存在当前播放器
if let existingPlayer = activePlayers[playerType],
currentPlaybackInfo[playerType] == playbackInfo {
// 使用现有播放器
player = existingPlayer
} else {
// 创建新播放器
player = self.player(for: playerType)
// 加入频道
if let token = playbackInfo.token,
let channelId = playbackInfo.channelId,
let uid = playbackInfo.uid, !token.isEmpty, !channelId.isEmpty {
joinChannel(for: player, token: token, channelId: channelId, uid: uid)
} else if let url = playbackInfo.url, !url.isEmpty {
player.play(url: url, title: playbackInfo.title)
}
}
// // 加入频道
// if let token = playbackInfo.token,
// let channelId = playbackInfo.channelId, let uid = playbackInfo.uid, !token.isEmpty, !channelId.isEmpty {
// joinChannel(for: player, token: token, channelId: channelId, uid: uid)
// } else if let url = playbackInfo.url, !url.isEmpty {
// player.play(url: url, title: playbackInfo.title)
// }
// 获取当前播放视图的截图和位置
if let sourceView = player.currentPlayView,
......@@ -240,8 +394,7 @@ class YHPlayerManager: NSObject {
let targetFrame = floatingWindow.calculateInitialFrame()
// 执行动画
let showFloatingWindow = { [weak self] in
guard let self = self else { return }
let showFloatingWindow = {
UIView.animate(withDuration: 0.3, animations: {
snapshotView.frame = targetFrame
}, completion: { _ in
......@@ -265,8 +418,7 @@ class YHPlayerManager: NSObject {
floatingWindow.playbackInfo = updatedInfo
self.floatingWindow = floatingWindow
let showFloatingWindow = { [weak self] in
guard let self = self else { return }
let showFloatingWindow = {
floatingWindow.show(in: window)
player.setPlayView(floatingWindow.contentView)
}
......@@ -290,7 +442,12 @@ class YHPlayerManager: NSObject {
let player = player(for: playerType)
player.setPlayView(view)
if let url = playbackInfo.url {
// 加入频道
if let token = playbackInfo.token,
let channelId = playbackInfo.channelId, let uid = playbackInfo.uid, !token.isEmpty, !channelId.isEmpty {
joinChannel(for: player, token: token, channelId: channelId, uid: uid)
} else if let url = playbackInfo.url, !url.isEmpty {
player.play(url: url, title: playbackInfo.title)
}
}
......@@ -305,50 +462,12 @@ class YHPlayerManager: NSObject {
playerVC.transitioningDelegate = self
transitionSourceView = sourceView
if let topVC = UIApplication.shared.keyWindow?.rootViewController?.topMostViewController() {
if let topVC = UIApplication.shared.yhKeyWindow()?.rootViewController?.topMostViewController() {
topVC.present(playerVC, animated: true) { [weak self] in
self?.transitionSourceView = nil
}
}
}
// MARK: - Resource Management
func cleanupOnExit() {
// 停止所有播放
activePlayers.forEach { $0.value.stop() }
// 释放副播放器
releasePlayer(.secondary)
// 清理播放信息
currentPlaybackInfo.removeAll()
floatingWindow?.dismiss()
floatingWindow = nil
// 重置主播放器
if let mainPlayer = activePlayers[.main] {
mainPlayer.reset()
}
}
deinit {
activePlayers.forEach { $0.value.releasePlayer() }
activePlayers.removeAll()
AgoraRtcEngineKit.destroy()
}
}
// MARK: - AgoraRtcEngineDelegate
extension YHPlayerManager: AgoraRtcEngineDelegate {
func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) {
printLog("AgoraRtcEngine Warning: \(warningCode.rawValue)")
}
func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) {
printLog("AgoraRtcEngine Error: \(errorCode.rawValue)")
}
}
// MARK: - AgoraRtcMediaPlayerDelegate
......@@ -370,13 +489,18 @@ extension YHPlayerManager: AgoraRtcMediaPlayerDelegate {
}
func AgoraRtcMediaPlayer(_ playerKit: AgoraRtcMediaPlayerProtocol,
didReceiveVideoSize size: CGSize) {
infoUpdated info: AgoraMediaPlayerUpdatedInfo) {
// 获取视频尺寸信息
let videoWidth = info.videoWidth
let videoHeight = info.videoHeight
let videoSize = CGSize(width: CGFloat(videoWidth), height: CGFloat(videoHeight))
if let player = activePlayers.values.first(where: { $0.playerKit === playerKit }) {
player.delegate?.player(player, didReceiveVideoSize: size)
player.delegate?.player(player, didReceiveVideoSize: videoSize)
}
if floatingWindow?.player?.playerKit === playerKit {
floatingWindow?.setVideoSize(size)
floatingWindow?.setVideoSize(videoSize)
}
}
}
......@@ -405,8 +529,9 @@ extension YHPlayerManager: YHFloatingWindowDelegate {
}
let player = player(for: playerType)
player.stop()
//player.stop()
floatingWindow = nil
leaveChannel(for: player)
}
func floatingWindow(_ window: YHFloatingWindow, didChangeSize size: CGSize) {
......
......@@ -14,7 +14,6 @@ class YHSimpleAudienceVC: UIViewController {
private var agoraKit: AgoraRtcEngineKit!
private var isJoined: Bool = false
private var remoteView: UIView!
// private var channelName: String = "1732950381844975000"
private let viewModel = YHLiveSalesViewModel()
private let liveId: Int = 40
......
......@@ -14,15 +14,25 @@ class YHVODPlayerViewController: YHBasePlayerViewController {
// MARK: - Properties
private let vodId: Int
var startPosition: Int = 0
//private let viewModel = YHVideoViewModel()
private let viewModel = YHLiveSalesViewModel()
private lazy var dropdownView: YHCategoryDropdownView = {
let view = YHCategoryDropdownView()
view.onSelect = { category in
print("Selected: \(category)")
}
return view
}()
// MARK: - Initialization
init(id: Int, url: String? = nil, title: String? = nil) {
self.vodId = id
super.init(nibName: nil, bundle: nil)
player?.delegate = self
currentPlayingURL = url
currentVideoTitle = title
if let url = url {
//play(url: url, title: title)
play(url: url, title: title)
}
}
......@@ -30,34 +40,61 @@ class YHVODPlayerViewController: YHBasePlayerViewController {
fatalError("init(coder:) has not been implemented")
}
func play(url: String, title: String? = nil) {
currentPlayingURL = url
currentVideoTitle = title
controlView.setTitle(title ?? "")
YHPlayerManager.shared.play(url: url, inView: playerView, title: title)
}
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
//setupUI()
loadVideoDetail()
controlView.isHidden = true
}
// MARK: - SetupView
private func setupUI() {
containerView.addSubview(dropdownView)
dropdownView.snp.makeConstraints { make in
make.top.equalTo(topBarView.snp.bottom).offset(24)
make.left.equalToSuperview().offset(16)
make.width.equalTo(56)
}
}
// MARK: - Data Loading
private func loadVideoDetail() {
// viewModel.getVideoDetail(videoId: vodId) { [weak self] videoDetail, error in
// guard let self = self else { return }
//
// if let videoDetail = videoDetail {
// self.handleVideoDetailSuccess(videoDetail)
// } else {
// printLog("YHVODPlayerViewController: 请求失败")
// if let errorMsg = error?.errorMsg, !errorMsg.isEmpty {
// YHHUD.flash(message: errorMsg)
// }
// }
// }
viewModel.getRecordedDetail(id: vodId) { [weak self] recordedDetail, error in
guard let self = self else { return }
if let recordedDetail = recordedDetail {
self.handleVideoDetailSuccess(recordedDetail)
} else {
printLog("YHVODPlayerViewController: 请求失败")
if let errorMsg = error?.errorMsg, !errorMsg.isEmpty {
YHHUD.flash(message: errorMsg)
}
}
}
}
// private func handleVideoDetailSuccess(_ detail: YHVideoDetailModel) {
// // 如果没有预设URL,使用接口返回的URL播放
// if currentPlayingURL == nil {
// play(url: detail.playUrl, title: detail.title)
// }
// }
private func handleVideoDetailSuccess(_ detail: YHRecordedDetailModel) {
// 更新顶部栏信息
topBarView.setupTopBarView(
headUrl: detail.avatar,
nickname: detail.account,
count: detail.access_num
)
// 如果没有预设URL,使用接口返回的URL播放
if currentPlayingURL == nil {
play(url: detail.recorded_url, title: nil)
}
dropdownView.configure(with: detail.recordedVideoCate.compactMap { $0.name })
}
}
// MARK: - YHPlayerDelegate
......
......@@ -9,6 +9,19 @@
import HyphenateChat
import UIKit
enum YHChatRoomCustomEvent: String {
// 直播开始
case liveStart = "chatRoomCustomEventLiveStart"
// 直播结束
case liveEnd = "chatRoomCustomEventLiveEnd"
// 直播暂停
case livePause = "chatRoomCustomEventLivePause"
// 直播恢复
case liveResume = "chatRoomCustomEventLiveResume"
// 直播商品刷新
case liveGoodsRefresh = "chatRoomCustomEventLiveGoodsRefresh"
}
class YHIMHelper: NSObject {
static let didLoginEaseIMSuccess = Notification.Name("com.YHIMHelper.didLoginEaseIMSuccess")
static let didLogOutEaseIM = Notification.Name("com.YHIMHelper.didLogOutEaseIM")
......
......@@ -18,6 +18,8 @@ class YHLiveDetailModel: SmartCodable {
var tips: String = ""
// 1:直播中 2:未直播 0:未知状态 3:结束直播
var status: Int = 0
// 1:正常 2:播放中 3:禁推---(当status==1才监测,3代表离开了)
var stream_status: Int = 0
var roomId: String = ""
var pullUrl: String = ""
var goods: [YHLiveGoodsItem] = []
......@@ -37,13 +39,29 @@ class YHLiveDetailModel: SmartCodable {
var pull_sd1_url: String = ""
// 拉流地址720p
var pull_hd_url: String = ""
// 1:直播中 2:未直播 0:未知状态 3:结束直播
var stream_status: Int = 0
// 实际开始时间
var actual_start_time: String = ""
// 实际结束时间
var actual_end_time: String = ""
func getLiveState() -> YHLiveState {
switch status {
case 0:
return .onLive
case 1:
if stream_status == 3 {
return .stop
}
return .onLive
case 2:
return .start
case 3:
return .end
default:
return .onLive
}
}
required init() {
}
}
......
//
// YHCategoryDropdownView.swift
// galaxy
//
// Created by alexzzw on 2024/12/4.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import UIKit
class YHCategoryDropdownView: UIView {
// MARK: - UI Components
private lazy var mainButton: UIButton = {
let button = UIButton(type: .custom)
button.backgroundColor = UIColor(white: 0, alpha: 0.5)
button.layer.cornerRadius = 4
// 设置箭头图标
let image = UIImage(named: "icon_arrow_down")
button.setImage(image, for: .normal)
button.tintColor = .white
button.addTarget(self, action: #selector(toggleDropdown), for: .touchUpInside)
return button
}()
private lazy var dropdownTableView: UITableView = {
let tableView = UITableView()
tableView.backgroundColor = UIColor(white: 0, alpha: 0.5)
tableView.layer.cornerRadius = 4
tableView.separatorStyle = .none
tableView.isScrollEnabled = false
tableView.register(YHDropCategoryCell.self, forCellReuseIdentifier: "YHDropCategoryCell")
tableView.delegate = self
tableView.dataSource = self
return tableView
}()
// MARK: - Properties
private var categories: [String] = []
private var isExpanded = false
private var selectedIndex = 0
var onSelect: ((String) -> Void)?
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - UI Setup
private func setupUI() {
addSubview(mainButton)
addSubview(dropdownTableView)
mainButton.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.height.equalTo(36)
}
dropdownTableView.snp.makeConstraints { make in
make.top.equalTo(mainButton.snp.bottom).offset(1)
make.left.right.equalTo(mainButton)
make.height.equalTo(0)
}
dropdownTableView.isHidden = true
}
// MARK: - Public Methods
func configure(with categories: [String]) {
self.categories = categories
dropdownTableView.reloadData()
}
// MARK: - Private Methods
@objc private func toggleDropdown() {
isExpanded.toggle()
let tableHeight = CGFloat(categories.count) * 36
// 更新箭头方向
UIView.animate(withDuration: 0.3) {
self.mainButton.imageView?.transform = self.isExpanded ?
CGAffineTransform(rotationAngle: .pi) : .identity
}
// 展开/收起动画
dropdownTableView.isHidden = false
dropdownTableView.snp.updateConstraints { make in
make.height.equalTo(self.isExpanded ? tableHeight : 0)
}
UIView.animate(withDuration: 0.3, animations: {
self.layoutIfNeeded()
self.dropdownTableView.alpha = self.isExpanded ? 1 : 0
}) { _ in
self.dropdownTableView.isHidden = !self.isExpanded
}
}
}
// MARK: - UITableViewDelegate & DataSource
extension YHCategoryDropdownView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categories.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YHDropCategoryCell", for: indexPath) as! YHDropCategoryCell
cell.titleLabel.text = categories[indexPath.row]
cell.isSelected = indexPath.row == selectedIndex
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 36
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedIndex = indexPath.row
onSelect?(categories[indexPath.row])
toggleDropdown()
tableView.reloadData()
}
}
// MARK: - CategoryCell
class YHDropCategoryCell: UITableViewCell {
let titleLabel: UILabel = {
let label = UILabel()
label.textColor = .white
label.font = .systemFont(ofSize: 14)
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupUI() {
backgroundColor = .clear
selectionStyle = .none
contentView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12)
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-12)
}
}
override var isSelected: Bool {
didSet {
backgroundColor = isSelected ? UIColor(white: 1, alpha: 0.1) : .clear
}
}
}
......@@ -36,7 +36,7 @@ class YHInputBottomBar: UIView {
private lazy var giftButton: UIButton = {
let button = UIButton(type: .custom)
button.setBackgroundImage(UIImage(named: "live_room_msg_gift"), for: .normal)
button.setTitle("99+", for: .normal)
button.setTitle("0", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = .PFSC_M(ofSize: 10)
button.addTarget(self, action: #selector(giftButtonTapped), for: .touchUpInside)
......
......@@ -10,23 +10,19 @@ import UIKit
import AttributedString
class YHLiveShopView: UIView {
var backDate: ((Int) -> Void)?
var closeEvent: (() -> Void)?
var backData: ((Int) -> Void)?
var centerView: UIView!
var titleLabel: UILabel!
var subTitleLabel: UILabel!
var closeButton: UIButton!
var lineView: UIView!
var tableView: UITableView!
var dataSource: [YHWorkExperienceFileModel] = []
var orderID: Int = 0 {
var dataSource: [YHLiveGoodsItem] = [] {
didSet {
self.viewModel.requestFileList(self.orderID) {[weak self] success, error in
guard let self = self else { return }
self.dataSource = self.viewModel.fileList
self.tableView.reloadData()
}
}
}
var viewModel = YHWorkExperienceViewModel()
var title: String = "" {
didSet {
......@@ -145,15 +141,17 @@ class YHLiveShopView: UIView {
dismiss()
}
static func show(callBack: @escaping ((Int) -> Void)) {
static func show(callBack: @escaping ((Int) -> Void)) -> YHLiveShopView {
let view = YHLiveShopView(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: KScreenHeight))
view.backDate = callBack
view.backData = callBack
let window = UIApplication.shared.yhKeyWindow()
window?.addSubview(view)
return view
}
@objc func dismiss() {
removeFromSuperview()
closeEvent?()
}
}
......@@ -168,11 +166,16 @@ extension YHLiveShopView: UIGestureRecognizerDelegate {
extension YHLiveShopView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
return dataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard dataSource.count > indexPath.row else {
return UITableViewCell()
}
let model = dataSource[indexPath.row]
let cell = tableView.dequeueReusableCell(withClass: YHLiveShopViewCell.self)
cell.dataSource = model
return cell
}
......@@ -197,6 +200,14 @@ extension YHLiveShopView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.01
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
guard dataSource.count > indexPath.row else {
return
}
backData?(indexPath.row)
}
}
class YHLiveShopViewCell: UITableViewCell {
......@@ -209,9 +220,20 @@ class YHLiveShopViewCell: UITableViewCell {
var buyButton: UIButton!
var addButton: UIButton!
var dataSource: Int = 0 {
var dataSource: YHLiveGoodsItem = YHLiveGoodsItem() {
didSet {
if let url = URL(string: dataSource.image) {
centerImageView.kf.setImage(with: url, placeholder: UIImage(named: "global_default_image"))
} else {
centerImageView.image = UIImage(named: "global_default_image")
}
titleLabel.text = dataSource.name
messageLabel.text = dataSource.description
let a: ASAttributedString = .init("¥", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor.mainTextColor))
let b: ASAttributedString = .init("\(dataSource.linePrice)", .font(UIFont.PFSC_R(ofSize: 20)),.foreground(UIColor.mainTextColor))
priceLabel.attributed.text = a + b
let c: ASAttributedString = .init("\(dataSource.price)", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
subPriceLabel.attributed.text = c
}
}
override func awakeFromNib() {
......@@ -251,7 +273,7 @@ class YHLiveShopViewCell: UITableViewCell {
titleLabel = {
let view = UILabel()
view.text = "高才A香港企明星(7)"
//view.text = "高才A香港企明星(7)"
view.font = UIFont.PFSC_M(ofSize: 17)
view.textColor = UIColor.mainTextColor
view.numberOfLines = 2
......@@ -267,7 +289,7 @@ class YHLiveShopViewCell: UITableViewCell {
messageLabel = {
let view = UILabel()
view.text = "高才A香港企明星(7)"
//view.text = "高才A香港企明星(7)"
view.font = UIFont.PFSC_M(ofSize: 13)
view.textColor = UIColor(hex: 0x6d788a)
view.numberOfLines = 2
......@@ -283,10 +305,9 @@ class YHLiveShopViewCell: UITableViewCell {
priceLabel = {
let view = UILabel()
let a: ASAttributedString = .init("¥", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor.mainTextColor))
let b: ASAttributedString = .init("61000", .font(UIFont.PFSC_R(ofSize: 20)),.foreground(UIColor.mainTextColor))
// let c: ASAttributedString = .init("¥61000", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
view.attributed.text = a + b
// let a: ASAttributedString = .init("¥", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor.mainTextColor))
// let b: ASAttributedString = .init("61000", .font(UIFont.PFSC_R(ofSize: 20)),.foreground(UIColor.mainTextColor))
// view.attributed.text = a + b
return view
}()
contentView.addSubview(priceLabel)
......@@ -299,8 +320,8 @@ class YHLiveShopViewCell: UITableViewCell {
subPriceLabel = {
let view = UILabel()
let c: ASAttributedString = .init("¥61000", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
view.attributed.text = c
// let c: ASAttributedString = .init("¥61000", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
// view.attributed.text = c
return view
}()
contentView.addSubview(subPriceLabel)
......@@ -363,10 +384,10 @@ class YHLiveShopViewCell: UITableViewCell {
}
@objc func add() {
YHHUD.flash(message: "已加入购物车")
//YHHUD.flash(message: "已加入购物车")
}
@objc func buy() {
YHHUD.flash(message: "已买")
//YHHUD.flash(message: "已买")
}
}
......@@ -236,7 +236,7 @@ class YHPlayerControlView: UIView {
// MARK: - Public Methods
func updatePlayButton(isPlaying: Bool) {
playButton.isSelected = isPlaying
//playButton.isSelected = isPlaying
}
func updateProgress(_ progress: Float, currentTime: String, totalTime: String) {
......
......@@ -33,7 +33,7 @@ class YHPlayerTopBarView: UIView {
private lazy var infoNameLabel: UILabel = {
let label = UILabel()
label.text = "优才E老师名字太长长况..."
label.text = "-"
label.textColor = .white
label.font = .PFSC_M(ofSize: 14)
return label
......@@ -41,7 +41,7 @@ class YHPlayerTopBarView: UIView {
private lazy var infoCountLabel: UILabel = {
let label = UILabel()
label.text = "865人来过"
label.text = "-"
label.textColor = .white.withAlphaComponent(0.7)
label.font = .PFSC_R(ofSize: 10)
return label
......
......@@ -35,7 +35,7 @@ enum YHPersonalModuleItemType: Int {
case privaceAgreement//隐私协议
case myOrder //我的订单 双十一订单入口
case liveEntryTest //直播入口
//case liveEntryTest //直播入口
}
class PersonalModuleItem {
......@@ -103,12 +103,11 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget {
let vc = YHMySettingViewController()
self.navigationController?.pushViewController(vc)
// let url = "https://pull-flv-l13.douyincdn.com/stage/stream-116307521507688888_ld5.flv?expire=1733728207&sign=cef0df720ef0dbe3126675d72dcacec2&major_anchor_level=common&abr_pts=-800&_session_id=037-2024120215100750CB84D802B8201D3D81.1733123408338.51633&rsi=1"
// let url = "https://pull-flv-f1-admin.douyincdn.com/thirdgame/stream-7443723341506054922_md.flv?keeptime=00093a80&wsSecret=cf2c048a5bceb7669e37b229e807c0e2&wsTime=674d82e7&major_anchor_level=common&abr_pts=-800&select_mode=score&_session_id=037-2024120217503167B9DF9F03DF6401DE50.1733133032147.26047&rsi=1"
// let playbackInfo = YHPlayerManager.PlaybackInfo(id: 40, url: url, isLive: true, scene: .fullscreen)
// YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo)
// let playbackInfo = YHPlayerManager.PlaybackInfo(id: 1, isLive: false, scene: .fullscreen)
// YHPlayerManager.shared.enterVOD(from: nil, playbackInfo: playbackInfo)
}
view.evaluateBlock = {
......@@ -331,8 +330,8 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget {
}
let item = PersonalModuleItem(icon: "mine_item_about_us", title: "直播测试入口".local, type: .liveEntryTest)
items.append(item)
// let item = PersonalModuleItem(icon: "mine_item_about_us", title: "直播测试入口".local, type: .liveEntryTest)
// items.append(item)
......@@ -439,9 +438,9 @@ extension YHMyViewController : UITableViewDelegate, UITableViewDataSource {
vc.isSupportWebviewInterBackFlag = true
UIViewController.current?.navigationController?.pushViewController(vc)
}
case .liveEntryTest:
let vc = YHSimpleAudienceVC()
self.navigationController?.pushViewController(vc) //for test hjl
// case .liveEntryTest:
// let vc = YHSimpleAudienceVC()
// self.navigationController?.pushViewController(vc) //for test hjl
default:
printLog("不需要响应")
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment