首页bug修改

This commit is contained in:
澜声世纪 2025-12-25 10:14:38 +08:00
parent 5fdccdad66
commit f9f5b83e20
9 changed files with 206 additions and 125 deletions

View File

@ -89,6 +89,7 @@
85606A9F2EEBE95A005D989D /* NRDashedLineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A9E2EEBE95A005D989D /* NRDashedLineView.swift */; }; 85606A9F2EEBE95A005D989D /* NRDashedLineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85606A9E2EEBE95A005D989D /* NRDashedLineView.swift */; };
85859E5C2EF3FC5F0020D282 /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 85859E552EF3FC5F0020D282 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 85859E5C2EF3FC5F0020D282 /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 85859E552EF3FC5F0020D282 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
85859E662EF3FC6E0020D282 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85859E632EF3FC6E0020D282 /* NotificationService.swift */; }; 85859E662EF3FC6E0020D282 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85859E632EF3FC6E0020D282 /* NotificationService.swift */; };
85859E682EFCD1D80020D282 /* NRHomeMustReadTodayTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85859E672EFCD1D80020D282 /* NRHomeMustReadTodayTransformer.swift */; };
85CF941D2EEBFEA6006467E3 /* NRCoinsPackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CF941C2EEBFEA6006467E3 /* NRCoinsPackModel.swift */; }; 85CF941D2EEBFEA6006467E3 /* NRCoinsPackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CF941C2EEBFEA6006467E3 /* NRCoinsPackModel.swift */; };
85CF941F2EEBFECF006467E3 /* NRCoinsPackReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CF941E2EEBFECF006467E3 /* NRCoinsPackReceiveModel.swift */; }; 85CF941F2EEBFECF006467E3 /* NRCoinsPackReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CF941E2EEBFECF006467E3 /* NRCoinsPackReceiveModel.swift */; };
85CF94212EEC050D006467E3 /* NRCoinsPackBuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CF94202EEC050D006467E3 /* NRCoinsPackBuyView.swift */; }; 85CF94212EEC050D006467E3 /* NRCoinsPackBuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CF94202EEC050D006467E3 /* NRCoinsPackBuyView.swift */; };
@ -588,6 +589,7 @@
85859E552EF3FC5F0020D282 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 85859E552EF3FC5F0020D282 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
85859E622EF3FC6E0020D282 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 85859E622EF3FC6E0020D282 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
85859E632EF3FC6E0020D282 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; }; 85859E632EF3FC6E0020D282 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
85859E672EFCD1D80020D282 /* NRHomeMustReadTodayTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRHomeMustReadTodayTransformer.swift; sourceTree = "<group>"; };
85CF941C2EEBFEA6006467E3 /* NRCoinsPackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackModel.swift; sourceTree = "<group>"; }; 85CF941C2EEBFEA6006467E3 /* NRCoinsPackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackModel.swift; sourceTree = "<group>"; };
85CF941E2EEBFECF006467E3 /* NRCoinsPackReceiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackReceiveModel.swift; sourceTree = "<group>"; }; 85CF941E2EEBFECF006467E3 /* NRCoinsPackReceiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackReceiveModel.swift; sourceTree = "<group>"; };
85CF94202EEC050D006467E3 /* NRCoinsPackBuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackBuyView.swift; sourceTree = "<group>"; }; 85CF94202EEC050D006467E3 /* NRCoinsPackBuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoinsPackBuyView.swift; sourceTree = "<group>"; };
@ -1359,6 +1361,7 @@
0398109E2ED069890006E317 /* M */ = { 0398109E2ED069890006E317 /* M */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
85859E672EFCD1D80020D282 /* NRHomeMustReadTodayTransformer.swift */,
039810BB2ED43C8E0006E317 /* NRReadWhatViewTransformer.swift */, 039810BB2ED43C8E0006E317 /* NRReadWhatViewTransformer.swift */,
F34990B82EDEB1620039E939 /* NRHomeNovelModuleItem.swift */, F34990B82EDEB1620039E939 /* NRHomeNovelModuleItem.swift */,
); );
@ -2529,6 +2532,7 @@
85CF94472EF001AD006467E3 /* NRMyUnlocksViewController.swift in Sources */, 85CF94472EF001AD006467E3 /* NRMyUnlocksViewController.swift in Sources */,
F3B8596B2EE91C9F0095A9CC /* NRStoreCoinsCell.swift in Sources */, F3B8596B2EE91C9F0095A9CC /* NRStoreCoinsCell.swift in Sources */,
F3B859712EE94A1B0095A9CC /* NRFeedbackViewController.swift in Sources */, F3B859712EE94A1B0095A9CC /* NRFeedbackViewController.swift in Sources */,
85859E682EFCD1D80020D282 /* NRHomeMustReadTodayTransformer.swift in Sources */,
85CF94392EEFE35A006467E3 /* NRLoginManager+Facebook.swift in Sources */, 85CF94392EEFE35A006467E3 /* NRLoginManager+Facebook.swift in Sources */,
F34348C72ED6CCBC00AA7E70 /* NRExploreNovelContentListViewController.swift in Sources */, F34348C72ED6CCBC00AA7E70 /* NRExploreNovelContentListViewController.swift in Sources */,
039810B82ED431780006E317 /* NRHomeNovelReadWhatView.swift in Sources */, 039810B82ED431780006E317 /* NRHomeNovelReadWhatView.swift in Sources */,

