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

直播流程更改

parent 771b73e1
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
04129E862CD0C8490072F87B /* YHAliYunLogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04129E852CD0C8490072F87B /* YHAliYunLogManager.swift */; }; 04129E862CD0C8490072F87B /* YHAliYunLogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04129E852CD0C8490072F87B /* YHAliYunLogManager.swift */; };
041390692C1081FA0098CB8A /* YHFileListEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041390682C1081FA0098CB8A /* YHFileListEmptyView.swift */; }; 041390692C1081FA0098CB8A /* YHFileListEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041390682C1081FA0098CB8A /* YHFileListEmptyView.swift */; };
0413A9AD2CFB086A00304BC6 /* YHSimpleAudienceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0413A9AC2CFB086A00304BC6 /* YHSimpleAudienceVC.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 */; }; 0414708B2C88627B00B7B688 /* YHButlerServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0414708A2C88627B00B7B688 /* YHButlerServiceManager.swift */; };
0414708E2C895A9300B7B688 /* YHButlerServiceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0414708D2C895A9300B7B688 /* YHButlerServiceViewModel.swift */; }; 0414708E2C895A9300B7B688 /* YHButlerServiceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0414708D2C895A9300B7B688 /* YHButlerServiceViewModel.swift */; };
041470922C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041470912C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift */; }; 041470922C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041470912C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift */; };
...@@ -1110,6 +1112,8 @@ ...@@ -1110,6 +1112,8 @@
04129E852CD0C8490072F87B /* YHAliYunLogManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHAliYunLogManager.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 041470912C898EB700B7B688 /* YHGalaxyManagerTipsItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGalaxyManagerTipsItemView.swift; sourceTree = "<group>"; };
...@@ -2977,6 +2981,7 @@ ...@@ -2977,6 +2981,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
04564D792CF8CEF0004456E4 /* YHPlayerManager.swift */, 04564D792CF8CEF0004456E4 /* YHPlayerManager.swift */,
0413A9AE2CFE2C8200304BC6 /* YHMainChannelDelegate.swift */,
04564D482CF385D9004456E4 /* YHBasePlayerViewController.swift */, 04564D482CF385D9004456E4 /* YHBasePlayerViewController.swift */,
04564D4A2CF389DD004456E4 /* YHLivePlayerViewController.swift */, 04564D4A2CF389DD004456E4 /* YHLivePlayerViewController.swift */,
04564D6B2CF6C414004456E4 /* YHLivePlayerViewController+Api.swift */, 04564D6B2CF6C414004456E4 /* YHLivePlayerViewController+Api.swift */,
...@@ -3003,6 +3008,7 @@ ...@@ -3003,6 +3008,7 @@
04564D7D2CF8D03D004456E4 /* YHFloatingWindow.swift */, 04564D7D2CF8D03D004456E4 /* YHFloatingWindow.swift */,
04013E412CFADF6B001A8E40 /* YHShareAlertView.swift */, 04013E412CFADF6B001A8E40 /* YHShareAlertView.swift */,
04013E452CFDA9AD001A8E40 /* YHLiveShopView.swift */, 04013E452CFDA9AD001A8E40 /* YHLiveShopView.swift */,
0413A9B02CFFDB9A00304BC6 /* YHCategoryDropdownView.swift */,
); );
path = V; path = V;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -6666,6 +6672,7 @@ ...@@ -6666,6 +6672,7 @@
04256E172C75BD2700A37BA4 /* YHVisaPaymentTipsCell.swift in Sources */, 04256E172C75BD2700A37BA4 /* YHVisaPaymentTipsCell.swift in Sources */,
045EEEAA2B9F171A0022A143 /* YHWorkExampleViewController.swift in Sources */, 045EEEAA2B9F171A0022A143 /* YHWorkExampleViewController.swift in Sources */,
04256E1F2C7618A800A37BA4 /* YHAppointWarmTipsCell.swift in Sources */, 04256E1F2C7618A800A37BA4 /* YHAppointWarmTipsCell.swift in Sources */,
0413A9B12CFFDB9A00304BC6 /* YHCategoryDropdownView.swift in Sources */,
04256E132C75BD2700A37BA4 /* YHPayMemberContentItems.swift in Sources */, 04256E132C75BD2700A37BA4 /* YHPayMemberContentItems.swift in Sources */,
A5FD63C12B62616D00D1D9DA /* YHInformationPerfectModel.swift in Sources */, A5FD63C12B62616D00D1D9DA /* YHInformationPerfectModel.swift in Sources */,
044F395C2CB8D58A007CA277 /* YHVisaRenewalPayInfoBaseCell.swift in Sources */, 044F395C2CB8D58A007CA277 /* YHVisaRenewalPayInfoBaseCell.swift in Sources */,
...@@ -6818,6 +6825,7 @@ ...@@ -6818,6 +6825,7 @@
04FD85742C219CFD00BEF9C5 /* YHMatchResultListViewController.swift in Sources */, 04FD85742C219CFD00BEF9C5 /* YHMatchResultListViewController.swift in Sources */,
045EEEB72B9F171A0022A143 /* YHWorkItemAddView.swift in Sources */, 045EEEB72B9F171A0022A143 /* YHWorkItemAddView.swift in Sources */,
0430E65C2C744187000511E2 /* YHAdopterCardModel.swift in Sources */, 0430E65C2C744187000511E2 /* YHAdopterCardModel.swift in Sources */,
0413A9AF2CFE2C8200304BC6 /* YHMainChannelDelegate.swift in Sources */,
04358E0E2C78395200811928 /* YHHKPlaceInfoCell.swift in Sources */, 04358E0E2C78395200811928 /* YHHKPlaceInfoCell.swift in Sources */,
A5ACE9372B4564F7002C94D2 /* YHBaseUrlManager.swift in Sources */, A5ACE9372B4564F7002C94D2 /* YHBaseUrlManager.swift in Sources */,
04EA230A2BB5172F009DA928 /* YHDocumentPromptTableViewCell.swift in Sources */, 04EA230A2BB5172F009DA928 /* YHDocumentPromptTableViewCell.swift in Sources */,
......
...@@ -277,9 +277,7 @@ extension YHLifeViewController: UICollectionViewDelegate, UICollectionViewDataSo ...@@ -277,9 +277,7 @@ extension YHLifeViewController: UICollectionViewDelegate, UICollectionViewDataSo
return return
} }
let item = self.viewModel.liveArr[indexPath.row] 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 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)
//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)
YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo) YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo)
} }
} }
......
...@@ -141,7 +141,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate { ...@@ -141,7 +141,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// // TODO: - alex测试 // // TODO: - alex测试
// if index == 1 { // if index == 1 {
// let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell // 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) // YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, playbackInfo: playbackInfo)
// return // return
// } // }
...@@ -222,20 +222,20 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate { ...@@ -222,20 +222,20 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// live_type 播放类型:1 展示最新直播,2指定直播,3 指定录播 // live_type 播放类型:1 展示最新直播,2指定直播,3 指定录播
// live_pull_url 直播拉流链接 // live_pull_url 直播拉流链接
// video_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 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) YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, playbackInfo: playbackInfo)
printLog("跳转直播") printLog("跳转直播")
case 101://录播 case 101://录播
printLog("跳转录播") printLog("跳转录播")
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell 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) YHPlayerManager.shared.enterVOD(from: cell?.bannerImagV, playbackInfo: playbackInfo)
case 102://图片直播 case 102://图片直播
printLog("跳转录播") printLog("跳转录播")
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell 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) YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, playbackInfo: playbackInfo)
case 0://0 不需要跳转 case 0://0 不需要跳转
printLog("0 不需要跳转") printLog("0 不需要跳转")
...@@ -271,7 +271,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate { ...@@ -271,7 +271,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// if let cell = cell as? YHHomeBannerCollectionViewCell { // if let cell = cell as? YHHomeBannerCollectionViewCell {
// if index == 1 { // 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) // YHPlayerManager.shared.enterBanner(playbackInfo: playbackInfo, inView: cell.bannerImagV)
// //
// } else { // } else {
......
...@@ -257,8 +257,8 @@ class YHSelectLookTableViewCell: UITableViewCell { ...@@ -257,8 +257,8 @@ class YHSelectLookTableViewCell: UITableViewCell {
flagLabel.isHidden = false flagLabel.isHidden = false
} }
let a: ASAttributedString = .init("¥", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor.mainTextColor)) 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 b: ASAttributedString = .init("\(dataSource.linePrice) ", .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 c: ASAttributedString = .init(\(dataSource.price)", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
self.subTitleLabel.attributed.text = a + b + c self.subTitleLabel.attributed.text = a + b + c
itemView.removeSubviews() itemView.removeSubviews()
var i = 0 var i = 0
......
...@@ -94,7 +94,7 @@ extension YHSelectLookView: UICollectionViewDelegate, UICollectionViewDataSource ...@@ -94,7 +94,7 @@ extension YHSelectLookView: UICollectionViewDelegate, UICollectionViewDataSource
return return
} }
let item = items[indexPath.row] 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) YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo)
} }
} }
......
...@@ -28,7 +28,7 @@ class YHBasePlayerViewController: YHBaseViewController { ...@@ -28,7 +28,7 @@ class YHBasePlayerViewController: YHBaseViewController {
lazy var playerView: UIView = { lazy var playerView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = .clear view.backgroundColor = .black
return view return view
}() }()
...@@ -57,12 +57,18 @@ class YHBasePlayerViewController: YHBaseViewController { ...@@ -57,12 +57,18 @@ class YHBasePlayerViewController: YHBaseViewController {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) 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) { override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated) 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?.invalidate()
controlsAutoHideTimer = nil controlsAutoHideTimer = nil
} }
...@@ -76,12 +82,10 @@ class YHBasePlayerViewController: YHBaseViewController { ...@@ -76,12 +82,10 @@ class YHBasePlayerViewController: YHBaseViewController {
gk_navBarAlpha = 0 gk_navBarAlpha = 0
gk_navigationBar.isHidden = true gk_navigationBar.isHidden = true
view.backgroundColor = .black view.backgroundColor = .black
view.addSubview(containerView) view.addSubview(containerView)
containerView.addSubview(playerView) containerView.addSubview(playerView)
containerView.addSubview(controlView) containerView.addSubview(controlView)
containerView.addSubview(topBarView) containerView.addSubview(topBarView)
setupConstraints() setupConstraints()
} }
......
...@@ -16,7 +16,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -16,7 +16,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
private var roomId: String? private var roomId: String?
private let messageQueue = DispatchQueue(label: "com.livePlayerRoom.messageQueue") private let messageQueue = DispatchQueue(label: "com.livePlayerRoom.messageQueue")
let viewModel = YHLiveSalesViewModel() let viewModel = YHLiveSalesViewModel()
private var goodsListView: YHLiveShopView?
private var isLiveStateOn: Bool = false
private var listMaxWidth: CGFloat { private var listMaxWidth: CGFloat {
return KScreenWidth * 248.0 / 375.0 return KScreenWidth * 248.0 / 375.0
} }
...@@ -43,6 +45,24 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -43,6 +45,24 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
return view 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 // MARK: - Initialization
init(id: Int, url: String? = nil, title: String? = nil, roomId: String? = nil) { init(id: Int, url: String? = nil, title: String? = nil, roomId: String? = nil) {
self.liveId = id self.liveId = id
...@@ -51,9 +71,6 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -51,9 +71,6 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
// 隐藏播控UI // 隐藏播控UI
controlView.isHidden = true controlView.isHidden = true
player?.delegate = self // 设置播放器代理 player?.delegate = self // 设置播放器代理
if let url = url {
play(url: url, title: title)
}
if let roomId = roomId { if let roomId = roomId {
setupChatRoom(roomId: roomId) setupChatRoom(roomId: roomId)
} }
...@@ -66,6 +83,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -66,6 +83,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
// MARK: - Lifecycle // MARK: - Lifecycle
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
modalPresentationStyle = .fullScreen
setupLiveUI() setupLiveUI()
setupLiveNotifications() setupLiveNotifications()
setupData() setupData()
...@@ -97,15 +115,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -97,15 +115,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
} }
topBarView.closeButtonClickEvent = { [weak self] in topBarView.closeButtonClickEvent = { [weak self] in
self?.quitChatRoom() self?.closeLive()
self?.leaveLiveRoom()
YHPlayerManager.shared.stop(type: .main)
if let navigationController = self?.navigationController {
navigationController.popViewController(animated: true)
} else {
self?.dismiss(animated: true)
}
} }
topBarView.zoomButtonClickEvent = { [weak self] in topBarView.zoomButtonClickEvent = { [weak self] in
self?.enterFloating() self?.enterFloating()
} }
...@@ -113,6 +125,33 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -113,6 +125,33 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
topBarView.shareButtonClickEvent = { [weak self] in topBarView.shareButtonClickEvent = { [weak self] in
self?.shareLive() 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() { private func setupData() {
...@@ -131,24 +170,37 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -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( topBarView.setupTopBarView(
headUrl: liveDetail.avatar, headUrl: liveDetail.avatar,
nickname: liveDetail.hxNickname, nickname: liveDetail.hxNickname,
count: liveDetail.access_num count: liveDetail.access_num
) )
playbackInfo?.channelId = liveDetail.rtmp_channel
// 如果没有预设URL,使用接口返回的URL播放 playbackInfo?.token = liveDetail.token
if currentPlayingURL == nil { if needJoinLiveChannel {
play(url: liveDetail.pullUrl) 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 // 如果没有预设roomId,使用接口返回的roomId
if roomId == nil { if roomId == nil, needJoinIMRoom {
roomId = liveDetail.roomId roomId = liveDetail.roomId
setupChatRoom(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) { private func setupChatRoom(roomId: String) {
...@@ -180,6 +232,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -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(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(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 // MARK: - Public Methods
...@@ -194,6 +247,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -194,6 +247,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
guard let playbackInfo = playbackInfo else { guard let playbackInfo = playbackInfo else {
return return
} }
//player?.setPlayViewNull()
YHPlayerManager.shared.enterFloating(from: self, playbackInfo: playbackInfo) YHPlayerManager.shared.enterFloating(from: self, playbackInfo: playbackInfo)
} }
...@@ -243,6 +297,16 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -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() { private func shareLive() {
guard let liveModel = viewModel.liveDetailModel else { guard let liveModel = viewModel.liveDetailModel else {
return return
...@@ -250,6 +314,47 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -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) 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 // MARK: - Message Handling
private func handleMessageInput(text: String, controller: YHMessageInputViewController) { private func handleMessageInput(text: String, controller: YHMessageInputViewController) {
guard checkLogin(), guard checkLogin(),
...@@ -274,7 +379,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -274,7 +379,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
} }
} }
} }
private func appendHistoryMessages(_ newMessages: [EMChatMessage]) { private func appendHistoryMessages(_ newMessages: [EMChatMessage]) {
messageQueue.async { messageQueue.async {
let filterMessages = newMessages.filter { message in let filterMessages = newMessages.filter { message in
...@@ -298,6 +403,17 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -298,6 +403,17 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
} }
// MARK: - Notification Handlers // 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) { @objc private func didChatManagerReceiveMessages(_ note: Notification) {
guard let messages = note.object as? [EMChatMessage], guard let messages = note.object as? [EMChatMessage],
let message = messages.first, let message = messages.first,
...@@ -305,6 +421,40 @@ class YHLivePlayerViewController: YHBasePlayerViewController { ...@@ -305,6 +421,40 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
return return
} }
appendHistoryMessages(messages) 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() { @objc private func didLoginYH() {
......
...@@ -12,9 +12,14 @@ enum YHLiveState: Int { ...@@ -12,9 +12,14 @@ enum YHLiveState: Int {
case start = 0 case start = 0
case stop = 1 case stop = 1
case end = 2 case end = 2
case onLive = 3
} }
class YHLiveStateViewController: YHBaseViewController { class YHLiveStateViewController: YHBaseViewController {
var bgLogoImageView: UIImageView!
var bgView: UIView!
var blurEffect: UIBlurEffect!
var blurView: UIVisualEffectView!
var closeButton: UIButton! var closeButton: UIButton!
var shareButton: UIButton! var shareButton: UIButton!
var logImageView: UIImageView! var logImageView: UIImageView!
...@@ -24,15 +29,62 @@ class YHLiveStateViewController: YHBaseViewController { ...@@ -24,15 +29,62 @@ class YHLiveStateViewController: YHBaseViewController {
var getCodeButton: UIButton! var getCodeButton: UIButton!
var state: YHLiveState = .start var state: YHLiveState = .start
var shareEvent: (() -> Void)?
var closeEvent: (() -> Void)?
var backHomeEvent: (() -> Void)?
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
setView() 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() { 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 = { closeButton = {
let button = UIButton(type: .custom) let button = UIButton(type: .custom)
button.setImage(UIImage(named: "live_close"), for: .normal) button.setImage(UIImage(named: "live_close"), for: .normal)
...@@ -49,7 +101,7 @@ class YHLiveStateViewController: YHBaseViewController { ...@@ -49,7 +101,7 @@ class YHLiveStateViewController: YHBaseViewController {
shareButton = { shareButton = {
let button = UIButton(type: .custom) let button = UIButton(type: .custom)
button.setImage(UIImage(named: "live_share"), for: .normal) 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 return button
}() }()
view.addSubview(shareButton) view.addSubview(shareButton)
...@@ -74,7 +126,7 @@ class YHLiveStateViewController: YHBaseViewController { ...@@ -74,7 +126,7 @@ class YHLiveStateViewController: YHBaseViewController {
loginTitleLabel = { loginTitleLabel = {
let label = UILabel() let label = UILabel()
label.text = "优才E老师" //label.text = "优才E老师"
label.font = UIFont.PFSC_M(ofSize: 16) label.font = UIFont.PFSC_M(ofSize: 16)
label.textColor = UIColor.white label.textColor = UIColor.white
label.textAlignment = .center label.textAlignment = .center
...@@ -151,15 +203,21 @@ class YHLiveStateViewController: YHBaseViewController { ...@@ -151,15 +203,21 @@ class YHLiveStateViewController: YHBaseViewController {
} }
} }
@objc func share() {
shareEvent?()
}
@objc func close() { @objc func close() {
dismiss(animated: true) closeEvent?()
// dismiss(animated: true)
} }
func updateData(_ type: YHLiveState) { func updateData(_ liveDetail: YHLiveDetailModel) {
let type = liveDetail.getLiveState()
switch type { switch type {
case .start: case .start:
loginSubTitleLabel.text = "直播暂未开始" loginSubTitleLabel.text = "直播暂未开始"
messageLabel.text = "预计6月28日18:00开始~" messageLabel.text = "预计\(liveDetail.start_time)开始~"
getCodeButton.isHidden = true getCodeButton.isHidden = true
case .stop: case .stop:
loginSubTitleLabel.text = "主播离开了" loginSubTitleLabel.text = "主播离开了"
...@@ -169,10 +227,12 @@ class YHLiveStateViewController: YHBaseViewController { ...@@ -169,10 +227,12 @@ class YHLiveStateViewController: YHBaseViewController {
loginSubTitleLabel.text = "直播已结束" loginSubTitleLabel.text = "直播已结束"
messageLabel.text = "直播已结束,去首页逛逛吧~" messageLabel.text = "直播已结束,去首页逛逛吧~"
getCodeButton.isHidden = false getCodeButton.isHidden = false
case .onLive:
break
} }
} }
@objc func backHome() { @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 @@ ...@@ -6,6 +6,119 @@
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved. // 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 AgoraRtcKit
import Foundation import Foundation
...@@ -23,35 +136,109 @@ protocol YHPlayerDelegate: AnyObject { ...@@ -23,35 +136,109 @@ protocol YHPlayerDelegate: AnyObject {
// MARK: - 播放器实例封装 // MARK: - 播放器实例封装
class YHPlayer { class YHPlayer {
// 持有一个固定的播放视图
private lazy var playerContentView: UIView = {
let view = UIView()
view.backgroundColor = .black
return view
}()
weak var delegate: YHPlayerDelegate? weak var delegate: YHPlayerDelegate?
let type: YHPlayerType let type: YHPlayerType
var playerKit: AgoraRtcMediaPlayerProtocol? var playerKit: AgoraRtcMediaPlayerProtocol?
weak var agoraKit: AgoraRtcEngineKit?
private(set) var currentURL: String? private(set) var currentURL: String?
weak var currentPlayView: UIView? weak var currentPlayView: UIView?
private(set) var currentTitle: String? 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 { var isMuted: Bool {
get { playerKit?.getMute() ?? false } get { playerKit?.getMute() ?? false }
set { playerKit?.mute(newValue) } set { playerKit?.mute(newValue) }
} }
init(type: YHPlayerType, playerKit: AgoraRtcMediaPlayerProtocol?) { init(type: YHPlayerType, playerKit: AgoraRtcMediaPlayerProtocol?, agoraKit: AgoraRtcEngineKit?) {
self.type = type self.type = type
self.playerKit = playerKit 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?) { func setPlayView(_ view: UIView?) {
// 保存旧的视图用于动画
// let oldView = currentPlayView
// 设置新的视图
currentPlayView = view 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) { func play(url: String, title: String? = nil) {
currentURL = url currentURL = url
currentTitle = title currentTitle = title
lastPlaybackInfo = (url, title) // 保存播放信息
let mediaSource = AgoraMediaSource() let mediaSource = AgoraMediaSource()
mediaSource.url = url mediaSource.url = url
mediaSource.autoPlay = true mediaSource.autoPlay = true
...@@ -63,9 +250,11 @@ class YHPlayer { ...@@ -63,9 +250,11 @@ class YHPlayer {
func stop() { func stop() {
playerKit?.stop() playerKit?.stop()
clearJoinInfo()
currentPlayView = nil currentPlayView = nil
currentURL = nil currentURL = nil
currentTitle = nil currentTitle = nil
// 保留 lastPlaybackInfo 用于恢复
} }
func pause() { func pause() {
...@@ -73,13 +262,39 @@ class YHPlayer { ...@@ -73,13 +262,39 @@ class YHPlayer {
} }
func resume() { func resume() {
playerKit?.play() 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() { func reset() {
stop() stop()
setPlayView(nil) setPlayView(nil)
delegate = nil delegate = nil
lastPlaybackInfo = nil
} }
func releasePlayer() { func releasePlayer() {
...@@ -87,6 +302,8 @@ class YHPlayer { ...@@ -87,6 +302,8 @@ class YHPlayer {
playerKit = nil playerKit = nil
} }
// MARK: - Playback Info
func getPosition() -> Int { func getPosition() -> Int {
return playerKit?.getPosition() ?? 0 return playerKit?.getPosition() ?? 0
} }
...@@ -98,4 +315,35 @@ class YHPlayer { ...@@ -98,4 +315,35 @@ class YHPlayer {
func getPlayState() -> AgoraMediaPlayerState { func getPlayState() -> AgoraMediaPlayerState {
return playerKit?.getPlayerState() ?? .idle 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 { ...@@ -15,25 +15,39 @@ class YHPlayerManager: NSObject {
// MARK: - Types // MARK: - Types
enum PlaybackScene: Int { enum PlaybackScene: Int {
case fullscreen // 直播间/点播页 case fullscreen
case floating // 小窗 case floating
case banner // banner case banner
} }
struct PlaybackInfo: Equatable { struct PlaybackInfo: Equatable {
let id: Int let id: Int
let url: String? var url: String?
let title: String? var title: String?
let roomId: String? var roomId: String?
var token: String?
var channelId: String?
var uid: UInt?
let isLive: Bool let isLive: Bool
var scene: PlaybackScene var scene: PlaybackScene
var playerType: YHPlayerType 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.id = id
self.url = url self.url = url
self.title = title self.title = title
self.roomId = roomId self.roomId = roomId
self.token = token
self.channelId = channelId
self.uid = uid
self.isLive = isLive self.isLive = isLive
self.scene = scene self.scene = scene
playerType = .main playerType = .main
...@@ -48,28 +62,41 @@ class YHPlayerManager: NSObject { ...@@ -48,28 +62,41 @@ class YHPlayerManager: NSObject {
static let shared = YHPlayerManager() 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 activePlayers: [YHPlayerType: YHPlayer] = [:]
private var currentPlaybackInfo: [YHPlayerType: PlaybackInfo] = [:] private var currentPlaybackInfo: [YHPlayerType: PlaybackInfo] = [:]
private var floatingWindow: YHFloatingWindow? private var floatingWindow: YHFloatingWindow?
// 转场动画相关
private var transitionSourceView: UIView? private var transitionSourceView: UIView?
// MARK: - Initialization // MARK: - Initialization
override private init() { override private init() {
super.init() super.init()
setupChannelDelegates()
setupAgoraKit() setupAgoraKit()
} }
private func setupChannelDelegates() {
mainChannelDelegate = YHMainChannelDelegate()
secondaryChannelDelegate = YHSecondaryChannelDelegate()
}
private func setupAgoraKit() { private func setupAgoraKit() {
let config = AgoraRtcEngineConfig() let config = AgoraRtcEngineConfig()
config.appId = YhConstant.AgoraRtcKit.appId config.appId = YhConstant.AgoraRtcKit.appId
config.areaCode = .global
config.channelProfile = .liveBroadcasting config.channelProfile = .liveBroadcasting
agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self) agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: mainChannelDelegate)
// Enable video
agoraKit.enableVideo() 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 // MARK: - Basic Playback Control
...@@ -110,6 +137,32 @@ class YHPlayerManager: NSObject { ...@@ -110,6 +137,32 @@ class YHPlayerManager: NSObject {
return activePlayers[type] 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 // MARK: - Player Management
private func player(for type: YHPlayerType) -> YHPlayer { private func player(for type: YHPlayerType) -> YHPlayer {
...@@ -123,11 +176,14 @@ class YHPlayerManager: NSObject { ...@@ -123,11 +176,14 @@ class YHPlayerManager: NSObject {
} }
private func createPlayer(for type: YHPlayerType) -> YHPlayer { private func createPlayer(for type: YHPlayerType) -> YHPlayer {
guard let playerKit = agoraKit.createMediaPlayer(with: self) else { let playerKit = agoraKit.createMediaPlayer(with: self)
//fatalError("Failed to create media player") let player = YHPlayer(type: type, playerKit: playerKit, agoraKit: agoraKit)
return YHPlayer(type: type, playerKit: nil) // 设置对应的 delegate
if type == .main {
mainChannelDelegate?.player = player
} else {
secondaryChannelDelegate?.player = player
} }
let player = YHPlayer(type: type, playerKit: playerKit)
return player return player
} }
...@@ -147,6 +203,65 @@ class YHPlayerManager: NSObject { ...@@ -147,6 +203,65 @@ class YHPlayerManager: NSObject {
return .main return .main
} }
} }
// 加入频道的逻辑移到 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 // MARK: - Scene Management
...@@ -161,7 +276,7 @@ class YHPlayerManager: NSObject { ...@@ -161,7 +276,7 @@ class YHPlayerManager: NSObject {
if playbackInfo.scene == .banner, if playbackInfo.scene == .banner,
let bannerPlayer = activePlayers[.secondary] { let bannerPlayer = activePlayers[.secondary] {
startPosition = bannerPlayer.getPosition() startPosition = bannerPlayer.getPosition()
releasePlayer(.secondary) bannerPlayer.stop()
} }
let playerVC = YHVODPlayerViewController(id: playbackInfo.id, url: playbackInfo.url, title: playbackInfo.title) let playerVC = YHVODPlayerViewController(id: playbackInfo.id, url: playbackInfo.url, title: playbackInfo.title)
...@@ -176,6 +291,10 @@ class YHPlayerManager: NSObject { ...@@ -176,6 +291,10 @@ class YHPlayerManager: NSObject {
// 关闭小窗 // 关闭小窗
exitFloating() exitFloating()
if let url = playbackInfo.url {
player.play(url: url, title: playbackInfo.title)
}
present(playerVC, from: sourceView) present(playerVC, from: sourceView)
} }
...@@ -187,10 +306,14 @@ class YHPlayerManager: NSObject { ...@@ -187,10 +306,14 @@ class YHPlayerManager: NSObject {
// 如果是从banner跳转,释放副播放器 // 如果是从banner跳转,释放副播放器
if playbackInfo.scene == .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 currentPlaybackInfo[playerType] = updatedInfo
let player = player(for: playerType) let player = player(for: playerType)
...@@ -201,24 +324,55 @@ class YHPlayerManager: NSObject { ...@@ -201,24 +324,55 @@ class YHPlayerManager: NSObject {
// 关闭小窗 // 关闭小窗
exitFloating() 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) { 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 playerType = determinePlayerType(for: .floating)
let player = player(for: playerType) let player: YHPlayer// = player(for: playerType)
var updatedInfo = playbackInfo var updatedInfo = playbackInfo
updatedInfo.scene = .floating updatedInfo.scene = .floating
updatedInfo.playerType = playerType updatedInfo.playerType = playerType
currentPlaybackInfo[playerType] = updatedInfo currentPlaybackInfo[playerType] = updatedInfo
if let url = playbackInfo.url { // 检查是否存在当前播放器
player.play(url: url, title: playbackInfo.title) 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, if let sourceView = player.currentPlayView,
let sourceSuperview = sourceView.superview { let sourceSuperview = sourceView.superview {
...@@ -240,8 +394,7 @@ class YHPlayerManager: NSObject { ...@@ -240,8 +394,7 @@ class YHPlayerManager: NSObject {
let targetFrame = floatingWindow.calculateInitialFrame() let targetFrame = floatingWindow.calculateInitialFrame()
// 执行动画 // 执行动画
let showFloatingWindow = { [weak self] in let showFloatingWindow = {
guard let self = self else { return }
UIView.animate(withDuration: 0.3, animations: { UIView.animate(withDuration: 0.3, animations: {
snapshotView.frame = targetFrame snapshotView.frame = targetFrame
}, completion: { _ in }, completion: { _ in
...@@ -265,8 +418,7 @@ class YHPlayerManager: NSObject { ...@@ -265,8 +418,7 @@ class YHPlayerManager: NSObject {
floatingWindow.playbackInfo = updatedInfo floatingWindow.playbackInfo = updatedInfo
self.floatingWindow = floatingWindow self.floatingWindow = floatingWindow
let showFloatingWindow = { [weak self] in let showFloatingWindow = {
guard let self = self else { return }
floatingWindow.show(in: window) floatingWindow.show(in: window)
player.setPlayView(floatingWindow.contentView) player.setPlayView(floatingWindow.contentView)
} }
...@@ -290,7 +442,12 @@ class YHPlayerManager: NSObject { ...@@ -290,7 +442,12 @@ class YHPlayerManager: NSObject {
let player = player(for: playerType) let player = player(for: playerType)
player.setPlayView(view) 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) player.play(url: url, title: playbackInfo.title)
} }
} }
...@@ -305,50 +462,12 @@ class YHPlayerManager: NSObject { ...@@ -305,50 +462,12 @@ class YHPlayerManager: NSObject {
playerVC.transitioningDelegate = self playerVC.transitioningDelegate = self
transitionSourceView = sourceView 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 topVC.present(playerVC, animated: true) { [weak self] in
self?.transitionSourceView = nil 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 // MARK: - AgoraRtcMediaPlayerDelegate
...@@ -370,13 +489,18 @@ extension YHPlayerManager: AgoraRtcMediaPlayerDelegate { ...@@ -370,13 +489,18 @@ extension YHPlayerManager: AgoraRtcMediaPlayerDelegate {
} }
func AgoraRtcMediaPlayer(_ playerKit: AgoraRtcMediaPlayerProtocol, 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 }) { 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 { if floatingWindow?.player?.playerKit === playerKit {
floatingWindow?.setVideoSize(size) floatingWindow?.setVideoSize(videoSize)
} }
} }
} }
...@@ -405,8 +529,9 @@ extension YHPlayerManager: YHFloatingWindowDelegate { ...@@ -405,8 +529,9 @@ extension YHPlayerManager: YHFloatingWindowDelegate {
} }
let player = player(for: playerType) let player = player(for: playerType)
player.stop() //player.stop()
floatingWindow = nil floatingWindow = nil
leaveChannel(for: player)
} }
func floatingWindow(_ window: YHFloatingWindow, didChangeSize size: CGSize) { func floatingWindow(_ window: YHFloatingWindow, didChangeSize size: CGSize) {
......
...@@ -14,7 +14,6 @@ class YHSimpleAudienceVC: UIViewController { ...@@ -14,7 +14,6 @@ class YHSimpleAudienceVC: UIViewController {
private var agoraKit: AgoraRtcEngineKit! private var agoraKit: AgoraRtcEngineKit!
private var isJoined: Bool = false private var isJoined: Bool = false
private var remoteView: UIView! private var remoteView: UIView!
// private var channelName: String = "1732950381844975000"
private let viewModel = YHLiveSalesViewModel() private let viewModel = YHLiveSalesViewModel()
private let liveId: Int = 40 private let liveId: Int = 40
......
...@@ -14,15 +14,25 @@ class YHVODPlayerViewController: YHBasePlayerViewController { ...@@ -14,15 +14,25 @@ class YHVODPlayerViewController: YHBasePlayerViewController {
// MARK: - Properties // MARK: - Properties
private let vodId: Int private let vodId: Int
var startPosition: Int = 0 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 // MARK: - Initialization
init(id: Int, url: String? = nil, title: String? = nil) { init(id: Int, url: String? = nil, title: String? = nil) {
self.vodId = id self.vodId = id
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
player?.delegate = self player?.delegate = self
currentPlayingURL = url
currentVideoTitle = title
if let url = url { if let url = url {
//play(url: url, title: title) play(url: url, title: title)
} }
} }
...@@ -30,34 +40,61 @@ class YHVODPlayerViewController: YHBasePlayerViewController { ...@@ -30,34 +40,61 @@ class YHVODPlayerViewController: YHBasePlayerViewController {
fatalError("init(coder:) has not been implemented") 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 // MARK: - Lifecycle
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
//setupUI()
loadVideoDetail() 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 // MARK: - Data Loading
private func loadVideoDetail() { private func loadVideoDetail() {
// viewModel.getVideoDetail(videoId: vodId) { [weak self] videoDetail, error in viewModel.getRecordedDetail(id: vodId) { [weak self] recordedDetail, error in
// guard let self = self else { return } guard let self = self else { return }
//
// if let videoDetail = videoDetail { if let recordedDetail = recordedDetail {
// self.handleVideoDetailSuccess(videoDetail) self.handleVideoDetailSuccess(recordedDetail)
// } else { } else {
// printLog("YHVODPlayerViewController: 请求失败") printLog("YHVODPlayerViewController: 请求失败")
// if let errorMsg = error?.errorMsg, !errorMsg.isEmpty { if let errorMsg = error?.errorMsg, !errorMsg.isEmpty {
// YHHUD.flash(message: errorMsg) YHHUD.flash(message: errorMsg)
// } }
// } }
// } }
} }
// private func handleVideoDetailSuccess(_ detail: YHVideoDetailModel) { private func handleVideoDetailSuccess(_ detail: YHRecordedDetailModel) {
// // 如果没有预设URL,使用接口返回的URL播放 // 更新顶部栏信息
// if currentPlayingURL == nil { topBarView.setupTopBarView(
// play(url: detail.playUrl, title: detail.title) 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 // MARK: - YHPlayerDelegate
......
...@@ -9,6 +9,19 @@ ...@@ -9,6 +9,19 @@
import HyphenateChat import HyphenateChat
import UIKit import UIKit
enum YHChatRoomCustomEvent: String {
// 直播开始
case liveStart = "chatRoomCustomEventLiveStart"
// 直播结束
case liveEnd = "chatRoomCustomEventLiveEnd"
// 直播暂停
case livePause = "chatRoomCustomEventLivePause"
// 直播恢复
case liveResume = "chatRoomCustomEventLiveResume"
// 直播商品刷新
case liveGoodsRefresh = "chatRoomCustomEventLiveGoodsRefresh"
}
class YHIMHelper: NSObject { class YHIMHelper: NSObject {
static let didLoginEaseIMSuccess = Notification.Name("com.YHIMHelper.didLoginEaseIMSuccess") static let didLoginEaseIMSuccess = Notification.Name("com.YHIMHelper.didLoginEaseIMSuccess")
static let didLogOutEaseIM = Notification.Name("com.YHIMHelper.didLogOutEaseIM") static let didLogOutEaseIM = Notification.Name("com.YHIMHelper.didLogOutEaseIM")
......
...@@ -18,6 +18,8 @@ class YHLiveDetailModel: SmartCodable { ...@@ -18,6 +18,8 @@ class YHLiveDetailModel: SmartCodable {
var tips: String = "" var tips: String = ""
// 1:直播中 2:未直播 0:未知状态 3:结束直播 // 1:直播中 2:未直播 0:未知状态 3:结束直播
var status: Int = 0 var status: Int = 0
// 1:正常 2:播放中 3:禁推---(当status==1才监测,3代表离开了)
var stream_status: Int = 0
var roomId: String = "" var roomId: String = ""
var pullUrl: String = "" var pullUrl: String = ""
var goods: [YHLiveGoodsItem] = [] var goods: [YHLiveGoodsItem] = []
...@@ -37,12 +39,28 @@ class YHLiveDetailModel: SmartCodable { ...@@ -37,12 +39,28 @@ class YHLiveDetailModel: SmartCodable {
var pull_sd1_url: String = "" var pull_sd1_url: String = ""
// 拉流地址720p // 拉流地址720p
var pull_hd_url: String = "" var pull_hd_url: String = ""
// 1:直播中 2:未直播 0:未知状态 3:结束直播
var stream_status: Int = 0
// 实际开始时间 // 实际开始时间
var actual_start_time: String = "" var actual_start_time: String = ""
// 实际结束时间 // 实际结束时间
var actual_end_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() { 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 { ...@@ -36,7 +36,7 @@ class YHInputBottomBar: UIView {
private lazy var giftButton: UIButton = { private lazy var giftButton: UIButton = {
let button = UIButton(type: .custom) let button = UIButton(type: .custom)
button.setBackgroundImage(UIImage(named: "live_room_msg_gift"), for: .normal) 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.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = .PFSC_M(ofSize: 10) button.titleLabel?.font = .PFSC_M(ofSize: 10)
button.addTarget(self, action: #selector(giftButtonTapped), for: .touchUpInside) button.addTarget(self, action: #selector(giftButtonTapped), for: .touchUpInside)
......
...@@ -10,21 +10,17 @@ import UIKit ...@@ -10,21 +10,17 @@ import UIKit
import AttributedString import AttributedString
class YHLiveShopView: UIView { class YHLiveShopView: UIView {
var backDate: ((Int) -> Void)? var closeEvent: (() -> Void)?
var backData: ((Int) -> Void)?
var centerView: UIView! var centerView: UIView!
var titleLabel: UILabel! var titleLabel: UILabel!
var subTitleLabel: UILabel! var subTitleLabel: UILabel!
var closeButton: UIButton! var closeButton: UIButton!
var lineView: UIView! var lineView: UIView!
var tableView: UITableView! var tableView: UITableView!
var dataSource: [YHWorkExperienceFileModel] = [] var dataSource: [YHLiveGoodsItem] = [] {
var orderID: Int = 0 {
didSet { didSet {
self.viewModel.requestFileList(self.orderID) {[weak self] success, error in self.tableView.reloadData()
guard let self = self else { return }
self.dataSource = self.viewModel.fileList
self.tableView.reloadData()
}
} }
} }
var viewModel = YHWorkExperienceViewModel() var viewModel = YHWorkExperienceViewModel()
...@@ -145,15 +141,17 @@ class YHLiveShopView: UIView { ...@@ -145,15 +141,17 @@ class YHLiveShopView: UIView {
dismiss() 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)) let view = YHLiveShopView(frame: CGRect(x: 0, y: 0, width: KScreenWidth, height: KScreenHeight))
view.backDate = callBack view.backData = callBack
let window = UIApplication.shared.yhKeyWindow() let window = UIApplication.shared.yhKeyWindow()
window?.addSubview(view) window?.addSubview(view)
return view
} }
@objc func dismiss() { @objc func dismiss() {
removeFromSuperview() removeFromSuperview()
closeEvent?()
} }
} }
...@@ -168,11 +166,16 @@ extension YHLiveShopView: UIGestureRecognizerDelegate { ...@@ -168,11 +166,16 @@ extension YHLiveShopView: UIGestureRecognizerDelegate {
extension YHLiveShopView: UITableViewDelegate, UITableViewDataSource { extension YHLiveShopView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7 return dataSource.count
} }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 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) let cell = tableView.dequeueReusableCell(withClass: YHLiveShopViewCell.self)
cell.dataSource = model
return cell return cell
} }
...@@ -197,6 +200,14 @@ extension YHLiveShopView: UITableViewDelegate, UITableViewDataSource { ...@@ -197,6 +200,14 @@ extension YHLiveShopView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0.01 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 { class YHLiveShopViewCell: UITableViewCell {
...@@ -209,9 +220,20 @@ class YHLiveShopViewCell: UITableViewCell { ...@@ -209,9 +220,20 @@ class YHLiveShopViewCell: UITableViewCell {
var buyButton: UIButton! var buyButton: UIButton!
var addButton: UIButton! var addButton: UIButton!
var dataSource: Int = 0 { var dataSource: YHLiveGoodsItem = YHLiveGoodsItem() {
didSet { 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() { override func awakeFromNib() {
...@@ -251,7 +273,7 @@ class YHLiveShopViewCell: UITableViewCell { ...@@ -251,7 +273,7 @@ class YHLiveShopViewCell: UITableViewCell {
titleLabel = { titleLabel = {
let view = UILabel() let view = UILabel()
view.text = "高才A香港企明星(7)" //view.text = "高才A香港企明星(7)"
view.font = UIFont.PFSC_M(ofSize: 17) view.font = UIFont.PFSC_M(ofSize: 17)
view.textColor = UIColor.mainTextColor view.textColor = UIColor.mainTextColor
view.numberOfLines = 2 view.numberOfLines = 2
...@@ -267,7 +289,7 @@ class YHLiveShopViewCell: UITableViewCell { ...@@ -267,7 +289,7 @@ class YHLiveShopViewCell: UITableViewCell {
messageLabel = { messageLabel = {
let view = UILabel() let view = UILabel()
view.text = "高才A香港企明星(7)" //view.text = "高才A香港企明星(7)"
view.font = UIFont.PFSC_M(ofSize: 13) view.font = UIFont.PFSC_M(ofSize: 13)
view.textColor = UIColor(hex: 0x6d788a) view.textColor = UIColor(hex: 0x6d788a)
view.numberOfLines = 2 view.numberOfLines = 2
...@@ -283,10 +305,9 @@ class YHLiveShopViewCell: UITableViewCell { ...@@ -283,10 +305,9 @@ class YHLiveShopViewCell: UITableViewCell {
priceLabel = { priceLabel = {
let view = UILabel() let view = UILabel()
let a: ASAttributedString = .init("¥", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor.mainTextColor)) // 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 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
view.attributed.text = a + b
return view return view
}() }()
contentView.addSubview(priceLabel) contentView.addSubview(priceLabel)
...@@ -299,8 +320,8 @@ class YHLiveShopViewCell: UITableViewCell { ...@@ -299,8 +320,8 @@ class YHLiveShopViewCell: UITableViewCell {
subPriceLabel = { subPriceLabel = {
let view = UILabel() let view = UILabel()
let c: ASAttributedString = .init("¥61000", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single)) // let c: ASAttributedString = .init("¥61000", .font(UIFont.PFSC_R(ofSize: 14)),.foreground(UIColor(hex:0x8993a2)), .strikethrough(.single))
view.attributed.text = c // view.attributed.text = c
return view return view
}() }()
contentView.addSubview(subPriceLabel) contentView.addSubview(subPriceLabel)
...@@ -363,10 +384,10 @@ class YHLiveShopViewCell: UITableViewCell { ...@@ -363,10 +384,10 @@ class YHLiveShopViewCell: UITableViewCell {
} }
@objc func add() { @objc func add() {
YHHUD.flash(message: "已加入购物车") //YHHUD.flash(message: "已加入购物车")
} }
@objc func buy() { @objc func buy() {
YHHUD.flash(message: "已买") //YHHUD.flash(message: "已买")
} }
} }
...@@ -236,7 +236,7 @@ class YHPlayerControlView: UIView { ...@@ -236,7 +236,7 @@ class YHPlayerControlView: UIView {
// MARK: - Public Methods // MARK: - Public Methods
func updatePlayButton(isPlaying: Bool) { func updatePlayButton(isPlaying: Bool) {
playButton.isSelected = isPlaying //playButton.isSelected = isPlaying
} }
func updateProgress(_ progress: Float, currentTime: String, totalTime: String) { func updateProgress(_ progress: Float, currentTime: String, totalTime: String) {
......
...@@ -33,7 +33,7 @@ class YHPlayerTopBarView: UIView { ...@@ -33,7 +33,7 @@ class YHPlayerTopBarView: UIView {
private lazy var infoNameLabel: UILabel = { private lazy var infoNameLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.text = "优才E老师名字太长长况..." label.text = "-"
label.textColor = .white label.textColor = .white
label.font = .PFSC_M(ofSize: 14) label.font = .PFSC_M(ofSize: 14)
return label return label
...@@ -41,7 +41,7 @@ class YHPlayerTopBarView: UIView { ...@@ -41,7 +41,7 @@ class YHPlayerTopBarView: UIView {
private lazy var infoCountLabel: UILabel = { private lazy var infoCountLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.text = "865人来过" label.text = "-"
label.textColor = .white.withAlphaComponent(0.7) label.textColor = .white.withAlphaComponent(0.7)
label.font = .PFSC_R(ofSize: 10) label.font = .PFSC_R(ofSize: 10)
return label return label
......
...@@ -35,7 +35,7 @@ enum YHPersonalModuleItemType: Int { ...@@ -35,7 +35,7 @@ enum YHPersonalModuleItemType: Int {
case privaceAgreement//隐私协议 case privaceAgreement//隐私协议
case myOrder //我的订单 双十一订单入口 case myOrder //我的订单 双十一订单入口
case liveEntryTest //直播入口 //case liveEntryTest //直播入口
} }
class PersonalModuleItem { class PersonalModuleItem {
...@@ -103,12 +103,11 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget { ...@@ -103,12 +103,11 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget {
let vc = YHMySettingViewController() let vc = YHMySettingViewController()
self.navigationController?.pushViewController(vc) self.navigationController?.pushViewController(vc)
// 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 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: 40, url: url, isLive: true, scene: .fullscreen) // let playbackInfo = YHPlayerManager.PlaybackInfo(id: 40, url: url, isLive: true, scene: .fullscreen)
// YHPlayerManager.shared.enterLive(from: nil, playbackInfo: playbackInfo) // 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 = { view.evaluateBlock = {
...@@ -331,8 +330,8 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget { ...@@ -331,8 +330,8 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget {
} }
let item = PersonalModuleItem(icon: "mine_item_about_us", title: "直播测试入口".local, type: .liveEntryTest) // let item = PersonalModuleItem(icon: "mine_item_about_us", title: "直播测试入口".local, type: .liveEntryTest)
items.append(item) // items.append(item)
...@@ -439,9 +438,9 @@ extension YHMyViewController : UITableViewDelegate, UITableViewDataSource { ...@@ -439,9 +438,9 @@ extension YHMyViewController : UITableViewDelegate, UITableViewDataSource {
vc.isSupportWebviewInterBackFlag = true vc.isSupportWebviewInterBackFlag = true
UIViewController.current?.navigationController?.pushViewController(vc) UIViewController.current?.navigationController?.pushViewController(vc)
} }
case .liveEntryTest: // case .liveEntryTest:
let vc = YHSimpleAudienceVC() // let vc = YHSimpleAudienceVC()
self.navigationController?.pushViewController(vc) //for test hjl // self.navigationController?.pushViewController(vc) //for test hjl
default: default:
printLog("不需要响应") 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