diff --git a/SynthReel.xcodeproj/project.pbxproj b/SynthReel.xcodeproj/project.pbxproj index ecdf632..d4ab4e8 100644 --- a/SynthReel.xcodeproj/project.pbxproj +++ b/SynthReel.xcodeproj/project.pbxproj @@ -685,6 +685,7 @@ 03B1A8EA2EC72BFB006C353F /* Player */ = { isa = PBXGroup; children = ( + 03B1A9242ECBFF03006C353F /* V */, 03B1A9202ECB2F25006C353F /* VC */, 03B1A8EB2EC72C0E006C353F /* M */, 03B1A9232ECBFEF9006C353F /* VM */, @@ -715,7 +716,6 @@ isa = PBXGroup; children = ( 03B1A9252ECBFF31006C353F /* SRShortPlayerViewModel.swift */, - 03B1A9242ECBFF03006C353F /* V */, 03980F4E2ECEB91C0006E317 /* SRRecommendPlayerViewModel.swift */, ); path = VM; diff --git a/SynthReel/Class/Player/VM/V/SRVipRetainAlert.swift b/SynthReel/Class/Player/V/SRVipRetainAlert.swift similarity index 78% rename from SynthReel/Class/Player/VM/V/SRVipRetainAlert.swift rename to SynthReel/Class/Player/V/SRVipRetainAlert.swift index 060a167..bb4dd67 100644 --- a/SynthReel/Class/Player/VM/V/SRVipRetainAlert.swift +++ b/SynthReel/Class/Player/V/SRVipRetainAlert.swift @@ -26,8 +26,8 @@ class SRVipRetainAlert: SRBaseAlert { private lazy var titleView: SRLabel = { let label = SRLabel() label.font = .font(ofSize: 24, weight: .init(900)) - label.text = "fableo_weekly_refill".localized.uppercased() - label.textColors = [UIColor._4_CFFD_4.cgColor, UIColor._51_D_4_FF.cgColor] + label.text = "synthreel_weekly_refill".localized.uppercased() + label.textColors = [UIColor._4_CFFD_4.cgColor,UIColor.white.cgColor, UIColor._51_D_4_FF.cgColor] label.textStartPoint = .init(x: 0.5, y: 0) label.textEndPoint = .init(x: 0.5, y: 1) return label @@ -76,7 +76,7 @@ class SRVipRetainAlert: SRBaseAlert { super.init(frame: frame) contentWidth = UIScreen.width - 55 contentView.backgroundColor = .clear - + closeButton.isHidden = false fa_setupLayout() } @@ -112,11 +112,10 @@ extension SRVipRetainAlert { } buyButton.snp.makeConstraints { make in - make.left.equalToSuperview().offset(20) make.centerX.equalToSuperview() make.top.equalTo(textLabel.snp.bottom).offset(12) - make.height.equalTo(48) - make.bottom.equalToSuperview() + make.height.equalTo(50) +// make.bottom.equalToSuperview() } } @@ -142,32 +141,8 @@ extension SRVipRetainAlert { let imageView = UIImageView(image: UIImage(named: "coinPackCell")) return imageView }() -// private lazy var bgView: FAGradientView = { -// let view = FAGradientView() -// view.fa_colors = [UIColor._524_B_8_E.cgColor, UIColor._303265.cgColor] -// view.fa_locations = [0, 1] -// view.fa_startPoint = .init(x: 0, y: 0.5) -// view.fa_endPoint = .init(x: 1, y: 0.5) -// view.layer.cornerRadius = 12 -// view.layer.masksToBounds = true -// view.layer.borderWidth = 1 -// view.layer.borderColor = UIColor.E_5_E_5_E_5.cgColor -// return view -// }() - private lazy var bgIconImageView1: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "coin_attachment_01")) - return imageView - }() - - private lazy var bgIconImageView2: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "coin_attachment_02")) - return imageView - }() - private lazy var bgIconImageView3 = UIImageView(image: UIImage(named: "coin_attachment_04")) - private lazy var bgIconImageView4 = UIImageView(image: UIImage(named: "coin_attachment_05")) - - private lazy var vipIconImageView = UIImageView(image: UIImage(named: "皇冠-金")) + private lazy var vipIconImageView = UIImageView(image: UIImage(named: "vicon")) private lazy var nameLabel: UILabel = { let label = UILabel() @@ -248,10 +223,6 @@ extension SRVipRetainAlert { addSubview(bgView) - bgView.addSubview(bgIconImageView4) - bgView.addSubview(bgIconImageView3) - bgView.addSubview(bgIconImageView1) - bgView.addSubview(bgIconImageView2) bgView.addSubview(vipIconImageView) bgView.addSubview(nameLabel) bgView.addSubview(textLabel) @@ -261,28 +232,9 @@ extension SRVipRetainAlert { make.edges.equalToSuperview() } - bgIconImageView1.snp.makeConstraints { make in - make.left.equalToSuperview().offset(0) - make.top.equalToSuperview().offset(0) - } - - bgIconImageView2.snp.makeConstraints { make in - make.right.equalToSuperview().offset(-26) - make.centerY.equalToSuperview() - } - - bgIconImageView3.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.centerX.equalTo(bgIconImageView2) - } - - bgIconImageView4.snp.makeConstraints { make in - make.left.bottom.equalToSuperview() - } - vipIconImageView.snp.makeConstraints { make in make.left.equalToSuperview().offset(16) - make.top.equalToSuperview().offset(18) + make.bottom.equalToSuperview().offset(-22) } nameLabel.snp.makeConstraints { make in @@ -291,8 +243,8 @@ extension SRVipRetainAlert { } textLabel.snp.makeConstraints { make in - make.left.equalTo(vipIconImageView) - make.bottom.equalToSuperview().offset(-18) + make.top.equalTo(6) + make.left.equalTo(14) } priceView.snp.makeConstraints { make in diff --git a/SynthReel/Class/Player/VM/V/SRDetailRecommendCell.swift b/SynthReel/Class/Player/VM/V/SRDetailRecommendCell.swift deleted file mode 100644 index 4fdd924..0000000 --- a/SynthReel/Class/Player/VM/V/SRDetailRecommendCell.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// SRDetailRecommendCell.swift -// SynthReel -// -// Created by CSGY on 2025/11/27. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import FSPagerView -import JXPlayer - -class SRDetailRecommendCell: FSPagerViewCell { - - var model: SRShortModel? { - didSet { - player.coverImageView?.sr_setImage(model?.image_url) - player.setPlayUrl(url: model?.video_url ?? "") - } - } - - /// ① 新增背景图 - private lazy var bgImageView: UIImageView = { - let iv = UIImageView() - iv.image = .homeViralHitsCell - iv.contentMode = .scaleAspectFill - iv.clipsToBounds = true - return iv - }() - - - private lazy var player: JXPlayer = { - let player = JXPlayer(controlView: nil) - player.playerView = self.playerView - player.isLoop = true - return player - }() - - private lazy var playerView: UIView = { - let view = UIView() - view.isUserInteractionEnabled = false - return view - }() - - - - override init(frame: CGRect) { - super.init(frame: frame) - contentView.addSubview(bgImageView) - bgImageView.snp.makeConstraints { make in - make.edges.equalToSuperview() - } - - // 播放器画面 - contentView.addSubview(playerView) - playerView.snp.makeConstraints { make in -// make.edges.equalToSuperview() - make.edges.equalTo(UIEdgeInsets(top: 15, left: 8, bottom: 15, right: 8)) - } -// addSubview(playerView) -// -// playerView.snp.makeConstraints { make in -// make.edges.equalToSuperview() -// } - } - - @MainActor required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func play() { - self.player.start() - } - - func pause() { - self.player.pause() - } - -} diff --git a/SynthReel/Class/Player/VM/V/SRDetailRecommendview.swift b/SynthReel/Class/Player/VM/V/SRDetailRecommendview.swift deleted file mode 100644 index 31eac76..0000000 --- a/SynthReel/Class/Player/VM/V/SRDetailRecommendview.swift +++ /dev/null @@ -1,175 +0,0 @@ -// -// SRDetailRecommendview.swift -// SynthReel -// -// Created by CSGY on 2025/11/27. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import FSPagerView - -class SRDetailRecommendview: SRBaseAlert { - - var clickCloseButton: (() -> Void)? - var didSelectedVideo: ((_ model: SRShortModel) -> Void)? - - var dataArr: [SRShortModel] = [] { - didSet { - self.pagerView.reloadData() - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in - self?.updateCurrentData() - } - } - } - - private weak var currentCell: SRDetailRecommendCell? { - didSet { - oldValue?.pause() - - currentCell?.play() - } - } - - private lazy var titleLabel: SRLabel = { - let label = SRLabel() - label.font = .font(ofSize: 16, weight: .init(900)) - label.textColors = [UIColor._4_CFFD_4.cgColor, UIColor._51_D_4_FF.cgColor] - label.textStartPoint = .init(x: 0.5, y: 0) - label.textEndPoint = .init(x: 0.5, y: 1) - label.text = "Keep the Drama Going".localized - return label - }() - - private lazy var bgView: UIImageView = { - let view = UIImageView(image: UIImage(named: "recommendBg")) - view.isUserInteractionEnabled = true - return view - }() - - private lazy var cancelButton: UIButton = { - let button = UIButton(type: .custom) - button.setImage(UIImage(named: "Close"), for: .normal) - button.addTarget(self, action: #selector(handleCancelButton), for: .touchUpInside) - return button - }() - - private lazy var pagerView: FSPagerView = { - let transformer = SRPagerViewTransformer(type: .linear) - transformer.minimumScale = 1 - - let view = FSPagerView() - view.itemSize = .init(width: 132, height: 185) - view.transformer = transformer - view.delegate = self - view.dataSource = self - view.isInfinite = true - view.interitemSpacing = 8 - view.register(SRDetailRecommendCell.self, forCellWithReuseIdentifier: "cell") - return view - }() - - override init(frame: CGRect) { - super.init(frame: frame) - contentWidth = UIScreen.width - self.closeButton.isHidden = true - - self.contentView.backgroundColor = .clear - self.contentView.layer.cornerRadius = 0 - self.contentView.layer.masksToBounds = false - - fa_setupLayout() - } - - @MainActor required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - - @objc private func handleCancelButton() { - self.dismiss() - self.clickCloseButton?() - } - - ///更新当前数据 - private func updateCurrentData() { - guard let cell = self.pagerView.cellForItem(at: self.pagerView.currentIndex) as? SRDetailRecommendCell else { return } - - self.currentCell = cell -// let model = cell.model -// self.videoNameLabel.text = model?.name - } - -} - -extension SRDetailRecommendview { - - private func fa_setupLayout() { - contentView.addSubview(bgView) - contentView.addSubview(cancelButton) - bgView.addSubview(titleLabel) - bgView.addSubview(pagerView) - - - bgView.snp.makeConstraints { make in - make.left.right.equalToSuperview().inset(15) - make.top.equalToSuperview().offset(-25) -// make.bottom.e() - } - - titleLabel.snp.makeConstraints { make in - make.top.equalTo(17) - make.centerX.equalToSuperview() - } - - pagerView.snp.makeConstraints { make in - make.left.right.equalToSuperview().inset(10) - make.bottom.equalTo(-17) - make.top.equalTo(titleLabel.snp.bottom).offset(10) - } - - cancelButton.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(bgView.snp.bottom).offset(30) - make.bottom.equalToSuperview() - } - - - } - -} - -//MARK: FSPagerViewDelegate FSPagerViewDataSource -extension SRDetailRecommendview: FSPagerViewDelegate, FSPagerViewDataSource { - - func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell { - let cell = pagerView.dequeueReusableCell(withReuseIdentifier: "cell", at: index) as! SRDetailRecommendCell - cell.model = self.dataArr[index] - return cell - } - - func numberOfItems(in pagerView: FSPagerView) -> Int { - return self.dataArr.count - } - - func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int) { - didSelectedVideo?(self.dataArr[index]) - self.dismiss() - } - - func pagerViewDidEndDecelerating(_ pagerView: FSPagerView) { - self.updateCurrentData() - } - -} - -extension SRDetailRecommendview { - - class PageControl: UIPageControl{ - override func size(forNumberOfPages pageCount: Int) -> CGSize { - return .init(width: 4, height: 4) - } - } - -} diff --git a/SynthReel/Class/Player/VM/V/SREpSelectorCell.swift b/SynthReel/Class/Player/VM/V/SREpSelectorCell.swift deleted file mode 100644 index bb17e5f..0000000 --- a/SynthReel/Class/Player/VM/V/SREpSelectorCell.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// SREpSelectorCell.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/19. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import SnapKit - -class SREpSelectorCell: UICollectionViewCell { - - - var model: SRVideoInfoModel? { - didSet { - numLabel.text = model?.episode - lockImageview.isHidden = !(model?.is_lock ?? true) - } - } - - var sr_isSelected: Bool = false { - didSet { - if sr_isSelected { - numLabel.textColors = [UIColor.srGreen.cgColor, UIColor.srBlue.cgColor] - boderView.isHidden = false - } else { - numLabel.textColors = [UIColor.white.cgColor, UIColor.white.cgColor] - boderView.isHidden = true - } - } - } - - lazy var numLabel: SRLabel = { - let label = SRLabel() - label.font = .font(ofSize: 14, weight: .regular) - label.textStartPoint = .init(x: 0.5, y: 0) - label.textEndPoint = .init(x: 0.5, y: 1) - return label - }() - - lazy var boderView: SRGradientView = { - let view = SRGradientView() - view.colors = [UIColor.srGreen.cgColor, UIColor.srBlue.cgColor] - view.startPoint = .init(x: 0.5, y: 0) - view.endPoint = .init(x: 0.5, y: 1) - view.layer.cornerRadius = 10 - view.layer.masksToBounds = true - return view - }() - - lazy var lockImageview = UIImageView.init(image: .lock) - - lazy var boderLayer: CAShapeLayer = { - let layer = CAShapeLayer() - return layer - }() - - override init(frame: CGRect) { - super.init(frame: frame) - contentView.layer.cornerRadius = 10 - contentView.layer.masksToBounds = true - contentView.backgroundColor = ._1_B_1_B_1_B - boderLayer.fillColor = contentView.backgroundColor?.cgColor // 设置为透明填充,实现镂空效果 - - - contentView.addSubview(boderView) - boderView.layer.addSublayer(boderLayer) - contentView.addSubview(numLabel) - contentView.addSubview(lockImageview) - - numLabel.snp.makeConstraints { make in - make.center.equalToSuperview() - } - - boderView.snp.makeConstraints { make in - make.edges.equalToSuperview() - } - - lockImageview.snp.makeConstraints { make in - make.right.top.equalToSuperview().inset(4) - make.width.height.equalTo(12) - } - } - - - override func layoutSubviews() { - super.layoutSubviews() - let size = self.bounds.size - let boderWidth: CGFloat = 1 - - boderLayer.path = UIBezierPath(roundedRect: .init(x: boderWidth, y: boderWidth, width: size.width - boderWidth * 2, height: size.height - boderWidth * 2), cornerRadius: 9.5).cgPath - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/SynthReel/Class/Player/VM/V/SREpSelectorView.swift b/SynthReel/Class/Player/VM/V/SREpSelectorView.swift deleted file mode 100644 index 5ca7123..0000000 --- a/SynthReel/Class/Player/VM/V/SREpSelectorView.swift +++ /dev/null @@ -1,211 +0,0 @@ -// -// SREpSelectorView.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/18. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import HWPanModal -import SnapKit - -class SREpSelectorView: SRPanModalContentView { - - var didSelected: ((_ index: Int) -> Void)? - - var model: SRShortDetailModel? { - didSet { - coverImageView.sr_setImage(model?.shortPlayInfo?.image_url) - shortNameLabel.text = model?.shortPlayInfo?.name - desLabel.text = model?.shortPlayInfo?.sr_description - - subtitleLabel.text = "all_episodes_text".localizedReplace(text: "\(model?.shortPlayInfo?.episode_total ?? 0)") - - if let text = model?.shortPlayInfo?.category?.first, text.count > 0 { - cagetoryLabel.text = "#" + text - } else { - cagetoryLabel.text = "" - } - self.collectionView.reloadData() - } - } - var selectedIndex: Int = 0 { - didSet { - self.collectionView.reloadData() - } - } - - lazy var coverBgView = UIImageView(image: UIImage(named: "ep_cover_bg_image")) - lazy var coverImageView: UIImageView = { - let imageView = SRImageView() - imageView.layer.cornerRadius = 2 - return imageView - }() - - lazy var shortNameLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 15, weight: .semibold) - label.textColor = .srBlue - return label - }() - - lazy var cagetoryLabel: SRLabel = { - let label = SRLabel() - label.font = .font(ofSize: 12, weight: .regular) - label.textColors = [UIColor.srGreen.cgColor, UIColor.srBlue.cgColor] - label.textStartPoint = .init(x: 0.5, y: 0) - label.textEndPoint = .init(x: 0.5, y: 1) - return label - }() - - lazy var desLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 12, weight: .regular) - label.textColor = .A_6_A_6_A_6 - label.numberOfLines = 3 - return label - }() - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 15, weight: .medium) - label.textColor = .white - label.text = "Select Episode".localized - return label - }() - - lazy var subtitleLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 12, weight: .regular) - label.textColor = .CCCCCC - return label - }() - - lazy var collectionViewLayout: UICollectionViewFlowLayout = { - let itemWidth = (UIScreen.width - 30 - 40) / 5 - - let layout = UICollectionViewFlowLayout() - layout.minimumLineSpacing = 10 - layout.minimumInteritemSpacing = 10 - layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15) - layout.itemSize = .init(width: floor(itemWidth), height: 50) - return layout - }() - - lazy var collectionView: SRCollectionView = { - let collectionView = SRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) - collectionView.delegate = self - collectionView.dataSource = self - collectionView.showsVerticalScrollIndicator = false - collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.safeBottom + 10, right: 0) - collectionView.register(SREpSelectorCell.self, forCellWithReuseIdentifier: "cell") - return collectionView - }() - - override init(frame: CGRect) { - super.init(frame: frame) - sr_setupUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} - - -extension SREpSelectorView { - - private func sr_setupUI() { - addSubview(coverBgView) - addSubview(coverImageView) - addSubview(shortNameLabel) - addSubview(cagetoryLabel) - addSubview(desLabel) - addSubview(titleLabel) - addSubview(subtitleLabel) - addSubview(collectionView) - - coverBgView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(15) - make.top.equalToSuperview().offset(18) - } - - coverImageView.snp.makeConstraints { make in - make.center.equalTo(coverBgView) - make.width.equalTo(63) - make.height.equalTo(84) - } - - shortNameLabel.snp.makeConstraints { make in - make.left.equalTo(coverImageView.snp.right).offset(10) - make.top.equalToSuperview().offset(24) - make.right.lessThanOrEqualToSuperview().offset(-15) - } - - cagetoryLabel.snp.makeConstraints { make in - make.left.equalTo(shortNameLabel) - make.top.equalTo(shortNameLabel.snp.bottom).offset(8) - } - - desLabel.snp.makeConstraints { make in - make.left.equalTo(shortNameLabel) - make.right.lessThanOrEqualToSuperview().offset(-15) - make.top.equalTo(shortNameLabel.snp.bottom).offset(32) - } - - titleLabel.snp.makeConstraints { make in - make.left.equalToSuperview().offset(15) - make.top.equalTo(coverBgView.snp.bottom).offset(16) - } - - subtitleLabel.snp.makeConstraints { make in - make.centerY.equalTo(titleLabel) - make.left.equalTo(titleLabel.snp.right).offset(3) - } - - collectionView.snp.makeConstraints { make in - make.left.right.equalToSuperview() - make.top.equalToSuperview().offset(166) - make.bottom.equalToSuperview() - } - } - -} - -//MARK: UICollectionViewDelegate UICollectionViewDataSource -extension SREpSelectorView: UICollectionViewDelegate, UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SREpSelectorCell - cell.model = self.model?.episodeList?[indexPath.row] - cell.sr_isSelected = indexPath.row == self.selectedIndex - return cell - } - - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return self.model?.episodeList?.count ?? 0 - } - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - - guard let epList = self.model?.episodeList else { return } - if self.selectedIndex == indexPath.row { return } - - let lastIndex = indexPath.row - 1 - var lastIsLock = false - if lastIndex > 0 && lastIndex < epList.count { - let lastModel = epList[lastIndex] - lastIsLock = lastModel.is_lock ?? false - } - if lastIsLock { - SRToast.show(text: "buy_fail_toast_02".localized) - return - } - - self.didSelected?(indexPath.row) - Task { - await self.dismiss(animated: true) - } - } -} diff --git a/SynthReel/Class/Player/VM/V/SRProgressView.swift b/SynthReel/Class/Player/VM/V/SRProgressView.swift deleted file mode 100644 index 6e9976b..0000000 --- a/SynthReel/Class/Player/VM/V/SRProgressView.swift +++ /dev/null @@ -1,216 +0,0 @@ -// -// SRProgressView.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/18. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import YYText -import YYCategories - -class SRProgressView: UIView { - - ///滑动开始 - var panStart: (() -> Void)? - - ///滑动中 - var panChange: ((_ progress: CGFloat) -> Void)? - - ///滑动完成回调 - var panFinish: ((_ progress: CGFloat) -> Void)? - - var progress: CGFloat = 0 { - didSet { - if !isPaning { - setNeedsDisplay() - } - } - } - - ///用来记录滑动时的当前进度 - private var tempProgress: CGFloat = 0 - - ///滑动进度 - private var panProgress: CGFloat = 0 - - var progressColor = UIColor.white.withAlphaComponent(0.2) - var currentProgress = UIColor.white - - var lineWidth: CGFloat = 3 - - ///加载中状态 - var isLoading = false { - didSet { - if isLoading { - if gradientTimer == nil { - gradientTimer = Timer.scheduledTimer(timeInterval: 0.05, target: YYTextWeakProxy(target: self), selector: #selector(handleGradientTimer), userInfo: nil, repeats: true) - } - } else { - gradientTimer?.invalidate() - gradientTimer = nil - } - } - } - - var insets: UIEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: 0) { - didSet { - self.invalidateIntrinsicContentSize() - setNeedsDisplay() - } - } - - private(set) lazy var panGesture: UIPanGestureRecognizer = { - let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(sender:))) - return pan - }() - - private(set) lazy var tagGesture: UITapGestureRecognizer = { - let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(sender:))) - return tap - }() - - ///是否在滑动中 - private var isPaning: Bool = false - - private var gradientTimer: Timer? - - private var gradientValue: CGFloat = 0 - - override var intrinsicContentSize: CGSize { - return .init(width: UIScreen.width, height: lineWidth + insets.top + insets.bottom) - } - - override init(frame: CGRect) { - super.init(frame: frame) -// self.backgroundColor = progressColor - self.backgroundColor = .clear - - self.addGestureRecognizer(panGesture) - self.addGestureRecognizer(tagGesture) - - - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - setNeedsDisplay() - } - - @objc private func handleGradientTimer() { - gradientValue += 0.1 - if gradientValue > 1 { - gradientValue = 0 - } - setNeedsDisplay() - } - - override func draw(_ rect: CGRect) { - super.draw(rect) - guard let context = UIGraphicsGetCurrentContext() else { return } - let width = rect.width - - let progressX = insets.left - let progressY = insets.top - let progressWidth = width - insets.left - insets.right - - if isLoading, !isPaning { - // 定义颜色空间 - let colorSpace = CGColorSpaceCreateDeviceRGB() - let colors: [CGColor] = [ - UIColor.clear.cgColor, - UIColor.white.cgColor, - UIColor.clear.cgColor - ] - let locations: [CGFloat] = [0.0, gradientValue, 1.0] - - guard let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations) else { - return - } - - let gradientRect = CGRect(x: progressX, - y: progressY, - width: progressWidth, - height: lineWidth) - - // 定义渐变的起点和终点 - let startPoint = CGPoint(x: rect.minX, y: rect.minY) - let endPoint = CGPoint(x: rect.maxX, y: rect.maxY) - - // 裁剪到渐变区域 - context.saveGState() - context.clip(to: gradientRect) - - // 绘制渐变 - context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: []) - } else { - var progress = self.progress - if self.isPaning { - progress = self.panProgress - } - let currentProgressWidth = progressWidth * progress - - ///绘制进度 - let progressPath = UIBezierPath(roundedRect: CGRect(x: progressX, y: progressY, width: progressWidth, height: lineWidth), cornerRadius: lineWidth / 2) - context.addPath(progressPath.cgPath) - context.setFillColor(progressColor.cgColor) - context.fillPath() - - ///绘制当前进度 - let currentPath = UIBezierPath(roundedRect: CGRect(x: progressX, y: progressY, width: progressWidth * progress, height: lineWidth), cornerRadius: lineWidth / 2) - context.addPath(currentPath.cgPath) - context.setFillColor(currentProgress.cgColor) - context.fillPath() - - ///绘制一个点 - let path = UIBezierPath(arcCenter: .init(x: currentProgressWidth + progressX, y: progressY + lineWidth / 2), radius: 3, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true) - context.addPath(path.cgPath) - context.setFillColor(currentProgress.cgColor) - context.fillPath() - } - - - } - -} - -extension SRProgressView { - @objc func handlePanGesture(sender: UIPanGestureRecognizer) { - - switch sender.state { - case .began: - self.isPaning = true - self.tempProgress = self.progress - sender.setTranslation(CGPoint(x: 0, y: 0), in: self) - self.panStart?() - - case .changed: - let point = sender.translation(in: self) - let offsetX = point.x / (self.width - self.insets.left - self.insets.right) - self.panProgress = self.tempProgress + offsetX - if self.panProgress < 0 { - self.panProgress = 0 - } - self.panChange?(self.panProgress) - setNeedsDisplay() - - default: - self.isPaning = false - self.panFinish?(self.panProgress) - - self.panProgress = 0 - } - } - - @objc func handleTapGesture(sender: UITapGestureRecognizer) { - let point = sender.location(in: self) - let offsetX = (point.x - self.insets.left) / (self.width - self.insets.left - self.insets.right) - self.panFinish?(offsetX) - } -} diff --git a/SynthReel/Class/Player/VM/V/SRRecommendPlayerCell.swift b/SynthReel/Class/Player/VM/V/SRRecommendPlayerCell.swift deleted file mode 100644 index 3b77847..0000000 --- a/SynthReel/Class/Player/VM/V/SRRecommendPlayerCell.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// SRRecommendPlayerCell.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/20. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import JXPlayer - -class SRRecommendPlayerCell: JXPlayerListCell { - - override var ControlViewClass: JXPlayerListControlView.Type { - return SRRecommendPlayerControlView.self - } - - override var model: Any? { - didSet { - let model = self.model as? SRShortModel - let videoInfo = model?.video_info - self.player.setPlayUrl(url: videoInfo?.video_url ?? "") - self.player.coverImageView?.sr_setImage(model?.image_url) - } - } -} diff --git a/SynthReel/Class/Player/VM/V/SRRecommendPlayerControlView.swift b/SynthReel/Class/Player/VM/V/SRRecommendPlayerControlView.swift deleted file mode 100644 index 3eec91e..0000000 --- a/SynthReel/Class/Player/VM/V/SRRecommendPlayerControlView.swift +++ /dev/null @@ -1,226 +0,0 @@ -// -// SRRecommendPlayerControlView.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/20. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import JXPlayer -import SnapKit -import YYCategories - -class SRRecommendPlayerControlView: JXPlayerListControlView { - - override var viewModel: JXPlayerListViewModel? { - didSet { - self.viewModel?.addObserver(self, forKeyPath: "isPlaying", context: nil) - } - } - - override var model: Any? { - didSet { - let model = model as! SRShortModel - - shortNameLabel.text = model.name - - stackView.sr_removeAllArrangedSubview() - if let text = model.category?.first, text.count > 0 { - categoryLabel.text = "#" + text - stackView.addArrangedSubview(categoryLabel) - } - - if let text = model.sr_description, text.count > 0 { - desLabel.text = text - stackView.addArrangedSubview(desLabel) - } - - } - } - - override var isCurrent: Bool { - didSet { - updatePlayerViewStatus() - } - } - - lazy var controlerView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "short_progress_bg_image")) - imageView.isUserInteractionEnabled = true - return imageView - }() - - lazy var shortNameLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 14, weight: .semibold) - label.textColor = .srBlue - return label - }() - - lazy var stackView: UIStackView = { - let view = UIStackView() - view.axis = .vertical - view.spacing = 8 - return view - }() - - lazy var categoryLabel: SRLabel = { - let label = SRLabel() - label.font = .font(ofSize: 11, weight: .regular) - label.textColors = [UIColor.srGreen.cgColor, UIColor.srBlue.cgColor] - label.textStartPoint = .init(x: 0.5, y: 0) - label.textEndPoint = .init(x: 0.5, y: 1) - return label - }() - - lazy var desLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 11, weight: .regular) - label.textColor = .A_6_A_6_A_6 - label.numberOfLines = 2 - return label - }() - - lazy var epBgView: UIView = { - let view = SRGradientView() - view.colors = [UIColor._51_D_4_FF.withAlphaComponent(0.5).cgColor, UIColor._4_CFFD_4.withAlphaComponent(0.1).cgColor] - view.startPoint = .init(x: 0, y: 0.5) - view.endPoint = .init(x: 1, y: 0.5) - view.layer.cornerRadius = 2 - view.layer.masksToBounds = true - let tap = UITapGestureRecognizer { [weak self] _ in - guard let self = self else { return } - let vc = SRDetailPlayerViewController() - vc.shortId = (self.model as? SRShortModel)?.short_play_id - self.viewController?.navigationController?.pushViewController(vc, animated: true) - } - view.addGestureRecognizer(tap) - return view - }() - - lazy var epIconImageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "ep_icon_02")) - imageView.setContentHuggingPriority(.required, for: .horizontal) - imageView.setContentCompressionResistancePriority(.required, for: .horizontal) - return imageView - }() - - lazy var epTextLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 12, weight: .regular) - label.textColor = .white - label.text = "recommend_ep_text".localized - return label - }() - - lazy var indicatorImageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "arrow_right_icon_02")) - imageView.setContentHuggingPriority(.required, for: .horizontal) - imageView.setContentCompressionResistancePriority(.required, for: .horizontal) - return imageView - }() - - lazy var playerImageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "play_icon_02")) - imageView.isHidden = true - return imageView - }() - - deinit { - self.viewModel?.removeObserver(self, forKeyPath: "isPlaying") - } - - override init(frame: CGRect) { - super.init(frame: frame) - sr_setupUI() - - let tap = UITapGestureRecognizer { [weak self] _ in - guard let self = self else { return } - self.viewModel?.userSwitchPlayAndPause() - } - self.addGestureRecognizer(tap) - } - - @MainActor required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - if keyPath == "isPlaying" { - updatePlayerViewStatus() - } - } - - - func updatePlayerViewStatus() { - if self.viewModel?.isPlaying == true || !isCurrent { - playerImageView.isHidden = true - } else { - playerImageView.isHidden = false - } - - } - -} - -extension SRRecommendPlayerControlView { - - private func sr_setupUI() { - addSubview(controlerView) - controlerView.addSubview(shortNameLabel) - controlerView.addSubview(stackView) - controlerView.addSubview(epBgView) - epBgView.addSubview(epIconImageView) - epBgView.addSubview(epTextLabel) - epBgView.addSubview(indicatorImageView) - addSubview(playerImageView) - - controlerView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(15) - make.centerX.equalToSuperview() - make.bottom.equalToSuperview().offset(-10) - } - - shortNameLabel.snp.makeConstraints { make in - make.left.equalToSuperview().offset(12) - make.right.lessThanOrEqualToSuperview().offset(-12) - make.top.equalToSuperview().offset(13) - } - - stackView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(12) - make.right.lessThanOrEqualToSuperview().offset(-12) - make.top.equalTo(shortNameLabel.snp.bottom).offset(8) - make.bottom.equalToSuperview().offset(-52) - } - - epBgView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(12) - make.right.equalToSuperview().offset(-12) - make.bottom.equalToSuperview().offset(-18) - make.height.equalTo(26) - } - - epIconImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.left.equalToSuperview().offset(8) - } - - epTextLabel.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.left.equalTo(epIconImageView.snp.right).offset(4) - make.right.lessThanOrEqualTo(self.indicatorImageView.snp.left).offset(-5) - } - - indicatorImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.right.equalToSuperview().offset(-12) - } - - playerImageView.snp.makeConstraints { make in - make.center.equalToSuperview() - } - } - -} diff --git a/SynthReel/Class/Player/VM/V/SRShortDetailControlView.swift b/SynthReel/Class/Player/VM/V/SRShortDetailControlView.swift deleted file mode 100644 index d2f0f9b..0000000 --- a/SynthReel/Class/Player/VM/V/SRShortDetailControlView.swift +++ /dev/null @@ -1,240 +0,0 @@ -// -// SRShortDetailControlView.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/18. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import JXPlayer -import SnapKit - -class SRShortDetailControlView: JXPlayerListControlView { - - var sr_viewModel: SRShortPlayerViewModel? { - return self.viewModel as? SRShortPlayerViewModel - } - - override var viewModel: JXPlayerListViewModel? { - didSet { - self.viewModel?.addObserver(self, forKeyPath: "isPlaying", context: nil) - } - } - - var shortModel: SRShortModel? { - didSet { - titleLabel.text = shortModel?.name - collectButton.isSelected = shortModel?.is_collect == true - } - } - - override var durationTime: TimeInterval { - didSet { - updateProgress() - let (_, m, s) = Int(durationTime).formatTimeGroup() - totalTimeLabel.text = "\(m):\(s)" - } - } - - override var currentTime: TimeInterval { - didSet { - updateProgress() - let (_, m, s) = Int(currentTime).formatTimeGroup() - currentTimeLabel.text = "\(m):\(s)" - } - } - - override var isLoading: Bool { - didSet { - progressView.isLoading = isLoading - } - } - - lazy var progressBgView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "short_progress_bg_image")) - imageView.isUserInteractionEnabled = true - return imageView - }() - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 14, weight: .medium) - label.textColor = .srBlue - return label - }() - - lazy var progressView: SRProgressView = { - let view = SRProgressView() - view.insets = .init(top: 10, left: 5, bottom: 10, right: 5) - view.panFinish = { [weak self] progress in - guard let self = self else { return } - self.viewModel?.seekTo(Float(progress)) - } - return view - }() - - lazy var totalTimeLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 10, weight: .regular) - label.textColor = .DFDFDF - label.text = "00:00" - return label - }() - - lazy var currentTimeLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 10, weight: .regular) - label.textColor = .DFDFDF - label.text = "00:00" - return label - }() - - lazy var epButton: UIButton = { - let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in - guard let self = self else { return } - self.sr_viewModel?.onEpSelectorView() - })) - button.setImage(UIImage(named: "ep_icon_01"), for: .normal) - return button - }() - - lazy var collectButton: UIButton = { - let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in - guard let self = self else { return } - guard let shortId = self.shortModel?.short_play_id else { return } - let videoId = (self.model as? SRVideoInfoModel)?.short_play_video_id - let isCollect = !(self.shortModel?.is_collect ?? false) - - Task { - await SRShortApi.requestShortCollect(shortId: shortId, videoId: videoId, isCollect: isCollect) - } - })) - button.setImage(UIImage(named: "collect_icon_01"), for: .normal) - button.setImage(UIImage(named: "collect_icon_01_selected"), for: .selected) - button.setImage(UIImage(named: "collect_icon_01_selected"), for: [.selected, .highlighted]) - return button - }() - - - lazy var playerImageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "play_icon_02")) - imageView.isHidden = true - return imageView - }() - - deinit { - self.viewModel?.removeObserver(self, forKeyPath: "isPlaying") - NotificationCenter.default.removeObserver(self) - } - - override init(frame: CGRect) { - super.init(frame: frame) - NotificationCenter.default.addObserver(self, selector: #selector(updateShortCollectStateNotification), name: SRShortApi.updateShortCollectStateNotification, object: nil) - - let tap = UITapGestureRecognizer { [weak self] _ in - guard let self = self else { return } - self.viewModel?.userSwitchPlayAndPause() - } - self.addGestureRecognizer(tap) - - sr_setupUI() - } - - @MainActor required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc private func updateShortCollectStateNotification(sender: Notification) { - guard let userInfo = sender.userInfo else { return } - guard let shortId = userInfo["id"] as? String else { return } - guard let state = userInfo["state"] as? Bool else { return } - guard shortId == self.shortModel?.short_play_id else { return } - self.shortModel?.is_collect = state - - collectButton.isSelected = state - } - - private func updateProgress() { - guard durationTime > 0 else { - progressView.progress = 0 - return - } - progressView.progress = currentTime / durationTime - } - - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - if keyPath == "isPlaying" { - updatePlayerViewStatus() - } - } - - - func updatePlayerViewStatus() { - if self.viewModel?.isPlaying == true || !isCurrent { - playerImageView.isHidden = true - } else { - playerImageView.isHidden = false - } - - } - -} - -extension SRShortDetailControlView { - - private func sr_setupUI() { - addSubview(progressBgView) - progressBgView.addSubview(titleLabel) - progressBgView.addSubview(progressView) - progressBgView.addSubview(totalTimeLabel) - progressBgView.addSubview(currentTimeLabel) - addSubview(epButton) - addSubview(collectButton) - addSubview(playerImageView) - - progressBgView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(15) - make.centerX.equalToSuperview() - make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 5)) - make.height.equalTo(88) - } - - titleLabel.snp.makeConstraints { make in - make.centerY.equalTo(progressBgView.snp.top).offset(23) - make.left.equalToSuperview().offset(9) - make.right.lessThanOrEqualToSuperview().offset(-9) - } - - progressView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(4) - make.right.equalToSuperview().offset(-6) - make.bottom.equalToSuperview().offset(-30) - } - - totalTimeLabel.snp.makeConstraints { make in - make.right.equalToSuperview().offset(-11) - make.bottom.equalToSuperview().offset(-24) - } - - currentTimeLabel.snp.makeConstraints { make in - make.left.equalToSuperview().offset(9) - make.bottom.equalToSuperview().offset(-24) - } - - epButton.snp.makeConstraints { make in - make.right.equalToSuperview().offset(-15) - make.bottom.equalTo(progressBgView.snp.top).offset(-44) - } - - collectButton.snp.makeConstraints { make in - make.centerX.equalTo(epButton) - make.bottom.equalTo(epButton.snp.top).offset(-25) - } - - playerImageView.snp.makeConstraints { make in - make.center.equalToSuperview() - } - } - -} diff --git a/SynthReel/Class/Player/VM/V/SRShortDetailPlayerCell.swift b/SynthReel/Class/Player/VM/V/SRShortDetailPlayerCell.swift deleted file mode 100644 index c9e553e..0000000 --- a/SynthReel/Class/Player/VM/V/SRShortDetailPlayerCell.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// SRShortDetailPlayerCell.swift -// SynthReel -// -// Created by 湖北秦九 on 2025/11/18. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit -import JXPlayer - -class SRShortDetailPlayerCell: JXPlayerListCell { - - override var ControlViewClass: JXPlayerListControlView.Type { - return SRShortDetailControlView.self - } - - var sr_controlView: SRShortDetailControlView { - return self.controlView as! SRShortDetailControlView - } - - var sr_viewModel: SRShortPlayerViewModel? { - return self.viewModel as? SRShortPlayerViewModel - } - - var hasLastEpisodeUnlocked: Bool = false { - didSet { - self.lockView.hasLastEpisodeUnlocked = hasLastEpisodeUnlocked - } - } - - private lazy var lockView: SRVideoLockView = { - let view = SRVideoLockView() - view.clickUnlockButton = { [weak self] in - Task { - await self?.sr_viewModel?.handleUnlockVideo() - } - } - - view.adUnlockButton = { [weak self] in - Task { - await self?.sr_viewModel?.handleAdUnlockVideo() - } - } - return view - }() - - override var model: Any? { - didSet { - let model = self.model as? SRVideoInfoModel - self.player.setPlayUrl(url: model?.video_url ?? "") - - self.lockView.isHidden = !(model?.is_lock ?? true) - lockView.videoInfo = model - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - - sr_setupLayout() - } - - @MainActor required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - var shortModel: SRShortModel? { - didSet { - self.sr_controlView.shortModel = shortModel - self.player.coverImageView?.sr_setImage(shortModel?.image_url) - } - } - -} - - -extension SRShortDetailPlayerCell { - - private func sr_setupLayout() { - addSubview(lockView) - - lockView.snp.makeConstraints { make in - make.edges.equalToSuperview() - } - } - -} diff --git a/SynthReel/Class/Player/VM/V/SRVideoLockView.swift b/SynthReel/Class/Player/VM/V/SRVideoLockView.swift deleted file mode 100644 index c90f6d2..0000000 --- a/SynthReel/Class/Player/VM/V/SRVideoLockView.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// SRVideoLockView.swift -// SynthReel -// -// Created by CSGY on 2025/12/1. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit - -class SRVideoLockView: UIView { - - var clickUnlockButton: (() -> Void)? - - var adUnlockButton: (() -> Void)? - - var videoInfo: SRVideoInfoModel? { - didSet { - unlockButton.setNeedsUpdateConfiguration() - } - } - - var hasLastEpisodeUnlocked = false { - didSet { - unlockButton.setNeedsUpdateConfiguration() - } - } - - lazy var unlockStackView: UIStackView = { - let stack = UIStackView() - stack.axis = .vertical - stack.spacing = 12 - stack.distribution = .fillEqually - return stack - }() - - private lazy var unlockButton: UIButton = { - var config = UIButton.Configuration.plain() - config.image = UIImage(named: "lock") - config.imagePadding = 6 - // 设置背景图片(使用 UIImage 作为背景) - config.background.image = UIImage(named: "unlockButtonBg") - config.background.imageContentMode = .scaleToFill // 让背景图铺满按钮 - - let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in - guard let self = self else { return } - self.clickUnlockButton?() - })) - button.configurationUpdateHandler = { [weak self] button in - guard let self = self else { return } - let attributeContainer = AttributeContainer([ - .font : UIFont.font(ofSize: 14, weight: .medium), - .foregroundColor : UIColor._51_D_4_FF - ]) - if hasLastEpisodeUnlocked { - button.configuration?.attributedTitle = .init("video_lock_tip_text".localized, attributes: attributeContainer) - } else { - button.configuration?.attributedTitle = .init("synthreel_unlocking_coins_notice".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer) - } - } - return button - }() - - private lazy var adlockButton: UIButton = { - var config = UIButton.Configuration.plain() - config.image = UIImage(named: "adlock") - config.imagePadding = 6 - // 设置背景图片(使用 UIImage 作为背景) - config.background.image = UIImage(named: "unlockButtonBg") - config.background.imageContentMode = .scaleToFill // 让背景图铺满按钮 - let attr = AttributeContainer([ - .font: UIFont.font(ofSize: 14, weight: .medium), - .foregroundColor: UIColor.white - ]) - config.attributedTitle = AttributedString("Watch 2ads to unlock".localized, attributes: attr) - - let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in - guard let self = self else { return } - self.adUnlockButton?() - })) - return button - }() - - override init(frame: CGRect) { - super.init(frame: frame) - backgroundColor = ._000000.withAlphaComponent(0.6) - sr_setupLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} - -extension SRVideoLockView { - - private func sr_setupLayout() { - addSubview(unlockStackView) - - unlockStackView.addArrangedSubview(unlockButton) - unlockStackView.addArrangedSubview(adlockButton) - - - unlockStackView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(45) - make.right.equalToSuperview().offset(-45) - make.height.equalTo(43 * 2 + 30) // 两个按钮 + 间距 - make.centerY.equalToSuperview() // 可自定义 - } - - unlockButton.snp.makeConstraints { make in - make.height.equalTo(43) - } - - adlockButton.snp.makeConstraints { make in - make.height.equalTo(43) - } - } -} diff --git a/SynthReel/Class/Player/VM/V/SRVideoRechargeView.swift b/SynthReel/Class/Player/VM/V/SRVideoRechargeView.swift deleted file mode 100644 index 9730eb9..0000000 --- a/SynthReel/Class/Player/VM/V/SRVideoRechargeView.swift +++ /dev/null @@ -1,320 +0,0 @@ -// -// SRVideoRechargeView.swift -// SynthReel -// -// Created by CSGY on 2025/12/5. -// Copyright © 2025 SR. All rights reserved. -// - -import UIKit - -class SRVideoRechargeView: SRPanModalContentView { - - var buyFinishHandle: (() -> Void)? - var didDismissHandle: (() -> Void)? - - var model: SRPayDateModel? { - didSet { - self.stackView.sr_removeAllArrangedSubview() - self.vipView.dataArr = model?.list_sub_vip ?? [] - self.coinsView.setDataArr(model?.list_coins ?? []) - - if let sort = model?.sort, sort.count > 0 { - sort.forEach { - if $0 == .vip, model?.list_sub_vip?.isEmpty == false { - self.stackView.addArrangedSubview(self.vipView) - } else if $0 == .coin, model?.list_coins?.isEmpty == false { - self.stackView.addArrangedSubview(self.coinsView) - } - } - } else { - if model?.list_sub_vip?.isEmpty == false { - self.stackView.addArrangedSubview(self.vipView) - } - if model?.list_coins?.isEmpty == false { - self.stackView.addArrangedSubview(self.coinsView) - } - } - - self.stackView.addArrangedSubview(self.tipView) - - self.setNeedsLayoutUpdate() - } - } - - var videoInfo: SRVideoInfoModel? { - didSet { - self.coinsView.videoId = videoInfo?.short_play_video_id - self.coinsView.shortPlayId = videoInfo?.short_play_id - self.vipView.videoId = videoInfo?.short_play_video_id - self.vipView.shortPlayId = videoInfo?.short_play_id - videoCoinsView.coins = videoInfo?.coins ?? 0 - - self.requestRestore() - } - } - - private lazy var closeButton: UIButton = { - let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in - guard let self = self else { return } -// FAStatAPI.requestEventStat(orderCode: nil, shortPlayId: self.videoInfo?.short_play_id, videoId: self.videoInfo?.short_play_video_id, eventKey: .payTemplateDialog, errorMsg: nil, otherParamenters: [ -// "event_name" : "pay cancel" -// ]) - Task { - await self.dismiss(animated: true) - } - self.didDismissHandle?() - })) - button.setImage(UIImage(named: "Close"), for: .normal) - return button - }() - - private lazy var scrollView: SRScrollView = { - let scrollView = SRScrollView() -// scrollView.clipsToBounds = false - return scrollView - }() - - private lazy var stackView: UIStackView = { - let view = UIStackView() - view.axis = .vertical - view.spacing = 18 - return view - }() - - private lazy var coinsView: SRStoreCoinsView = { - let view = SRStoreCoinsView() - view.buyFinishHandle = { [weak self] in - self?.buyFinishHandle?() - Task { - await self?.dismiss(animated: true) - } - } - return view - }() - - private lazy var vipView: SRStoreVipView = { - let view = SRStoreVipView() - view.buyFinishHandle = { [weak self] in - self?.buyFinishHandle?() - Task { - await self?.dismiss(animated: true) - } - } - return view - }() - - private lazy var videoCoinsView: SRVideoRechargeView.CoinsView = { - let view = SRVideoRechargeView.CoinsView() - view.title = "synthreel_price".localized + ":" - return view - }() - - private lazy var totalCoinsView: SRVideoRechargeView.CoinsView = { - let view = SRVideoRechargeView.CoinsView() - view.title = "synthreel_balance".localized + ":" - view.coins = SRLogin.manager.userInfo?.totalCoins ?? 0 - return view - }() - - private lazy var tipView: UIView = { - let view = UIView() - view.addSubview(tipTitleLabel) - view.addSubview(tipTextLabel) - - tipTitleLabel.snp.makeConstraints { make in - make.top.equalToSuperview().offset(7) - make.left.equalToSuperview().offset(16) - } - - tipTextLabel.snp.makeConstraints { make in - make.left.equalToSuperview().offset(16) - make.right.lessThanOrEqualToSuperview().offset(-16) - make.top.equalTo(tipTitleLabel.snp.bottom).offset(4) - make.bottom.equalToSuperview() - } - return view - }() - - private lazy var tipTitleLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 12, weight: .medium) - label.textColor = .white - label.text = "synthreel_tips".localized - return label - }() - - private lazy var tipTextLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 10, weight: .regular) - label.textColor = .white - label.text = "store_tips".localized - label.numberOfLines = 0 - return label - }() - - deinit { - NotificationCenter.default.removeObserver(self) - } - - override init(frame: CGRect) { - super.init(frame: frame) - NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: SRLogin.userInfoUpdateNotification, object: nil) - self.contentHeight = UIScreen.height - UIScreen.safeTop -// self.backgroundColor = ._000000.withAlphaComponent(0.6) - self.backgroundColor = .clear - self.mainScrollView = self.scrollView - fa_setupLayout() - } - - @MainActor required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc private func userInfoUpdateNotification() { - totalCoinsView.coins = SRLogin.manager.userInfo?.totalCoins ?? 0 - } - - override func present(in view: UIView?) { - super.present(in: view) -// self.hw_contentView.sr_addEffectView(style: .dark) -// self.hw_contentView.sr_setRoundedCorner(topLeft: 24, topRight: 24, bottomLeft: 0, bottomRight: 0) - } - - override func allowsTapBackgroundToDismiss() -> Bool { - return false - } -} - -extension SRVideoRechargeView { - - private func fa_setupLayout() { - addSubview(closeButton) - addSubview(videoCoinsView) - addSubview(totalCoinsView) -// addSubview(titleLabel) - addSubview(scrollView) - scrollView.addSubview(stackView) - - closeButton.snp.makeConstraints { make in - make.right.equalToSuperview().offset(-16) - make.top.equalToSuperview().offset(12) - } - - videoCoinsView.snp.makeConstraints { make in - make.centerY.equalTo(closeButton) - make.left.equalToSuperview().offset(16) - } - - totalCoinsView.snp.makeConstraints { make in - make.centerY.equalTo(closeButton) - make.left.equalTo(videoCoinsView.snp.right).offset(15) - } - -// titleLabel.snp.makeConstraints { make in -// make.left.equalToSuperview().offset(16) -// make.top.equalToSuperview().offset(39) -// } - - scrollView.snp.makeConstraints { make in - make.left.right.equalToSuperview() - make.top.equalToSuperview().offset(74) - make.bottom.equalToSuperview() - } - - stackView.snp.makeConstraints { make in - make.left.centerX.equalToSuperview() - make.top.equalToSuperview() - make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 10)) - } - } - -} - -extension SRVideoRechargeView { - - @objc private func requestRestore() { - guard let shortPlayId = self.videoInfo?.short_play_id, let videoId = self.videoInfo?.short_play_video_id else { return } - - SRIapManager.manager.restore(isLoding: false, shortPlayId: shortPlayId, videoId: videoId) { [weak self] isFinish, buyType in - if isFinish { - Task { - await SRLogin.manager.requestUserInfo(completer: nil) - self?.buyFinishHandle?() - await self?.dismiss(animated: true) - } - } - } - } - -} - - -extension SRVideoRechargeView { - - class CoinsView: UIView { - var title: String? { - didSet { - titleLabel.text = title - } - } - - var coins: Int = 0 { - didSet { - coinsLabel.text = "\(coins)" - } - } - - private lazy var titleLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 14, weight: .regular) - label.textColor = .white - return label - }() - - private lazy var iconImageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "bigCoins")) - return imageView - }() - - private lazy var coinsLabel: UILabel = { - let label = UILabel() - label.font = .font(ofSize: 14, weight: .bold) - label.textColor = .white - return label - }() - - override init(frame: CGRect) { - super.init(frame: frame) - - addSubview(titleLabel) - addSubview(iconImageView) - addSubview(coinsLabel) - - titleLabel.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.bottom.lessThanOrEqualToSuperview() - make.left.equalToSuperview() - } - - iconImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.bottom.lessThanOrEqualToSuperview() - make.left.equalTo(titleLabel.snp.right).offset(6) - } - - coinsLabel.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.bottom.lessThanOrEqualToSuperview() - make.left.equalTo(iconImageView.snp.right).offset(4) - make.right.equalToSuperview() - } - } - - @MainActor required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - } - -} diff --git a/SynthReel/Libs/Alert/SRBaseAlert.swift b/SynthReel/Libs/Alert/SRBaseAlert.swift index adb7ef6..21fb69b 100644 --- a/SynthReel/Libs/Alert/SRBaseAlert.swift +++ b/SynthReel/Libs/Alert/SRBaseAlert.swift @@ -35,7 +35,7 @@ class SRBaseAlert: UIView { private(set) lazy var closeButton: UIButton = { let button = UIButton(type: .custom) - button.setImage(UIImage(named: "close_icon_03"), for: .normal) + button.setImage(UIImage(named: "Close"), for: .normal) button.addTarget(self, action: #selector(dismiss), for: .touchUpInside) return button }() diff --git a/SynthReel/Source/en.lproj/Localizable.strings b/SynthReel/Source/en.lproj/Localizable.strings index a54326b..8eaad28 100644 --- a/SynthReel/Source/en.lproj/Localizable.strings +++ b/SynthReel/Source/en.lproj/Localizable.strings @@ -85,6 +85,7 @@ "synthreel_coin_bag_buy_tip_title" = "How Do I Receive Coins?"; "synthreel_continue" = "Claim Now"; "vip_retain_alert_text" = "Unlock every show you love!"; +"vip_tip_01" = "Unlimited access to all series"; "coins_pack_tips" = "1.Coins are delivered instantly upon purchase.
2.Daily bonus coins available from the next day.
3.All coins will be revoked when the subscription expires, including both initial and daily coins.";