View File

@ -5,116 +5,137 @@
// Created by on 2025/11/26. // Created by on 2025/11/26.
// //
import UIKit
import SnapKit import SnapKit
import UIKit
class NRExploreNovelContentListViewController: NRViewController { class NRExploreNovelContentListViewController: NRViewController {
var menuItem: NRExploreNovelMenuItem? var menuItem: NRExploreNovelMenuItem?
var contentType: NRExploreNovelContentViewController.ContentType = .today var contentType: NRExploreNovelContentViewController.ContentType = .today
lazy var dataArr: [NRNovelModel] = [] lazy var dataArr: [NRNovelModel] = []
lazy var collectionViewLayout: UICollectionViewCompositionalLayout = { lazy var collectionViewLayout: UICollectionViewCompositionalLayout = {
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))) let item = NSCollectionLayoutItem(
layoutSize: .init(
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(60)), subitems: [item]) widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(60)),
subitems: [item])
let section = NSCollectionLayoutSection(group: group) let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 8 section.interGroupSpacing = 8
section.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0) section.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
let configuration = UICollectionViewCompositionalLayoutConfiguration() let configuration = UICollectionViewCompositionalLayoutConfiguration()
let layout = UICollectionViewCompositionalLayout(section: section, configuration: configuration) let layout = UICollectionViewCompositionalLayout(
section: section, configuration: configuration)
return layout return layout
}() }()
lazy var collectionView: NRCollectionView = { lazy var collectionView: NRCollectionView = {
let collectionView = NRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) let collectionView = NRCollectionView(
frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self collectionView.delegate = self
collectionView.dataSource = self collectionView.dataSource = self
collectionView.contentInset = .init(top: 0, left: 0, bottom: 10, right: 0) collectionView.contentInset = .init(top: 0, left: 0, bottom: 10, right: 0)
collectionView.register(NRExploreNovelContentListCell.self, forCellWithReuseIdentifier: "cell") collectionView.register(
NRExploreNovelContentListCell.self, forCellWithReuseIdentifier: "cell")
return collectionView return collectionView
}() }()
@MainActor deinit { @MainActor deinit {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.backgroundImageView.isHidden = true self.backgroundImageView.isHidden = true
self.view.backgroundColor = .clear self.view.backgroundColor = .clear
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: NRNetworkReachableManager.networkStatusDidChangeNotification, object: nil) NotificationCenter.default.addObserver(
self, selector: #selector(networkStatusDidChangeNotification),
name: NRNetworkReachableManager.networkStatusDidChangeNotification, object: nil)
nr_setupUI() nr_setupUI()
Task { Task {
await requestDataArr() await requestDataArr()
} }
} }
@objc private func networkStatusDidChangeNotification() { @objc private func networkStatusDidChangeNotification() {
guard NRNetworkReachableManager.manager.isReachable == true, self.dataArr.isEmpty else { return } guard NRNetworkReachableManager.manager.isReachable == true, self.dataArr.isEmpty else {
return
}
Task { Task {
await requestDataArr() await requestDataArr()
} }
} }
} }
extension NRExploreNovelContentListViewController { extension NRExploreNovelContentListViewController {
private func nr_setupUI() { private func nr_setupUI() {
view.addSubview(collectionView) view.addSubview(collectionView)
collectionView.snp.makeConstraints { make in collectionView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview() make.left.right.bottom.equalToSuperview()
make.top.equalToSuperview().offset(12) make.top.equalToSuperview().offset(12)
} }
} }
} }
//MARK: UICollectionViewDelegate UICollectionViewDataSource //MARK: UICollectionViewDelegate UICollectionViewDataSource
extension NRExploreNovelContentListViewController: UICollectionViewDelegate, UICollectionViewDataSource { extension NRExploreNovelContentListViewController: UICollectionViewDelegate,
UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! NRExploreNovelContentListCell
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)
-> UICollectionViewCell
{
let cell =
collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
as! NRExploreNovelContentListCell
cell.menuItem = self.menuItem cell.menuItem = self.menuItem
cell.row = indexPath.row cell.row = indexPath.row
cell.model = dataArr[indexPath.row] cell.model = dataArr[indexPath.row]
return cell return cell
} }
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int)
-> Int
{
return dataArr.count return dataArr.count
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = dataArr[indexPath.row] let model = dataArr[indexPath.row]
let vc = NRNovelDetailViewController() let vc = NRNovelDetailViewController()
vc.novelId = model.id ?? "" vc.novelId = model.id ?? ""
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)
} }
} }
extension NRExploreNovelContentListViewController { extension NRExploreNovelContentListViewController {
private func requestDataArr() async { private func requestDataArr() async {
guard let type = self.menuItem?.type else { return } guard let type = self.menuItem?.type else { return }
guard let list = await NRHomeAPI.requestRankingCollection(type: type.rawValue, days: self.contentType.rawValue) else { return } guard
let list = await NRHomeAPI.requestRankingCollection(
type: type.rawValue, days: self.contentType.rawValue)
else { return }
self.dataArr = list self.dataArr = list
self.collectionView.reloadData() self.collectionView.reloadData()
} }
} }

