1
@ -122,7 +122,6 @@
|
||||
F34349082ED945DA00AA7E70 /* NRCoreText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34349072ED945DA00AA7E70 /* NRCoreText.swift */; };
|
||||
F343490A2ED96EE600AA7E70 /* NRNovelReadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34349092ED96EE600AA7E70 /* NRNovelReadView.swift */; };
|
||||
F343490C2ED9751800AA7E70 /* NRReadChapterCatalogModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343490B2ED9751800AA7E70 /* NRReadChapterCatalogModel.swift */; };
|
||||
F343490E2ED9A5D000AA7E70 /* NRNovelReadMoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343490D2ED9A5D000AA7E70 /* NRNovelReadMoreView.swift */; };
|
||||
F34349102ED9A77A00AA7E70 /* NRPanModalContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343490F2ED9A77A00AA7E70 /* NRPanModalContentView.swift */; };
|
||||
F34349122EDA84F100AA7E70 /* NRProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34349112EDA84F100AA7E70 /* NRProgressView.swift */; };
|
||||
F34349142EDA9AE900AA7E70 /* NRNovelReadSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34349132EDA9AE900AA7E70 /* NRNovelReadSettingView.swift */; };
|
||||
@ -303,7 +302,6 @@
|
||||
F34349072ED945DA00AA7E70 /* NRCoreText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRCoreText.swift; sourceTree = "<group>"; };
|
||||
F34349092ED96EE600AA7E70 /* NRNovelReadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadView.swift; sourceTree = "<group>"; };
|
||||
F343490B2ED9751800AA7E70 /* NRReadChapterCatalogModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRReadChapterCatalogModel.swift; sourceTree = "<group>"; };
|
||||
F343490D2ED9A5D000AA7E70 /* NRNovelReadMoreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadMoreView.swift; sourceTree = "<group>"; };
|
||||
F343490F2ED9A77A00AA7E70 /* NRPanModalContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRPanModalContentView.swift; sourceTree = "<group>"; };
|
||||
F34349112EDA84F100AA7E70 /* NRProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRProgressView.swift; sourceTree = "<group>"; };
|
||||
F34349132EDA9AE900AA7E70 /* NRNovelReadSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadSettingView.swift; sourceTree = "<group>"; };
|
||||
@ -842,7 +840,6 @@
|
||||
F34348FC2ED8561300AA7E70 /* NRNovelReadContentBottomView.swift */,
|
||||
F34348FE2ED85BF200AA7E70 /* NRReadBatteryView.swift */,
|
||||
F34349092ED96EE600AA7E70 /* NRNovelReadView.swift */,
|
||||
F343490D2ED9A5D000AA7E70 /* NRNovelReadMoreView.swift */,
|
||||
F34349132EDA9AE900AA7E70 /* NRNovelReadSettingView.swift */,
|
||||
F34349172EDAA02900AA7E70 /* NRNovelReadSettingItemView.swift */,
|
||||
F34349152EDA9FC700AA7E70 /* NRReadSettingBrightnessView.swift */,
|
||||
@ -1133,7 +1130,6 @@
|
||||
F34348F72ED84B0D00AA7E70 /* NRNovelReaderViewController+Page.swift in Sources */,
|
||||
039810902ED060EF0006E317 /* NRViewController.swift in Sources */,
|
||||
039810702ED053910006E317 /* String+NRAdd.swift in Sources */,
|
||||
F343490E2ED9A5D000AA7E70 /* NRNovelReadMoreView.swift in Sources */,
|
||||
039810932ED062CE0006E317 /* NRHomeViewController.swift in Sources */,
|
||||
039810BC2ED43C8E0006E317 /* NRReadWhatViewTransformer.swift in Sources */,
|
||||
039810D02ED54D370006E317 /* NRHomeCategoryTagView.swift in Sources */,
|
||||
|
||||
@ -80,8 +80,10 @@ class NRNetwork: NSObject {
|
||||
completion?(res)
|
||||
} else {
|
||||
if code == 402, parameters.isToast {
|
||||
DispatchQueue.main.async {
|
||||
NRToast.show(text: "network_error_1".localized)
|
||||
}
|
||||
}
|
||||
//重新获取token
|
||||
self.requestToken { token in
|
||||
if token != nil {
|
||||
@ -121,9 +123,11 @@ class NRNetwork: NSObject {
|
||||
let response: NRNetwork.Response<T> = _deserialize(data: tempData)
|
||||
if !response.isSuccess{
|
||||
if parameters.isToast {
|
||||
DispatchQueue.main.async {
|
||||
NRToast.show(text: response.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
completion?(response)
|
||||
|
||||
} catch {
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
import UIKit
|
||||
import SnapKit
|
||||
import collection_view_layouts
|
||||
import YYCategories
|
||||
|
||||
class NRHomeNovelHotTagView: UIView {
|
||||
|
||||
@ -129,6 +130,12 @@ extension NRHomeNovelHotTagView: UICollectionViewDelegate, UICollectionViewDataS
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
let vc = NRNovelGenresViewController()
|
||||
vc.model = self.dataArr[indexPath.row]
|
||||
self.viewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRHomeNovelHotTagView: LayoutDelegate {
|
||||
|
||||
@ -16,7 +16,7 @@ class NRMeHeaderView: UITableViewHeaderFooterView {
|
||||
let imageView = NRImageView()
|
||||
imageView.layer.cornerRadius = 30
|
||||
imageView.layer.borderWidth = 1
|
||||
imageView.layer.borderColor = UIColor.black.withAlphaComponent(0.15).cgColor
|
||||
imageView.layer.borderColor = UIColor.white.withAlphaComponent(0.5).cgColor
|
||||
return imageView
|
||||
}()
|
||||
|
||||
|
||||
@ -1,160 +0,0 @@
|
||||
//
|
||||
// NRNovelReadMoreView.swift
|
||||
// ReaderHive
|
||||
//
|
||||
// Created by 长沙鸿瑶 on 2025/11/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import HWPanModal
|
||||
import SnapKit
|
||||
|
||||
class NRNovelReadMoreView: NRPanModalContentView {
|
||||
|
||||
weak var viewModel: NRNovelReadViewModel? {
|
||||
didSet {
|
||||
let progress = CGFloat(viewModel?.currentPageIndexPath.section ?? 0) / CGFloat(viewModel?.chapterCatalogList.count ?? 0)
|
||||
self.progressView.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
lazy var catalogButton: UIButton = {
|
||||
let button = self.createButton(title: "Catalog".localized, icon: UIImage(named: "catalog_icon_01"))
|
||||
return button
|
||||
}()
|
||||
|
||||
lazy var nightButton: UIButton = {
|
||||
let button = self.createButton(title: "Night".localized, icon: UIImage(named: "night_icon_01"))
|
||||
return button
|
||||
}()
|
||||
|
||||
lazy var settingsButton: UIButton = {
|
||||
let button = self.createButton(title: "Settings".localized, icon: UIImage(named: "settings_icon_01"))
|
||||
button.addAction(UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.dismiss(animated: true) { }
|
||||
|
||||
self.viewModel?.showSettingView()
|
||||
}), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
lazy var stackView: UIStackView = {
|
||||
let view = UIStackView(arrangedSubviews: [catalogButton, nightButton, settingsButton])
|
||||
view.axis = .horizontal
|
||||
view.distribution = .equalSpacing
|
||||
return view
|
||||
}()
|
||||
|
||||
lazy var prevLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .black
|
||||
label.text = "Prev".localized
|
||||
label.setContentHuggingPriority(.required, for: .horizontal)
|
||||
label.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var nextLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .black
|
||||
label.text = "Next".localized
|
||||
label.setContentHuggingPriority(.required, for: .horizontal)
|
||||
label.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var progressView: NRProgressView = {
|
||||
let view = NRProgressView()
|
||||
view.thumbImage = UIImage(named: "Progress-handle")
|
||||
view.insets = .init(top: 6, left: 0, bottom: 6, right: 0)
|
||||
view.panFinish = { [weak self] progress in
|
||||
self?.progressView.progress = progress
|
||||
let totalCount = self?.viewModel?.chapterCatalogList.count ?? 0
|
||||
let index = Int(floor(CGFloat(totalCount) * progress))
|
||||
self?.viewModel?.skip(chapterIndex: index)
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
contentHeight = UIScreen.safeBottom + 105
|
||||
|
||||
backgroundColor = .white
|
||||
|
||||
nr_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func backgroundConfig() -> HWBackgroundConfig {
|
||||
let config = HWBackgroundConfig()
|
||||
config.backgroundAlpha = 0
|
||||
return config
|
||||
}
|
||||
|
||||
override func cornerRadius() -> CGFloat {
|
||||
return 0
|
||||
}
|
||||
|
||||
private func createButton(title: String, icon: UIImage?) -> UIButton {
|
||||
var configuration = UIButton.Configuration.plain()
|
||||
configuration.contentInsets = .zero
|
||||
configuration.image = icon
|
||||
configuration.imagePadding = 2
|
||||
configuration.imagePlacement = .top
|
||||
configuration.attributedTitle = AttributedString(title, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 10, weight: .regular),
|
||||
.foregroundColor : UIColor.black
|
||||
]))
|
||||
|
||||
let button = UIButton(configuration: configuration)
|
||||
button.snp.makeConstraints { make in
|
||||
make.width.equalTo(72)
|
||||
}
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NRNovelReadMoreView {
|
||||
|
||||
private func nr_setupUI() {
|
||||
addSubview(stackView)
|
||||
addSubview(progressView)
|
||||
addSubview(prevLabel)
|
||||
addSubview(nextLabel)
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(28)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(48)
|
||||
make.height.equalTo(56)
|
||||
}
|
||||
|
||||
progressView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(8)
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualTo(nextLabel.snp.left).offset(0)
|
||||
make.left.greaterThanOrEqualTo(prevLabel.snp.right).offset(0)
|
||||
}
|
||||
|
||||
prevLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(progressView)
|
||||
make.left.equalToSuperview().offset(20)
|
||||
}
|
||||
|
||||
nextLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(progressView)
|
||||
make.right.equalToSuperview().offset(-20)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -103,10 +103,13 @@ class NRNovelReaderViewController: NRViewController {
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
Task {
|
||||
await NRLoginManager.manager.updateUserInfo()
|
||||
//防止自动锁屏
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
UIApplication.shared.isIdleTimerDisabled = false
|
||||
}
|
||||
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
@ -190,6 +193,26 @@ extension NRNovelReaderViewController {
|
||||
|
||||
guard !self.viewModel.chapterCatalogList.isEmpty else { return }
|
||||
|
||||
|
||||
let indexPath = self.indexPathToReadRecord()
|
||||
let section = indexPath.section
|
||||
|
||||
self.viewModel.currentPageIndexPath = indexPath
|
||||
|
||||
let currentCatalogModel = self.viewModel.chapterCatalogList[section]
|
||||
|
||||
//获取章节数据
|
||||
await self.viewModel.requestChapterData(currentCatalogModel)
|
||||
|
||||
//校验索引,避免越界
|
||||
self.viewModel.checkCurrentIndexPath()
|
||||
|
||||
self.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
///根据历史记录获取索引
|
||||
private func indexPathToReadRecord() -> IndexPath {
|
||||
//读取历史记录
|
||||
let recordModel = self.viewModel.getReadRecord()
|
||||
|
||||
@ -221,19 +244,7 @@ extension NRNovelReaderViewController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.viewModel.currentPageIndexPath = IndexPath(row: row, section: section)
|
||||
|
||||
let currentCatalogModel = self.viewModel.chapterCatalogList[section]
|
||||
|
||||
//获取章节数据
|
||||
await self.viewModel.requestChapterData(currentCatalogModel)
|
||||
|
||||
//校验索引,避免越界
|
||||
self.viewModel.checkCurrentIndexPath()
|
||||
|
||||
self.reloadData()
|
||||
}
|
||||
return IndexPath(row: row, section: section)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -124,9 +124,6 @@ extension NRNovelReadViewModel {
|
||||
|
||||
///显示更多工具栏
|
||||
func showMoreView() {
|
||||
// let view = NRNovelReadMoreView()
|
||||
// view.viewModel = self
|
||||
// view.present(in: nil)
|
||||
guard let model = self.novelModel else { return }
|
||||
|
||||
let view = NRNovelReadGradeView()
|
||||
|
||||
@ -45,6 +45,7 @@ class NRLocalizedManager: NSObject {
|
||||
// }
|
||||
// return key
|
||||
return "en"
|
||||
// return "zh"
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: LocalizedUserDefaultsKey)
|
||||
|
||||
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 384 KiB After Width: | Height: | Size: 556 KiB |
@ -5,12 +5,12 @@
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "EverRead@2x.png",
|
||||
"filename" : "单文字LOGO(ReaderHive)@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "EverRead@3x.png",
|
||||
"filename" : "单文字LOGO(ReaderHive)@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 16 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/home_title_image.imageset/单文字LOGO(ReaderHive)@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
ReaderHive/Source/Assets.xcassets/Image/home_title_image.imageset/单文字LOGO(ReaderHive)@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 4.1 KiB |