Commit 8079abe0 authored by Alex朱枝文's avatar Alex朱枝文

增加直播点播入口

parent ce194313
......@@ -273,7 +273,11 @@ extension YHLifeViewController: UICollectionViewDelegate, UICollectionViewDataSo
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//跳转直播 文哥代办
YHShareAlertView.show(image: "http://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960", title: "12344", subMessage: "12213243", linkUrl: "https://www.baidu.com", isLive: true)
guard self.viewModel.liveArr.count > indexPath.row else {
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)
}
}
......
......@@ -24,8 +24,14 @@ class YHHomeBannerView: UIView {
self.indicatorView.curIndicatorIndex = 0
// 指定显示图片为第一个
bannerView.selectItem(at: 0, animated: false)
let noNeedAutoScroll = dataArr.contains(where: {
$0.skip_type == 100 || $0.skip_type == 102
})
// // TODO: - alex测试
// noNeedAutoScroll = true
// // TODO: - alex测试
// 开启定时器开始滚动
bannerView.automaticSlidingInterval = bannerSildingInterval
bannerView.automaticSlidingInterval = noNeedAutoScroll ? 0 : bannerSildingInterval
bannerView.removesInfiniteLoopForSingleItem = true
bannerView.alwaysBounceHorizontal = true
}
......@@ -132,6 +138,13 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
if model.isLocalItemFlag {
return
}
// // TODO: - alex测试
// if index == 1 {
// let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
// YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, id: 23, url: "https://pull-flv-l6.douyincdn.com/stage/stream-116295918585905183.flv?k=e21f1ae1e7591521&t=1733551151&major_anchor_level=common&abr_pts=-800&_session_id=037-202411301359108030CAEAC1F742805E6D.1732946351732.18942&rsi=1", title: nil, roomId: nil, type: .secondary)
// return
// }
// // TODO: - alex测试
if model.skip_url.isEmpty == false {
switch model.skip_type {
case 1: //跳转H5
......@@ -201,6 +214,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
vc.url = model.skip_url
self.parentViewController?.navigationController?.pushViewController(vc)
case 100:// 直播
//文哥
// media_type 投放类型:1 图片,2 直播
// live_id 直播ID
// live_status 直播状态 1:直播中 2:未直播 0:未知状态 3:结束直播
......@@ -208,11 +222,17 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// live_pull_url 直播拉流链接
// video_url 视频链接
// recorded_cate_id 录播分类id
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, id: model.live_id, url: model.live_pull_url, title: nil, roomId: nil, type: .secondary)
printLog("跳转直播")
case 101://录播
printLog("跳转录播")
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
YHPlayerManager.shared.enterVOD(from: cell?.bannerImagV, id: model.live_id, url: model.video_url, title: nil, type: .secondary)
case 102://图片直播
printLog("跳转录播")
let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, id: model.live_id, url: model.live_pull_url, title: nil, roomId: nil, type: .secondary)
case 0://0 不需要跳转
printLog("0 不需要跳转")
default:
......@@ -233,4 +253,58 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
func pagerViewDidEndScrollAnimation(_ pagerView: FSPagerView) {
self.indicatorView.curIndicatorIndex = pagerView.currentIndex
}
func pagerView(_ pagerView: FSPagerView, willDisplay cell: FSPagerViewCell, forItemAt index: Int) {
if index >= dataArr.count {
return
}
let model = dataArr[index]
if model.isLocalItemFlag {
return
}
// // TODO: - alex测试
// if let cell = cell as? YHHomeBannerCollectionViewCell {
// if index == 1 {
// YHPlayerManager.shared.play(url: "https://pull-flv-l11.douyincdn.com/thirdgame/stream-404525958790382412.flv?expire=1733554587&sign=d1e9f927e20f4a3fb4e2dd2a2712e256&major_anchor_level=common&abr_pts=-800&_session_id=037-20241130145626DBDEB00EB11CB388DD95.1732949787574.66743&rsi=1", inView: cell.bannerImagV, title: nil, type: .secondary)
// } else {
// let player = YHPlayerManager.shared.getPlayer(.secondary)
// player?.setPlayView(nil)
// }
// return
// }
// // TODO: - alex测试
if model.skip_url.isEmpty == false {
if let cell = cell as? YHHomeBannerCollectionViewCell {
if model.skip_type == 100 {
YHPlayerManager.shared.play(url: model.live_pull_url, inView: cell.bannerImagV, title: nil, type: .secondary)
} else {
let player = YHPlayerManager.shared.getPlayer(.secondary)
player?.setPlayView(nil)
}
}
}
}
func pagerView(_ pagerView: FSPagerView, didEndDisplaying cell: FSPagerViewCell, forItemAt index: Int) {
if index >= dataArr.count {
return
}
let model = dataArr[index]
if model.isLocalItemFlag {
return
}
// // TODO: - alex测试
// if index == 1 {
// YHPlayerManager.shared.stop(type: .secondary)
// return
// }
// // TODO: - alex测试
if model.skip_url.isEmpty == false {
if model.skip_type == 100 {
YHPlayerManager.shared.stop(type: .secondary)
}
}
}
}
......@@ -90,7 +90,11 @@ extension YHSelectLookView: UICollectionViewDelegate, UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//跳转直播 文哥代办
guard items.count > indexPath.row else {
return
}
let item = items[indexPath.row]
YHPlayerManager.shared.enterLive(from: nil, id: item.id, url: item.pull_url, title: item.live_title, roomId: item.room_id)
}
}
......
......@@ -15,4 +15,16 @@ extension YHLivePlayerViewController {
callback(liveDetail, error)
}
}
func joinLiveRoom(id: Int, callback: @escaping (_ success: Bool, _ error: YHErrorModel?) -> Void) {
viewModel.joinLiveRoom(id: id) { success, error in
callback(success, error)
}
}
func leaveLiveRoom(id: Int, callback: @escaping (_ success: Bool, _ error: YHErrorModel?) -> Void) {
viewModel.leaveLiveRoom(id: id) { success, error in
callback(success, error)
}
}
}
......@@ -69,6 +69,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
setupLiveUI()
setupLiveNotifications()
setupData()
if YHLoginManager.shared.isLogin() {
joinLiveRoom(id: liveId, callback: { _, _ in })
}
}
deinit {
......@@ -95,6 +98,7 @@ 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)
......@@ -105,6 +109,10 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
topBarView.zoomButtonClickEvent = { [weak self] in
self?.enterFloating()
}
topBarView.shareButtonClickEvent = { [weak self] in
self?.shareLive()
}
}
private func setupData() {
......@@ -169,6 +177,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
name: YHIMHelper.didLogOutEaseIM,
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)
}
// MARK: - Public Methods
......@@ -207,6 +218,19 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
}
private func leaveLiveRoom() {
guard YHLoginManager.shared.isLogin() else {
return
}
leaveLiveRoom(id: liveId) { _, error in
if let error = error {
printLog("leaveLiveRoom: \(error)")
} else {
printLog("leaveLiveRoom: success")
}
}
}
private func quitChatRoom() {
guard let roomId = roomId else { return }
......@@ -219,6 +243,13 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
}
private func shareLive() {
guard let liveModel = viewModel.liveDetailModel else {
return
}
YHShareAlertView.show(image: liveModel.live_image, title: "@" + liveModel.account, subMessage: liveModel.live_title, linkUrl: liveModel.live_h5_url, isLive: true)
}
// MARK: - Message Handling
private func handleMessageInput(text: String, controller: YHMessageInputViewController) {
guard checkLogin(),
......@@ -276,6 +307,16 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
appendHistoryMessages(messages)
}
@objc private func didLoginYH() {
if YHLoginManager.shared.isLogin() {
joinLiveRoom(id: liveId, callback: { _, _ in })
}
}
@objc private func didLogOutYH() {
//
}
@objc private func didLoginEaseIMSuccess() {
if let roomId = roomId {
joinChatRoom(roomId: roomId)
......
......@@ -16,10 +16,30 @@ class YHLiveDetailModel: SmartCodable {
var hxUid: String = ""
var access_num: Int = 0
var tips: String = ""
// 1:直播中 2:未直播 0:未知状态 3:结束直播
var status: Int = 0
var roomId: String = ""
var pullUrl: String = ""
var goods: [YHLiveGoodsItem] = []
// 直播封面
var live_image: String = ""
// 直播主题
var live_title: String = ""
// h5直播地址
var live_h5_url: String = ""
// 预计开始时间
var start_time: String = ""
// 拉流地址360p
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 = ""
required init() {
}
......
......@@ -19,16 +19,16 @@ protocol YHFloatingWindowDelegate: AnyObject {
class YHFloatingWindow: NSObject {
// MARK: - Properties
weak var player: YHPlayer?
weak var delegate: YHFloatingWindowDelegate?
var playbackInfo: YHPlayerManager.PlaybackInfo?
// 视频方向
enum VideoOrientation {
case portrait // 竖屏 9:16
case landscape // 横屏 16:9
var aspectRatio: CGFloat {
switch self {
case .portrait: return 9.0 / 16.0
......@@ -36,215 +36,219 @@ class YHFloatingWindow: NSObject {
}
}
}
// 窗口尺寸
private struct Size {
static let minWidth: CGFloat = 120
static let maxWidth: CGFloat = UIScreen.main.bounds.width
static let minHeight: CGFloat = 67.5 // 16:9
static let maxHeight: CGFloat = UIScreen.main.bounds.height
static let defaultWidth: CGFloat = 150
static let defaultHeight: CGFloat = 84.375 // 16:9
}
private(set) var contentView: UIView
private var containerView: UIView
private var videoOrientation: VideoOrientation = .landscape
// 手势相关
private var initialFrame: CGRect = .zero
private var lastScale: CGFloat = 1.0
private var isResizing: Bool = false
private var initialCenter: CGPoint = .zero
// 缩放相关
private var currentScale: CGFloat = 1.0
private var initialDistance: CGFloat = 0
private let scaleMultiplier: CGFloat = 1.5
// UI组件
private lazy var closeButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_close"), for: .normal)
button.setImage(UIImage(named: "live_win_close"), for: .normal)
button.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
return button
}()
private lazy var closeButtonContainer: UIView = {
let container = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
container.backgroundColor = .clear
container.addSubview(closeButton)
closeButton.center = CGPoint(x: container.bounds.width/2, y: container.bounds.height/2)
return container
}()
// MARK: - Initialization
override init() {
// 创建容器视图
containerView = UIView(frame: CGRect(x: 0, y: 0,
width: Size.defaultWidth,
height: Size.defaultHeight))
// 创建内容视图
width: Size.defaultWidth,
height: Size.defaultHeight))
contentView = UIView(frame: containerView.bounds)
super.init()
setupUI()
setupGestures()
}
// MARK: - Setup
private func setupUI() {
// 容器视图设置
containerView.backgroundColor = .black
containerView.layer.cornerRadius = 8
containerView.layer.cornerRadius = 3
containerView.clipsToBounds = true
containerView.layer.masksToBounds = true
// 添加阴影
containerView.layer.shadowColor = UIColor.black.cgColor
containerView.layer.shadowOffset = CGSize(width: 0, height: 2)
containerView.layer.shadowRadius = 4
containerView.layer.shadowOpacity = 0.3
// 添加内容视图
containerView.addSubview(contentView)
contentView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
// 添加关闭按钮
containerView.addSubview(closeButton)
closeButton.snp.makeConstraints { make in
make.top.right.equalToSuperview().inset(8)
make.size.equalTo(CGSize(width: 24, height: 24))
}
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
contentView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
contentView.topAnchor.constraint(equalTo: containerView.topAnchor),
contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
])
containerView.addSubview(closeButtonContainer)
closeButtonContainer.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
closeButtonContainer.topAnchor.constraint(equalTo: containerView.topAnchor),
closeButtonContainer.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
closeButtonContainer.widthAnchor.constraint(equalToConstant: 30),
closeButtonContainer.heightAnchor.constraint(equalToConstant: 30)
])
}
private func setupGestures() {
// 平移手势
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
// 缩放手势
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
// 点击手势
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
tapGesture.delegate = self
containerView.addGestureRecognizer(panGesture)
containerView.addGestureRecognizer(pinchGesture)
containerView.addGestureRecognizer(tapGesture)
}
// MARK: - Public Methods
func calculateInitialFrame() -> CGRect {
// 计算浮窗的初始位置和大小
let width: CGFloat = 150 // 或其他合适的宽度
let height: CGFloat = width * 9 / 16 // 保持16:9比例
let width: CGFloat = Size.defaultWidth
let height: CGFloat = width / videoOrientation.aspectRatio
let x = UIScreen.main.bounds.width - width - 16
let y = UIScreen.main.bounds.height - height - 100 // 距离底部适当距离
let y = UIScreen.main.bounds.height - height - 100
return CGRect(x: x, y: y, width: width, height: height)
}
func show(in window: UIWindow) {
containerView.frame = calculateInitialFrame()
window.addSubview(containerView)
}
func show(in window: UIWindow, at point: CGPoint? = nil) {
// 设置初始位置
if let point = point {
containerView.center = point
} else {
// 默认位置:右下角
containerView.frame.origin = CGPoint(
x: window.bounds.width - containerView.bounds.width - 20,
y: window.bounds.height - containerView.bounds.height - 100
)
}
window.addSubview(containerView)
// 显示动画
containerView.alpha = 0
// containerView.transform = CGAffineTransform(scaleX: 0.3, y: 0.3)
UIView.animate(withDuration: 0.3) {
self.containerView.alpha = 1
self.containerView.transform = .identity
}
}
func dismiss() {
UIView.animate(withDuration: 0.3, animations: {
self.containerView.alpha = 0
//self.containerView.transform = CGAffineTransform(scaleX: 0.3, y: 0.3)
}) { _ in
self.containerView.removeFromSuperview()
}
}
func setVideoSize(_ size: CGSize) {
// 更新视频方向
let orientation: VideoOrientation = size.width > size.height ? .landscape : .portrait
if orientation != videoOrientation {
videoOrientation = orientation
updateLayoutForOrientation()
}
}
// MARK: - Private Methods
private func updateLayoutForOrientation() {
let currentWidth = containerView.bounds.width
let newHeight = currentWidth / videoOrientation.aspectRatio
UIView.animate(withDuration: 0.3) {
var frame = self.containerView.frame
frame.size.height = newHeight
self.containerView.frame = frame
// 通知代理
self.delegate?.floatingWindow(self, didChangeSize: frame.size)
}
}
private func snapToNearestSize() {
let currentWidth = containerView.bounds.width
// 定义三种尺寸状态
let smallWidth = Size.minWidth
let mediumWidth = Size.maxWidth * 0.5
let largeWidth = Size.maxWidth
// 确定目标尺寸
let targetWidth: CGFloat
if currentWidth < (smallWidth + mediumWidth) / 2 {
targetWidth = smallWidth
} else if currentWidth < (mediumWidth + largeWidth) / 2 {
targetWidth = mediumWidth
} else {
targetWidth = largeWidth
let sizeSteps: [CGFloat] = [
Size.minWidth,
Size.maxWidth * 0.33,
Size.maxWidth * 0.5,
Size.maxWidth * 0.75,
Size.maxWidth
]
var targetWidth = sizeSteps[0]
var minDifference = abs(currentWidth - targetWidth)
for size in sizeSteps {
let difference = abs(currentWidth - size)
if difference < minDifference {
minDifference = difference
targetWidth = size
}
}
// 计算对应高度
let targetHeight = targetWidth / videoOrientation.aspectRatio
// 执行动画
UIView.animate(withDuration: 0.3) {
let centerX = containerView.center.x
let centerY = containerView.center.y
UIView.animate(withDuration: 0.3,
delay: 0,
options: [.curveEaseOut],
animations: {
var frame = self.containerView.frame
frame.size = CGSize(width: targetWidth, height: targetHeight)
frame.origin.x = self.containerView.center.x - targetWidth / 2
frame.origin.y = self.containerView.center.y - targetHeight / 2
frame.origin.x = centerX - targetWidth / 2
frame.origin.y = centerY - targetHeight / 2
self.containerView.frame = frame
// 通知代理
self.delegate?.floatingWindow(self, didChangeSize: frame.size)
}
})
}
// MARK: - Gesture Handlers
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
guard !isResizing else { return }
let translation = gesture.translation(in: containerView.superview)
switch gesture.state {
case .began:
initialCenter = containerView.center
case .changed:
var newCenter = CGPoint(
x: initialCenter.x + translation.x,
......@@ -252,113 +256,140 @@ class YHFloatingWindow: NSObject {
)
newCenter = adjustedPosition(for: newCenter)
containerView.center = newCenter
// 通知代理
delegate?.floatingWindow(self, didChangePosition: newCenter)
case .ended:
let velocity = gesture.velocity(in: containerView.superview)
handlePanEndedWithVelocity(velocity)
default:
break
}
}
@objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) {
switch gesture.state {
case .began:
isResizing = true
initialFrame = containerView.frame
lastScale = 1.0
currentScale = 1.0
let touch1 = gesture.location(ofTouch: 0, in: containerView)
let touch2 = gesture.location(ofTouch: 1, in: containerView)
initialDistance = hypot(touch2.x - touch1.x, touch2.y - touch1.y)
case .changed:
let scale = gesture.scale / lastScale
let newWidth = initialFrame.width * scale
let touch1 = gesture.location(ofTouch: 0, in: containerView)
let touch2 = gesture.location(ofTouch: 1, in: containerView)
let currentDistance = hypot(touch2.x - touch1.x, touch2.y - touch1.y)
let scale = (currentDistance / initialDistance) * scaleMultiplier
let scaleDelta = scale / currentScale
currentScale = scale
let newWidth = initialFrame.width * scaleDelta
let newHeight = newWidth / videoOrientation.aspectRatio
var newFrame = initialFrame
newFrame.size = constrainSize(CGSize(width: newWidth, height: newHeight))
newFrame.origin.x = containerView.center.x - newFrame.width / 2
newFrame.origin.y = containerView.center.y - newFrame.height / 2
let centerX = containerView.center.x
let centerY = containerView.center.y
newFrame.origin.x = centerX - newFrame.width / 2
newFrame.origin.y = centerY - newFrame.height / 2
CATransaction.begin()
CATransaction.setDisableActions(true)
containerView.frame = newFrame
// 通知代理
CATransaction.commit()
delegate?.floatingWindow(self, didChangeSize: newFrame.size)
case .ended:
case .ended, .cancelled:
isResizing = false
snapToNearestSize()
default:
break
}
}
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: containerView)
if closeButtonContainer.frame.contains(location) {
return
}
delegate?.floatingWindowDidTap(self)
}
@objc private func closeButtonTapped() {
delegate?.floatingWindowDidClose(self)
dismiss()
}
// MARK: - Helper Methods
private func constrainSize(_ size: CGSize) -> CGSize {
var width = size.width
var height = size.height
// 限制最小/最大尺寸
width = max(min(width, Size.maxWidth), Size.minWidth)
if width < Size.minWidth {
width = Size.minWidth
} else if width > Size.maxWidth {
width = Size.maxWidth
}
height = width / videoOrientation.aspectRatio
if height > Size.maxHeight {
height = Size.maxHeight
width = height * videoOrientation.aspectRatio
}
return CGSize(width: width, height: height)
}
private func adjustedPosition(for center: CGPoint) -> CGPoint {
guard let superview = containerView.superview else { return center }
var adjustedCenter = center
let halfWidth = containerView.bounds.width / 2
let halfHeight = containerView.bounds.height / 2
// 限制不超出屏幕边界
adjustedCenter.x = min(max(halfWidth, adjustedCenter.x),
superview.bounds.width - halfWidth)
adjustedCenter.y = min(max(halfHeight, adjustedCenter.y),
superview.bounds.height - halfHeight)
// 计算实际可用区域
let topLimit = superview.safeAreaInsets.top + halfHeight
let bottomLimit = superview.bounds.height - superview.safeAreaInsets.bottom - halfHeight
// 限制不超出屏幕边界和安全区域
let safeAreaInsets: UIEdgeInsets
if #available(iOS 11.0, *) {
safeAreaInsets = superview.safeAreaInsets
} else {
safeAreaInsets = .zero
}
let topLimit = safeAreaInsets.top + halfHeight
let bottomLimit = superview.bounds.height - safeAreaInsets.bottom - halfHeight
adjustedCenter.x = min(max(halfWidth, adjustedCenter.x),
superview.bounds.width - halfWidth)
superview.bounds.width - halfWidth)
adjustedCenter.y = min(max(topLimit, adjustedCenter.y),
bottomLimit)
bottomLimit)
return adjustedCenter
}
private func handlePanEndedWithVelocity(_ velocity: CGPoint) {
let magnitude = sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y))
let slideMultiplier = magnitude / 200
let slideFactor = 0.1 * slideMultiplier
var finalCenter = CGPoint(
x: containerView.center.x + (velocity.x * slideFactor),
y: containerView.center.y + (velocity.y * slideFactor)
)
finalCenter = adjustedPosition(for: finalCenter)
UIView.animate(withDuration: 0.3) {
self.containerView.center = finalCenter
// 通知代理
self.delegate?.floatingWindow(self, didChangePosition: finalCenter)
}
}
......@@ -368,14 +399,14 @@ class YHFloatingWindow: NSObject {
extension YHFloatingWindow: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldReceive touch: UITouch) -> Bool {
// 如果点击的是按钮,不触发点击手势
if touch.view is UIButton {
shouldReceive touch: UITouch) -> Bool {
let location = touch.location(in: containerView)
if closeButtonContainer.frame.contains(location) {
return false
}
return true
......
......@@ -133,4 +133,46 @@ extension YHLiveSalesViewModel {
callback(nil, err)
}
}
/*
离开直播间
*/
func leaveLiveRoom(id: Int, callback: @escaping (_ success: Bool, _ error: YHErrorModel?) -> Void) {
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.LiveSales.leaveLiveRoom
_ = YHNetRequest.getRequest(url: strUrl, params: ["live_id": id]) { json, _ in
// 1. json字符串 转 对象
printLog("model 是 ==> \(json)")
if json.code == 200 {
callback(true, nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callback(false, err)
}
} failBlock: { err in
callback(false, err)
}
}
/*
进入直播间
*/
func joinLiveRoom(id: Int, callback: @escaping (_ success: Bool, _ error: YHErrorModel?) -> Void) {
let strUrl = YHBaseUrlManager.shared.curURL() + YHAllApiName.LiveSales.joinLiveRoom
_ = YHNetRequest.getRequest(url: strUrl, params: ["live_id": id]) { json, _ in
// 1. json字符串 转 对象
printLog("model 是 ==> \(json)")
if json.code == 200 {
callback(true, nil)
} else {
let err = YHErrorModel(errorCode: Int32(json.code), errorMsg: json.msg.isEmpty ? "" : json.msg)
callback(false, err)
}
} failBlock: { err in
callback(false, err)
}
}
}
......@@ -676,5 +676,9 @@ class YHAllApiName {
static let categoryList = "super-app/goods/category-list"
static let goodsList = "super-app/goods/list"
// 离开直播间
static let leaveLiveRoom = "super-app/live/app-live-exit"
// 进入直播间--需求登录
static let joinLiveRoom = "super-app/live/app-live-join"
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "live_win_close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "live_win_close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
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