From b7a0a86a1a9950e6dbe108560bc42d93f09005a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=BE=9C=E5=A3=B0=E4=B8=96=E7=BA=AA?= <>
Date: Mon, 8 Dec 2025 17:32:39 +0800
Subject: [PATCH] =?UTF-8?q?1.=E6=96=87=E4=BB=B6=E7=9B=AE=E5=BD=95=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
SynthReel.xcodeproj/project.pbxproj | 2 +-
.../Player/{VM => }/V/SRVipRetainAlert.swift | 66 +---
.../Player/VM/V/SRDetailRecommendCell.swift | 79 -----
.../Player/VM/V/SRDetailRecommendview.swift | 175 ----------
.../Class/Player/VM/V/SREpSelectorCell.swift | 99 ------
.../Class/Player/VM/V/SREpSelectorView.swift | 211 ------------
.../Class/Player/VM/V/SRProgressView.swift | 216 ------------
.../Player/VM/V/SRRecommendPlayerCell.swift | 26 --
.../VM/V/SRRecommendPlayerControlView.swift | 226 -------------
.../VM/V/SRShortDetailControlView.swift | 240 -------------
.../Player/VM/V/SRShortDetailPlayerCell.swift | 88 -----
.../Class/Player/VM/V/SRVideoLockView.swift | 120 -------
.../Player/VM/V/SRVideoRechargeView.swift | 320 ------------------
SynthReel/Libs/Alert/SRBaseAlert.swift | 2 +-
SynthReel/Source/en.lproj/Localizable.strings | 1 +
15 files changed, 12 insertions(+), 1859 deletions(-)
rename SynthReel/Class/Player/{VM => }/V/SRVipRetainAlert.swift (78%)
delete mode 100644 SynthReel/Class/Player/VM/V/SRDetailRecommendCell.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRDetailRecommendview.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SREpSelectorCell.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SREpSelectorView.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRProgressView.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRRecommendPlayerCell.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRRecommendPlayerControlView.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRShortDetailControlView.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRShortDetailPlayerCell.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRVideoLockView.swift
delete mode 100644 SynthReel/Class/Player/VM/V/SRVideoRechargeView.swift
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.";