View File

@ -0,0 +1,47 @@
//
// NRHomeMustReadTodayTransformer.swift
// ReaderHive
//
// Created by on 2025/11/24.
//
import FSPagerView
import UIKit
class NRHomeMustReadTodayTransformer: FSPagerViewTransformer {
nonisolated override init(type: FSPagerViewTransformerType) {
super.init(type: type)
}
nonisolated override func applyTransform(to attributes: FSPagerViewLayoutAttributes) {
MainActor.assumeIsolated {
guard let pagerView = self.pagerView else { return }
let itemWidth = pagerView.itemSize.width
let pagerWidth = pagerView.frame.width
// 16
let leftMargin: CGFloat = 16
// FSPagerView item
// item pagerView.width / 2
// item 16 (16 + itemWidth / 2)
let targetCenter = leftMargin + itemWidth / 2
let currentCenter = pagerWidth / 2
let offset = currentCenter - targetCenter
// item offset
attributes.transform = CGAffineTransform(translationX: -offset, y: 0)
}
}
nonisolated override func proposedInteritemSpacing() -> CGFloat {
guard let pagerView = self.pagerView else {
return 0
}
return MainActor.assumeIsolated {
return pagerView.interitemSpacing
}
}
}

View File

@ -5,20 +5,21 @@
// Created by on 2025/11/24. // Created by on 2025/11/24.
// //
import UIKit import FSPagerView
import SnapKit import SnapKit
import UIKit
class NRHomeNovelMustReadTodayCell: FSPagerViewCell {
class NRHomeNovelMustReadTodayCell: UICollectionViewCell {
var model: NRNovelModel? { var model: NRNovelModel? {
didSet { didSet {
coverImageView.nr_setImage(model?.image_url) coverImageView.nr_setImage(model?.image_url)
titleLabel.text = model?.name titleLabel.text = model?.name
desLabel.text = model?.nr_description desLabel.text = model?.nr_description
starView.grade = (model?.rate ?? 0) / 2 starView.grade = (model?.rate ?? 0) / 2
starView.text = NSNumber(value: model?.rate ?? 0).toString(maximumFractionDigits: 1, minimumFractionDigits: 1) starView.text = NSNumber(value: model?.rate ?? 0).toString(maximumFractionDigits: 1, minimumFractionDigits: 1)
if let text = model?.category?.first, text.count > 0 { if let text = model?.category?.first, text.count > 0 {
categoryView.isHidden = false categoryView.isHidden = false
categoryLabel.text = text categoryLabel.text = text
@ -27,19 +28,19 @@ class NRHomeNovelMustReadTodayCell: UICollectionViewCell {
} }
} }
} }
lazy var bgView: UIImageView = { lazy var bgView: UIImageView = {
let view = UIImageView(image: UIImage(named: "home_cell_bg_image_01")) let view = UIImageView(image: UIImage(named: "home_cell_bg_image_01"))
return view return view
}() }()
lazy var coverImageView: NRImageView = { lazy var coverImageView: NRImageView = {
let imageView = NRImageView() let imageView = NRImageView()
imageView.layer.cornerRadius = 4 imageView.layer.cornerRadius = 4
imageView.layer.masksToBounds = true imageView.layer.masksToBounds = true
return imageView return imageView
}() }()
lazy var categoryView: UIView = { lazy var categoryView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = .black.withAlphaComponent(0.05) view.backgroundColor = .black.withAlphaComponent(0.05)
@ -47,21 +48,21 @@ class NRHomeNovelMustReadTodayCell: UICollectionViewCell {
view.layer.masksToBounds = true view.layer.masksToBounds = true
return view return view
}() }()
lazy var categoryLabel: UILabel = { lazy var categoryLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .font(ofSize: 10, weight: .regular) label.font = .font(ofSize: 10, weight: .regular)
label.textColor = .black.withAlphaComponent(0.5) label.textColor = .black.withAlphaComponent(0.5)
return label return label
}() }()
lazy var titleLabel: UILabel = { lazy var titleLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .font(ofSize: 14, weight: .medium) label.font = .font(ofSize: 14, weight: .medium)
label.textColor = .black label.textColor = .black
return label return label
}() }()
lazy var desLabel: UILabel = { lazy var desLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .font(ofSize: 10, weight: .regular) label.font = .font(ofSize: 10, weight: .regular)
@ -69,17 +70,19 @@ class NRHomeNovelMustReadTodayCell: UICollectionViewCell {
label.numberOfLines = 2 label.numberOfLines = 2
return label return label
}() }()
lazy var readNowBgView: UIView = { lazy var readNowBgView: UIView = {
let view = NRGradientView() let view = NRGradientView()
view.colors = [UIColor.F_3912_F.cgColor, UIColor.FF_4_A_4_A.cgColor, UIColor.FA_9_B_1_F.cgColor] view.colors = [
UIColor.F_3912_F.cgColor, UIColor.FF_4_A_4_A.cgColor, UIColor.FA_9_B_1_F.cgColor,
]
view.startPoint = .init(x: 0, y: 0.5) view.startPoint = .init(x: 0, y: 0.5)
view.endPoint = .init(x: 1, y: 0.5) view.endPoint = .init(x: 1, y: 0.5)
view.layer.cornerRadius = 8 view.layer.cornerRadius = 8
view.layer.masksToBounds = true view.layer.masksToBounds = true
return view return view
}() }()
lazy var readNowLabel: UILabel = { lazy var readNowLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .font(ofSize: 14, weight: .medium) label.font = .font(ofSize: 14, weight: .medium)
@ -87,17 +90,17 @@ class NRHomeNovelMustReadTodayCell: UICollectionViewCell {
label.text = "Read Now".localized label.text = "Read Now".localized
return label return label
}() }()
lazy var starView: NRStarGradeView = { lazy var starView: NRStarGradeView = {
let view = NRStarGradeView() let view = NRStarGradeView()
return view return view
}() }()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.contentView.layer.cornerRadius = 12 self.contentView.layer.cornerRadius = 12
self.contentView.layer.masksToBounds = true self.contentView.layer.masksToBounds = true
categoryLabel.text = "Satisfying" categoryLabel.text = "Satisfying"
titleLabel.text = "A Strike to the Heart" titleLabel.text = "A Strike to the Heart"
desLabel.text = "Haunted by fading memories, a man navigates a labyrinth of dreams and reality, uncovering truths that blur the line between past and present." desLabel.text = "Haunted by fading memories, a man navigates a labyrinth of dreams and reality, uncovering truths that blur the line between past and present."
@ -109,11 +112,11 @@ class NRHomeNovelMustReadTodayCell: UICollectionViewCell {
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
} }
extension NRHomeNovelMustReadTodayCell { extension NRHomeNovelMustReadTodayCell {
private func nr_setupUI() { private func nr_setupUI() {
contentView.addSubview(bgView) contentView.addSubview(bgView)
contentView.addSubview(coverImageView) contentView.addSubview(coverImageView)
@ -124,57 +127,57 @@ extension NRHomeNovelMustReadTodayCell {
contentView.addSubview(desLabel) contentView.addSubview(desLabel)
contentView.addSubview(readNowBgView) contentView.addSubview(readNowBgView)
readNowBgView.addSubview(readNowLabel) readNowBgView.addSubview(readNowLabel)
bgView.snp.makeConstraints { make in bgView.snp.makeConstraints { make in
make.edges.equalToSuperview() make.edges.equalToSuperview()
} }
coverImageView.snp.makeConstraints { make in coverImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12) make.left.equalToSuperview().offset(12)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
make.width.equalTo(100) make.width.equalTo(100)
make.height.equalTo(150) make.height.equalTo(150)
} }
categoryView.snp.makeConstraints { make in categoryView.snp.makeConstraints { make in
make.left.equalTo(coverImageView.snp.right).offset(12) make.left.equalTo(coverImageView.snp.right).offset(12)
make.right.lessThanOrEqualToSuperview().offset(-12) make.right.lessThanOrEqualToSuperview().offset(-12)
make.top.equalTo(coverImageView) make.top.equalTo(coverImageView)
make.height.equalTo(20) make.height.equalTo(20)
} }
categoryLabel.snp.makeConstraints { make in categoryLabel.snp.makeConstraints { make in
make.center.equalToSuperview() make.center.equalToSuperview()
make.left.equalToSuperview().offset(8) make.left.equalToSuperview().offset(8)
} }
titleLabel.snp.makeConstraints { make in titleLabel.snp.makeConstraints { make in
make.left.equalTo(categoryView) make.left.equalTo(categoryView)
make.top.equalTo(coverImageView).offset(24) make.top.equalTo(coverImageView).offset(24)
make.right.lessThanOrEqualToSuperview().offset(-12) make.right.lessThanOrEqualToSuperview().offset(-12)
} }
starView.snp.makeConstraints { make in starView.snp.makeConstraints { make in
make.left.equalTo(titleLabel) make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(6) make.top.equalTo(titleLabel.snp.bottom).offset(6)
} }
desLabel.snp.makeConstraints { make in desLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel) make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(33) make.top.equalTo(titleLabel.snp.bottom).offset(33)
make.right.lessThanOrEqualToSuperview().offset(-12) make.right.lessThanOrEqualToSuperview().offset(-12)
} }
readNowBgView.snp.makeConstraints { make in readNowBgView.snp.makeConstraints { make in
make.left.equalTo(titleLabel) make.left.equalTo(titleLabel)
make.bottom.equalTo(coverImageView) make.bottom.equalTo(coverImageView)
make.right.equalToSuperview().offset(-12) make.right.equalToSuperview().offset(-12)
make.height.equalTo(36) make.height.equalTo(36)
} }
readNowLabel.snp.makeConstraints { make in readNowLabel.snp.makeConstraints { make in
make.center.equalToSuperview() make.center.equalToSuperview()
} }
} }
} }

