From 3fb1d9c61d4b68d42c9062ee9952fd0428244b32 Mon Sep 17 00:00:00 2001 From: zjx Date: Mon, 16 Jun 2025 18:11:54 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=8E=86=E5=8F=B2=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=EF=BC=8Cbug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Veloria/Base/Extension/UIColor+VPAdd.swift | 4 + .../Controller/VPExploreViewController.swift | 43 ++++++++- .../Controller/VPHomePageViewController.swift | 38 +++++--- .../Home/View/VPHomePlayHistoricalView.swift | 90 ++++++++++++++++++ .../Controller/VPMyListViewController.swift | 33 ++++++- Veloria/Class/Player/View/VPEpisodeView.swift | 13 +++ Veloria/Libs/Empty/UIScrollView+Empty.swift | 30 +++++- .../icon/close_icon_03.imageset/Close.png | Bin 0 -> 780 bytes .../icon/close_icon_03.imageset/Close@3x.png | Bin 0 -> 1237 bytes .../icon/close_icon_03.imageset/Contents.json | 22 +++++ .../play_icon_02.imageset/Component 41@2x.png | Bin 0 -> 5085 bytes .../play_icon_02.imageset/Component 41@3x.png | Bin 0 -> 10126 bytes .../icon/play_icon_02.imageset/Contents.json | 22 +++++ Veloria/Source/en.lproj/Localizable.strings | 1 + 14 files changed, 278 insertions(+), 18 deletions(-) create mode 100644 Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Close.png create mode 100644 Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Close@3x.png create mode 100644 Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Contents.json create mode 100644 Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Component 41@2x.png create mode 100644 Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Component 41@3x.png create mode 100644 Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Contents.json diff --git a/Veloria/Base/Extension/UIColor+VPAdd.swift b/Veloria/Base/Extension/UIColor+VPAdd.swift index 9713ac8..ed570b7 100644 --- a/Veloria/Base/Extension/UIColor+VPAdd.swift +++ b/Veloria/Base/Extension/UIColor+VPAdd.swift @@ -250,4 +250,8 @@ extension UIColor { return UIColor(rgb: 0xE0E0E0, alpha: alpha) } + static func colorDBDBDB(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0xDBDBDB, alpha: alpha) + } + } diff --git a/Veloria/Class/Explore/Controller/VPExploreViewController.swift b/Veloria/Class/Explore/Controller/VPExploreViewController.swift index c7595cb..d7277ea 100644 --- a/Veloria/Class/Explore/Controller/VPExploreViewController.swift +++ b/Veloria/Class/Explore/Controller/VPExploreViewController.swift @@ -15,6 +15,15 @@ class VPExploreViewController: VPVideoPlayerViewController { var pagination: VPListPaginationModel? + private lazy var emptyView: VPEmptyView = { + let view = VPEmptyView.createNoNetworkEmptyView { [weak self] in + guard let self = self else { return } + self.requestDataArr(page: 1) + } + view.isHidden = false + return view + }() + deinit { NotificationCenter.default.removeObserver(self) } @@ -22,13 +31,15 @@ class VPExploreViewController: VPVideoPlayerViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: VPLoginManager.loginStateDidChangeNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) self.collectionView.vp_onRefrsh = true self.collectionView.vp_refreshDelegate = self self.delegate = self self.dataSource = self - requestDataArr(page: 1) + + vp_setupUI() } override func viewWillAppear(_ animated: Bool) { @@ -39,9 +50,30 @@ class VPExploreViewController: VPVideoPlayerViewController { @objc private func loginStateDidChangeNotification() { requestDataArr(page: 1) } + + @objc private func reachabilityDidChangeNotification() { + if VPNetworkReachabilityManager.manager.isReachable == true, self.getDataCount() == 0 { + requestDataArr(page: 1) + } + } } +extension VPExploreViewController { + + private func vp_setupUI() { + + view.addSubview(emptyView) + + emptyView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerX.equalToSuperview() + make.centerY.equalToSuperview().offset(-100) + } + } + +} + //MARK: -------------- VPPlayerListViewControllerDelegate -------------- extension VPExploreViewController: VPPlayerListViewControllerDelegate { func vp_playerViewControllerLoadMoreData(playerViewController: VPVideoPlayerViewController) { @@ -95,6 +127,8 @@ extension VPExploreViewController { VPVideoAPI.requestRecommandsVideo(page: page) { [weak self] listModel in guard let self = self else { return } + self.emptyView.isHidden = true + self.collectionView.isHidden = false if let listModel = listModel, let list = listModel.list { if page == 1 { self.setDataArr(dataArr: list) { [weak self] in @@ -105,6 +139,13 @@ extension VPExploreViewController { self.addDataArr(dataArr: list) } self.pagination = listModel.pagination + + } + else { + if VPNetworkReachabilityManager.manager.isReachable != true, self.getDataCount() == 0 { + self.emptyView.isHidden = false + self.collectionView.isHidden = true + } } completer?() } diff --git a/Veloria/Class/Home/Controller/VPHomePageViewController.swift b/Veloria/Class/Home/Controller/VPHomePageViewController.swift index dd0d24f..17f8ead 100644 --- a/Veloria/Class/Home/Controller/VPHomePageViewController.swift +++ b/Veloria/Class/Home/Controller/VPHomePageViewController.swift @@ -127,11 +127,7 @@ class VPHomePageViewController: VPViewController { }() private lazy var emptyView: VPEmptyView = { - let view = VPEmptyView() - view.image = UIImage(named: "empty_image_03") - view.title = "veloria_no_network".localized - view.des = "veloria_no_network_string".localized - view.clickButtonBlock = { [weak self] in + let view = VPEmptyView.createNoNetworkEmptyView { [weak self] in guard let self = self else { return } self.vp_setup() } @@ -140,6 +136,7 @@ class VPHomePageViewController: VPViewController { private lazy var playHistoricalView: VPHomePlayHistoricalView = { let view = VPHomePlayHistoricalView() + view.isHidden = true return view }() @@ -157,6 +154,11 @@ class VPHomePageViewController: VPViewController { self.navigationController?.setNavigationBarHidden(true, animated: true) } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + self.requestPlayHistorical() + } + override func handleHeaderRefresh(_ completer: (() -> Void)?) { if let vc = self.pageView.upSc.currentVC as? VPViewController { vc.handleHeaderRefresh { [weak self] in @@ -204,12 +206,7 @@ class VPHomePageViewController: VPViewController { extension VPHomePageViewController { @objc private func reachabilityDidChangeNotification() { if VPNetworkReachabilityManager.manager.isReachable == true { - if self.viewModel.oldModuleList == nil { - requestHomeData() - } - requestCategories() - - vp_setupUI() + vp_setup() } } @@ -217,9 +214,12 @@ extension VPHomePageViewController { extension VPHomePageViewController { private func vp_setup() { - requestHomeData() + if self.viewModel.oldModuleList == nil { + requestHomeData() + } requestCategories() setupPageView() + requestPlayHistorical() vp_setupUI() } @@ -266,7 +266,7 @@ extension VPHomePageViewController { playHistoricalView.snp.makeConstraints { make in make.centerX.equalToSuperview() - make.right.equalToSuperview().offset(15) + make.right.equalToSuperview().offset(-15) make.bottom.equalToSuperview().offset(-(UIScreen.customTabBarHeight + 10)) } } @@ -320,4 +320,16 @@ extension VPHomePageViewController { } } + private func requestPlayHistorical() { + + VPVideoAPI.requestPlayHistoryList(page: 1, pageSize: 1) { [weak self] listModel in + guard let self = self else { return } + if let model = listModel?.list?.first { + self.playHistoricalView.model = model + self.playHistoricalView.isHidden = false + } + } + + } + } diff --git a/Veloria/Class/Home/View/VPHomePlayHistoricalView.swift b/Veloria/Class/Home/View/VPHomePlayHistoricalView.swift index a3c5aba..5899474 100644 --- a/Veloria/Class/Home/View/VPHomePlayHistoricalView.swift +++ b/Veloria/Class/Home/View/VPHomePlayHistoricalView.swift @@ -9,6 +9,15 @@ import UIKit class VPHomePlayHistoricalView: UIView { + var model: VPShortModel? { + didSet { + coverImageView.vp_setImage(url: model?.image_url) + titleLabel.text = model?.name + + subtitleLabel.text = "veloria_last_play_episode".localizedReplace(text: model?.current_episode ?? "") + } + } + private lazy var bgView: UIView = { let view = UIView() view.layer.cornerRadius = 10 @@ -17,6 +26,41 @@ class VPHomePlayHistoricalView: UIView { return view }() + private lazy var closeButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "close_icon_03"), for: .normal) + button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside) + return button + }() + + private lazy var coverImageView: VPImageView = { + let imageView = VPImageView() + imageView.layer.cornerRadius = 8 + imageView.layer.masksToBounds = true + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 13) + label.textColor = .colorFFFFFF() + return label + }() + + private lazy var subtitleLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.textColor = .colorDBDBDB() + return label + }() + + private lazy var playButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "play_icon_02"), for: .normal) + button.addTarget(self, action: #selector(handlePlayButton), for: .touchUpInside) + return button + }() + override init(frame: CGRect) { super.init(frame: frame) @@ -28,6 +72,17 @@ class VPHomePlayHistoricalView: UIView { fatalError("init(coder:) has not been implemented") } + @objc private func handleCloseButton() { + self.isHidden = true + } + + @objc private func handlePlayButton() { + guard let id = model?.short_play_id else { return } + + let vc = VPDetailPlayerViewController() + vc.shortPlayId = id + VPAppTool.topViewController?.navigationController?.pushViewController(vc, animated: true) + } } @@ -35,12 +90,47 @@ extension VPHomePlayHistoricalView { private func vp_setupUI() { addSubview(bgView) + addSubview(coverImageView) + bgView.addSubview(closeButton) + bgView.addSubview(titleLabel) + bgView.addSubview(subtitleLabel) + bgView.addSubview(playButton) + bgView.snp.makeConstraints { make in make.left.right.bottom.equalToSuperview() make.top.equalToSuperview().offset(12) make.height.equalTo(56) } + + coverImageView.snp.makeConstraints { make in + make.top.bottom.equalToSuperview() + make.left.equalToSuperview().offset(32) + make.width.equalTo(52) + } + + closeButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(8) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(91) + make.top.equalToSuperview().offset(12) + make.right.lessThanOrEqualToSuperview().offset(-50) + } + + subtitleLabel.snp.makeConstraints { make in + make.left.equalTo(titleLabel) + make.bottom.equalToSuperview().offset(-11) + make.right.lessThanOrEqualToSuperview().offset(-50) + } + + playButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-11) + } + } } diff --git a/Veloria/Class/MyList/Controller/VPMyListViewController.swift b/Veloria/Class/MyList/Controller/VPMyListViewController.swift index 2c612c0..7757dea 100644 --- a/Veloria/Class/MyList/Controller/VPMyListViewController.swift +++ b/Veloria/Class/MyList/Controller/VPMyListViewController.swift @@ -126,10 +126,23 @@ class VPMyListViewController: VPViewController { return button }() + private lazy var emptyView: VPEmptyView = { + let view = VPEmptyView.createNoNetworkEmptyView { [weak self] in + guard let self = self else { return } + self.vp_setupUI() + } + view.isHidden = false + return view + }() + + deinit { + NotificationCenter.default.removeObserver(self) + } override func viewDidLoad() { super.viewDidLoad() - + NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) + vp_setupUI() // pageView.selectMenu(with: 1) } @@ -155,7 +168,10 @@ class VPMyListViewController: VPViewController { self?.pageView.selectMenu(with: 0) } } - + + @objc private func reachabilityDidChangeNotification() { + vp_setupUI() + } } extension VPMyListViewController { @@ -175,6 +191,19 @@ extension VPMyListViewController { extension VPMyListViewController { private func vp_setupUI() { + + guard VPNetworkReachabilityManager.manager.isReachable == true, pageView.superview == nil else { + if emptyView.superview == nil { + view.addSubview(emptyView) + emptyView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerX.equalToSuperview() + make.centerY.equalToSuperview().offset(-100) + } + } + return + } + view.addSubview(pageView) view.addSubview(editorButton) view.addSubview(cancelEditButton) diff --git a/Veloria/Class/Player/View/VPEpisodeView.swift b/Veloria/Class/Player/View/VPEpisodeView.swift index e8c02be..ea4a982 100644 --- a/Veloria/Class/Player/View/VPEpisodeView.swift +++ b/Veloria/Class/Player/View/VPEpisodeView.swift @@ -281,6 +281,19 @@ extension VPEpisodeView: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard indexPath.row != currentIndex else { return } + + var lastIndex = indexPath.row - 1 + var lastIsLock = false + if lastIndex > 0 && lastIndex < self.dataArr.count { + let lastModel = self.dataArr[lastIndex] + lastIsLock = lastModel.is_lock ?? false + } + + if lastIsLock { + VPToast.show(text: "veloria_jump_unlock_error".localized) + return + } + self.didSelectedIndex?(indexPath.row) self.dismiss(animated: true) { diff --git a/Veloria/Libs/Empty/UIScrollView+Empty.swift b/Veloria/Libs/Empty/UIScrollView+Empty.swift index cf81c2e..e33249b 100644 --- a/Veloria/Libs/Empty/UIScrollView+Empty.swift +++ b/Veloria/Libs/Empty/UIScrollView+Empty.swift @@ -9,17 +9,43 @@ import UIKit import EmptyDataSet_Swift extension UIScrollView { - func vp_addNormalEmpty(image: UIImage? = UIImage(named: "empty_image_01"), title: String? = "veloria_no_data".localized, des: String? = "veloria_no_data_add".localized) { + func vp_addNormalEmpty(image: UIImage? = UIImage(named: "empty_image_01"), title: String? = "veloria_no_data".localized, des: String? = "veloria_no_data_add".localized, buttonHandle: (() -> Void)? = nil) { let emptyView = VPEmptyView() emptyView.image = image emptyView.title = title emptyView.des = des + if let handle = buttonHandle { + emptyView.clickButtonBlock = handle + } self.emptyDataSetView { view in view.customView(emptyView) .verticalOffset(-130) - } } + + func vp_addNoNetworkEmpty(buttonHandle: (() -> Void)? = nil) { + + let emptyView = VPEmptyView.createNoNetworkEmptyView(buttonHandle: buttonHandle) + + self.emptyDataSetView { view in + view.customView(emptyView) + .verticalOffset(-130) + } + } + +} + +extension VPEmptyView { + + static func createNoNetworkEmptyView(buttonHandle: (() -> Void)?) -> VPEmptyView { + let view = VPEmptyView() + view.image = UIImage(named: "empty_image_03") + view.title = "veloria_no_network".localized + view.des = "veloria_no_network_string".localized + view.clickButtonBlock = buttonHandle + return view + } + } diff --git a/Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Close.png b/Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Close.png new file mode 100644 index 0000000000000000000000000000000000000000..38af02d19aa8bd8d1a7b84fb6df6064756e13ca3 GIT binary patch literal 780 zcmV+n1M~ceP)gCq@*ALAt50Fu2dHU#J~nN za3p7*?~QMB-rL=r?I(@a>)V}qGdr^%nIvL9pEtGXsO+meS9zw=ljSIK;=e>Or#D0dVECVhJ|-*C*~!`wp8{ck5b#2(bCrlB>|_@fb(_3?gMpN zR1au#83AK7NX_(`B#_Jlb{7sexb{{qH&v5$+;^3)#=K(82aJ<2%tjZs5rGc>7)HFu z=JP`3vyTLfOI|_KfDWMz=vr*;AYi-Jt%UJY<-d=FV;tYlBo4E+4+4Aaj3v(etW2V8 zJTZrcY+E2;ofzKe4txq#M+hKr zj~^_@C`xPoMJf_AqGNfH0RanLbh0PmkW4FyDRH#ePC>x3zb#?or{YOCPhx(QIIQwU zAaKV{Co-ug71>@Q(Uv%h&5!HxUh-=Az0I=#;1a!K_g8}@VF$#aY#;8yH?uPAv&8|? zk}ZMWKRWmp1Q>QBahzI`Pc#mlC+zlZsojkTjO@npN;Z$46gRHrvG2Q-+AS6**42hC zrEsWAsWSmJdMw3N`l4=Sq+Ibs4-<<7u4Kw z#U`}=(=6gm3UI*vQ~6u_aq1yr&vST(wFR*q$DlpWv9%{Z&mRDWHAPN8MN*_CZT=xO|Bx;pkTTyuN{E!kDJViD3P1u1H!k7= z3R?%2CT7V+HN%ja=MTg5}tdJ-HOn#gE#2;ulnq3;Y z3S8u#$=u8T;d!{$5|=faY&D3upg;r(U;^lTm&=NCt0$y8hHNO*yn!_v&TS0BuMlfY z6~G;B@MVYWQ3vr0?x05rzDf3qnKZ}DYYRl!xxxzQV%0l2@W z^tYs{C%RNNp)r>{mcVw3rEe0%UH8bgMxlsWK_l=@O&*i-=d8&C(nnkRG}sbX9>bUb z8G+ZT3JtYmCutQFh}aQs7JL?H(P+ZLZBFJ%-az_n3kMQTyY6$A0P%aH5)-yP54S0T z67e8aD-w&I@FYOYqi>!+CwT+mpeOLA#E=}?0$b|$U{*_I88DY?8pa;Lq%t{j0W$h} zmY>q%!D|I$0iBoJvEsiJ0B+2lOD^oXAlT)+1trA|TwX+-(W#D&OeIjk+`%no@tG;cMto=sGVE z8_&L?_-s^r2;N)z`No#BiG_@`O$!L-`Hn^l4T59G1Twt;>O6am77Vg~I+l3m0wg?N zshh#CdUJ%{Z0ndE6P-%9R%p_KK)C27{?hz-65z9fZ!2%!5DwZStWz8}8-+3xnXw|Z zs^mviA>^&CPIs5umyMp#$d&R2oBNFw-nth!9LV~+IS96WueZE00000NkvXXu0mjfxtJ#^ literal 0 HcmV?d00001 diff --git a/Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Contents.json new file mode 100644 index 0000000..7f10a63 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/close_icon_03.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Close.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Close@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Component 41@2x.png b/Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Component 41@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..75dee8c80093f15aba833af5486494c1a8b850c2 GIT binary patch literal 5085 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 literal 0 HcmV?d00001 diff --git a/Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Component 41@3x.png b/Veloria/Source/Assets.xcassets/icon/play_icon_02.imageset/Component 41@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..91dc257285038cdc60b7021fa3d358728d065686 GIT binary patch literal 10126 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