View File

@ -5,82 +5,88 @@
// Created by on 2025/11/24. // Created by on 2025/11/24.
// //
import UIKit import FSPagerView
import SnapKit import SnapKit
import UIKit
import YYCategories import YYCategories
class NRHomeNovelMustReadTodayView: NRHomeNovelHeaderContentView { class NRHomeNovelMustReadTodayView: NRHomeNovelHeaderContentView {
var dataArr: [NRNovelModel] = [] { var dataArr: [NRNovelModel] = [] {
didSet { didSet {
self.collectionView.reloadData() self.pagerView.reloadData()
} }
} }
lazy var pagerView: FSPagerView = {
lazy var collectionViewLayout: UICollectionViewFlowLayout = { let pagerView = FSPagerView()
let layout = UICollectionViewFlowLayout() pagerView.delegate = self
layout.scrollDirection = .horizontal pagerView.dataSource = self
layout.itemSize = .init(width: 316, height: 174) //
layout.minimumLineSpacing = 16 pagerView.isInfinite = true
return layout //
pagerView.automaticSlidingInterval = 5.0
// item
pagerView.interitemSpacing = 16
// item
pagerView.itemSize = CGSize(width: 316, height: 174)
// Transformer
pagerView.transformer = NRHomeMustReadTodayTransformer(type: .linear)
// Cell
pagerView.register(NRHomeNovelMustReadTodayCell.self, forCellWithReuseIdentifier: "cell")
return pagerView
}() }()
lazy var collectionView: NRCollectionView = {
let collectionView = NRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.showsHorizontalScrollIndicator = false
collectionView.contentInset = .init(top: 0, left: 16, bottom: 0, right: 16)
collectionView.register(NRHomeNovelMustReadTodayCell.self, forCellWithReuseIdentifier: "cell")
return collectionView
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
self.titleLabel.text = "Must-Read Today".localized self.titleLabel.text = "Must-Read Today".localized
nr_setupUI() nr_setupUI()
} }
@MainActor required init?(coder: NSCoder) { @MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
} }
extension NRHomeNovelMustReadTodayView { extension NRHomeNovelMustReadTodayView {
private func nr_setupUI() { private func nr_setupUI() {
contentView.addSubview(collectionView) contentView.addSubview(pagerView)
collectionView.snp.makeConstraints { make in pagerView.snp.makeConstraints { make in
make.left.right.top.equalToSuperview() make.left.right.top.equalToSuperview()
make.bottom.equalToSuperview() make.bottom.equalToSuperview()
make.height.equalTo(self.collectionViewLayout.itemSize.height) make.height.equalTo(174)
} }
} }
} }
//MARK: UICollectionViewDelegate UICollectionViewDataSource // MARK: - FSPagerViewDataSource, FSPagerViewDelegate
extension NRHomeNovelMustReadTodayView: UICollectionViewDelegate, UICollectionViewDataSource { extension NRHomeNovelMustReadTodayView: FSPagerViewDataSource, FSPagerViewDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { func numberOfItems(in pagerView: FSPagerView) -> Int {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! NRHomeNovelMustReadTodayCell
cell.model = self.dataArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.dataArr.count return self.dataArr.count
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
let cell =
pagerView.dequeueReusableCell(withReuseIdentifier: "cell", at: index)
as! NRHomeNovelMustReadTodayCell
cell.model = self.dataArr[index]
return cell
}
func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int) {
pagerView.deselectItem(at: index, animated: true)
let vc = NRNovelDetailViewController() let vc = NRNovelDetailViewController()
vc.novelId = dataArr[indexPath.row].id ?? "" vc.novelId = dataArr[index].id ?? ""
self.viewController?.navigationController?.pushViewController(vc, animated: true) self.viewController?.navigationController?.pushViewController(vc, animated: true)
} }
// UICollectionViewContentInset FSPagerView itemSize transformer
// transform
} }

View File

@ -33,7 +33,7 @@ class NRReadChapterCatalogModel: NSObject, SmartCodable {
func parserEmpty() { func parserEmpty() {
let chapterModel = NRReadChapterModel() let chapterModel = NRReadChapterModel()
if self.is_lock == true { if self.is_lock == true {
chapterModel.parserEmpty("Not unlocked yet".localized) chapterModel.parserEmpty("Chapter Locked".localized)
} else { } else {
chapterModel.parserEmpty("Loading".localized) chapterModel.parserEmpty("Loading".localized)
} }

View File

@ -73,7 +73,7 @@ class NRReadChapterModel: NSObject, SmartCodable {
/// ///
func parserEmpty(_ text: String) { func parserEmpty(_ text: String) {
fullContent = NSMutableAttributedString(string: "\n\n\n\n\n" + text, attributes: NRNovelReadSetManager.manager.attributes(isTitle: true)) fullContent = NSMutableAttributedString(string: "\n\n\n\n\n" + text, attributes: NRNovelReadSetManager.manager.attributes(isTitle: false))
let pageModel = NRReadPageModel() let pageModel = NRReadPageModel()
pageModel.content = fullContent pageModel.content = fullContent

View File

@ -201,10 +201,10 @@ extension NRNovelReadViewModel {
self.vc?.loadData() self.vc?.loadData()
} }
view.didDismissHandle = { [weak self] in // view.didDismissHandle = { [weak self] in
guard let self = self else { return } // guard let self = self else { return }
self.showVipRetainAlert(catalogModel) // self.showVipRetainAlert(catalogModel)
} // }
view.present(in: nil) view.present(in: nil)
self.popView = view self.popView = view

View File

@ -76,7 +76,7 @@
"alert_title_01" = "Recommend this book?"; "alert_title_01" = "Recommend this book?";
"alert_detail_01" = "Help us share this story with others."; "alert_detail_01" = "Help us share this story with others.";
"Yes, Recommend" = "Yes, Recommend"; "Yes, Recommend" = "Yes, Recommend";
"Not unlocked yet" = "Not unlocked yet"; "Chapter Locked" = "Chapter Locked";
"No data" = "No data"; "No data" = "No data";
"Coins" = "Coins"; "Coins" = "Coins";
"Bonus" = "Bonus"; "Bonus" = "Bonus";