滑动返回优化

This commit is contained in:
澜声世纪 2025-12-19 17:48:16 +08:00
parent 067bba0814
commit 6ecceff7a9
25 changed files with 187 additions and 49 deletions

View File

@ -51,11 +51,13 @@ struct NRNovelAPI {
///
static func requestUploadRecord(_ id: String, chapterId: String) {
var param = NRNetwork.Parameters(path: "/novel/watchProgressReport")
// var param = NRNetwork.Parameters(path: "/novel/watchProgressReport")
var param = NRNetwork.Parameters(path: "/createHistory")
param.isToast = false
param.parameters = [
"short_play_id" : id,
"short_play_video_id" : chapterId
// "short_play_video_id" : chapterId
"video_id" : chapterId
]
NRNetwork.request(parameters: param) { (response: NRNetwork.Response<String>) in

View File

@ -34,10 +34,22 @@ class NRProgressView: UIView {
///
private var panProgress: CGFloat = 0
var progressColor: UIColor = .black.withAlphaComponent(0.25)
var currentProgress: UIColor = .F_9710_D
var progressColor: UIColor = .black.withAlphaComponent(0.25) {
didSet {
setNeedsDisplay()
}
}
var currentProgress: UIColor = .F_9710_D {
didSet {
setNeedsDisplay()
}
}
var lineWidth: CGFloat = 4
var lineWidth: CGFloat = 4 {
didSet {
setNeedsDisplay()
}
}
///
var isLoading = false {
@ -53,7 +65,11 @@ class NRProgressView: UIView {
}
}
var thumbImage: UIImage?
var thumbImage: UIImage? {
didSet {
setNeedsDisplay()
}
}
var insets: UIEdgeInsets = .init(top: 0, left: 15, bottom: 0, right: 15) {
didSet {

View File

@ -7,8 +7,22 @@
import UIKit
protocol NRScrollViewDelegate: AnyObject {
func nr_gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool?
}
extension NRScrollViewDelegate {
func nr_gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool? {
return nil
}
}
class NRScrollView: UIScrollView {
weak var nr_delegate: NRScrollViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
self.contentInsetAdjustmentBehavior = .never
@ -18,4 +32,24 @@ class NRScrollView: UIScrollView {
super.init(coder: coder)
}
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let result = self.nr_delegate?.nr_gestureRecognizerShouldBegin(gestureRecognizer) {
return result
}
let result = super.gestureRecognizerShouldBegin(gestureRecognizer)
return result
}
}
class NRPagerScrollView: NRScrollView {
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let result = super.gestureRecognizerShouldBegin(gestureRecognizer)
guard let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer else { return result }
let translation = panGestureRecognizer.translation(in: self)
if translation.x > 0, self.contentOffset.x == 0 {
return false
}
return result
}
}

View File

@ -55,7 +55,18 @@ class NRTableView: UITableView, UIGestureRecognizerDelegate {
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return shouldRecognizeSimultaneously
guard shouldRecognizeSimultaneously else { return false }
guard gestureRecognizer.isKind(of: UIPanGestureRecognizer.self) && otherGestureRecognizer.isKind(of: UIPanGestureRecognizer.self) else { return false }
var superview = otherGestureRecognizer.view
while superview != nil {
if superview == self {
return true
}
superview = superview?.superview
}
return false
}
}

View File

@ -101,6 +101,7 @@ extension NRNovelGenresCell {
categoryView.snp.makeConstraints { make in
make.left.equalToSuperview()
make.right.lessThanOrEqualToSuperview()
make.bottom.equalToSuperview()
}

View File

@ -12,12 +12,14 @@ class NRHomeCategoryTagView: UIView {
override var intrinsicContentSize: CGSize {
return .init(width: 10, height: 20)
let textWidth = self.categoryLabel.sizeThatFits(.init(width: UIScreen.width - 50, height: 20)).width
return .init(width: textWidth + 16, height: 20)
}
var text: String? {
set {
categoryLabel.text = newValue
self.invalidateIntrinsicContentSize()
}
get {
return categoryLabel.text

View File

@ -100,6 +100,7 @@ extension NRHomeNovelListCell {
categooryView.snp.makeConstraints { make in
make.bottom.equalToSuperview()
make.left.equalToSuperview()
make.right.lessThanOrEqualToSuperview()
}
}

View File

@ -114,6 +114,7 @@ extension NRHomeNovelListTextCell {
categoryLabel.snp.makeConstraints { make in
make.left.equalTo(nameLabel)
make.right.lessThanOrEqualToSuperview().offset(-8)
make.bottom.equalTo(coverImageView).offset(-7)
}
}

View File

@ -138,6 +138,7 @@ extension NRHomeNovelMustReadTodayCell {
categoryView.snp.makeConstraints { make in
make.left.equalTo(coverImageView.snp.right).offset(12)
make.right.lessThanOrEqualToSuperview().offset(-12)
make.top.equalTo(coverImageView)
make.height.equalTo(20)
}

View File

@ -114,6 +114,7 @@ extension NRHomeNovelNextViewCell {
categoryView.snp.makeConstraints { make in
make.left.equalToSuperview()
make.right.lessThanOrEqualToSuperview()
// make.top.equalTo(titleLabel.snp.bottom).offset(4)
make.bottom.equalToSuperview()
make.height.equalTo(20)

View File

@ -122,6 +122,7 @@ extension NRNovelHistoryCell {
categoryView.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.right.lessThanOrEqualToSuperview().offset(60)
make.bottom.equalToSuperview().offset(-7.5)
}

View File

@ -47,6 +47,7 @@ class NRDetailRechargeView: NRPanModalContentView {
didSet {
coinsView.shortPlayId = worksId
vipView.shortPlayId = worksId
self.requestRestore()
}
}
@ -54,6 +55,7 @@ class NRDetailRechargeView: NRPanModalContentView {
didSet {
coinsView.videoId = chapterId
vipView.videoId = chapterId
self.requestRestore()
}
}
@ -92,6 +94,10 @@ class NRDetailRechargeView: NRPanModalContentView {
private lazy var closeButton: UIButton = {
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
NRStatAPI.nr_requestEventStat(orderCode: nil, shortPlayId: self.worksId, videoId: self.chapterId, eventKey: .payTemplateDialog, errorMsg: nil, otherParamenters: [
"event_name" : "pay cancel"
])
Task {
await self.dismiss(animated: true)
}
@ -226,3 +232,23 @@ extension NRDetailRechargeView {
}
}
extension NRDetailRechargeView {
@objc private func requestRestore() {
guard let shortPlayId = self.worksId, let videoId = self.chapterId else { return }
NRIapManager.manager.restore(isLoding: false, shortPlayId: shortPlayId, videoId: videoId) { [weak self] isFinish, buyType in
if isFinish {
Task {
await NRLoginManager.manager.updateUserInfo()
}
self?.buyFinishHandle?()
Task {
await self?.dismiss(animated: true)
}
}
}
}
}

View File

@ -19,8 +19,20 @@ extension NRNovelDetailHeaderView {
stackView.nr_removeAllArrangedSubview()
model?.category?.forEach {
if let view = self.createCategoryView($0) {
var categoryTotalWidth: CGFloat = 0
let categoryArr = model?.category ?? []
for text in categoryArr {
if let view = self.createCategoryView(text) {
nrPrint(message: view.intrinsicContentSize)
let viewWidth = view.intrinsicContentSize.width
if categoryTotalWidth == 0 {
categoryTotalWidth += viewWidth
} else {
categoryTotalWidth += (viewWidth + self.stackView.spacing)
}
if categoryTotalWidth > UIScreen.width - 32 {
break
}
self.stackView.addArrangedSubview(view)
}
}

View File

@ -42,6 +42,8 @@ class NRNovelDetailHeaderView: UIView {
heatsDataView.num = CGFloat(model?.heats ?? 0)
wordDataView.num = CGFloat(model?.words ?? 0)
rateDataView.num = model?.rate ?? 0
contentsMoreButton.setNeedsUpdateConfiguration()
}
}
@ -144,9 +146,9 @@ class NRNovelDetailHeaderView: UIView {
}
}))
button.isHidden = true
button.setImage(UIImage(named: "arrow_bown_icon_01"), for: .normal)
button.setImage(UIImage(named: "arrow_right_icon_01"), for: .selected)
button.setImage(UIImage(named: "arrow_right_icon_01"), for: [.selected, .highlighted])
button.setImage(UIImage(named: "arrow_right_icon_01"), for: .normal)
button.setImage(UIImage(named: "arrow_bown_icon_01"), for: .selected)
button.setImage(UIImage(named: "arrow_bown_icon_01"), for: [.selected, .highlighted])
return button
}()
@ -187,10 +189,6 @@ class NRNovelDetailHeaderView: UIView {
configuration.image = UIImage(named: "arrow_right_icon_04")
configuration.imagePadding = 0
configuration.imagePlacement = .trailing
configuration.attributedTitle = AttributedString("Completed".localized, attributes: AttributeContainer([
.font : UIFont.font(ofSize: 12, weight: .regular),
.foregroundColor : UIColor.black.withAlphaComponent(0.5)
]))
let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
@ -198,6 +196,17 @@ class NRNovelDetailHeaderView: UIView {
vc.novelModel = self.model
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}))
button.configurationUpdateHandler = { [weak self] button in
guard let self = self else { return }
button.configuration?.attributedTitle = AttributedString("Completed".localized, attributes: AttributeContainer([
// button.configuration?.attributedTitle = AttributedString(self.model?.process ?? "", attributes: AttributeContainer([
.font : UIFont.font(ofSize: 12, weight: .regular),
.foregroundColor : UIColor.black.withAlphaComponent(0.5)
]))
}
return button
}()

View File

@ -265,10 +265,12 @@ class NRNovelReadBottomView: UIView {
prevButton.setTitleColor(.white, for: .normal)
nextButton.setTitleColor(.white, for: .normal)
contentView.backgroundColor = ._36353_A
progressView.progressColor = .white.withAlphaComponent(0.25)
} else {
prevButton.setTitleColor(.black, for: .normal)
nextButton.setTitleColor(.black, for: .normal)
contentView.backgroundColor = .white
progressView.progressColor = .black.withAlphaComponent(0.25)
}
catalogButton.setNeedsUpdateConfiguration()
nightButton.setNeedsUpdateConfiguration()

View File

@ -18,7 +18,7 @@ class NRNovelReadGradeView: NRPanModalContentView {
nameLabel.text = model?.name
starView.grade = (model?.rate ?? 0) / 2
starView.text = NSNumber(value: model?.rate ?? 0).toString(maximumFractionDigits: 1)
starView.text = NSNumber(value: model?.rate ?? 0).toString(maximumFractionDigits: 1, minimumFractionDigits: 1)
if let text = model?.category?.first, text.count > 0 {
categoryView.isHidden = false

View File

@ -25,8 +25,8 @@ class NRNovelReadStarGradeView: UIView {
gradeView.updateOnTouch = true
gradeView.fillMode = .full
} else {
label.text = "My Rate##".localizedReplace(text: NSNumber(value: self_rate).toString())
gradeView.grade = self_rate
label.text = "My Rate##".localizedReplace(text: NSNumber(value: self_rate).toString(maximumFractionDigits: 1, minimumFractionDigits: 1))
gradeView.grade = self_rate / 2
gradeView.updateOnTouch = false
gradeView.fillMode = .precise
}
@ -84,7 +84,7 @@ class NRNovelReadStarGradeView: UIView {
guard let id = self.model?.id else { return }
Task {
guard await NRNovelAPI.requestRateScore(id, stars: CGFloat(grade)) else { return}
self.model?.self_rate = grade
self.model?.self_rate = grade * 2
gradeView.isHidden = true
label.isHidden = true
finishView.isHidden = false

View File

@ -44,8 +44,6 @@ class NRNovelReadView: UIView {
// 使
backgroundColor = UIColor.clear
// 便
// backgroundColor = DZM_COLOR_ARC
}
///

View File

@ -17,14 +17,13 @@ class NRNovelDetailCatalogViewController: NRViewController {
totalChaptersLabel.text = "## Chapters".localizedReplace(text: "\(novelModel?.episode_total ?? 0)")
Task {
await requestDataArr()
}
}
}
lazy var dataArr: [NRReadChapterCatalogModel] = []
var isViewDidAppear = false
private lazy var lineView: UIView = {
let view = UIView()
@ -70,6 +69,10 @@ class NRNovelDetailCatalogViewController: NRViewController {
configNavigationBack("arrow_left_icon_05")
nr_setupUI()
Task {
await requestDataArr()
}
}
@ -79,7 +82,17 @@ class NRNovelDetailCatalogViewController: NRViewController {
self.nr_setNavigationStyle(titleColor: UINavigationBar.titleBlackColor)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if isViewDidAppear {
Task {
await requestDataArr()
}
} else {
isViewDidAppear = true
}
}
}

View File

@ -203,11 +203,10 @@ extension NRNovelReaderViewController {
}
let indexPath = self.indexPathToReadRecord()
let section = indexPath.section
self.viewModel.currentPageIndexPath = indexPath
let currentCatalogModel = self.viewModel.chapterCatalogList[section]
let currentCatalogModel = self.viewModel.chapterCatalogList[indexPath.section]
//
await self.viewModel.requestChapterData(currentCatalogModel)
@ -225,8 +224,6 @@ extension NRNovelReaderViewController {
//
let recordModel = self.viewModel.getReadRecord()
var tempCatalogModel: NRReadChapterCatalogModel?
//
var section = 0
var row = 0
@ -234,7 +231,6 @@ extension NRNovelReaderViewController {
for (index, model) in self.viewModel.chapterCatalogList.enumerated() {
if model.id == catalogModel.id {
section = index
tempCatalogModel = model
break
}
}
@ -243,6 +239,8 @@ extension NRNovelReaderViewController {
}
self.targetCatalogModel = nil
} else {
var tempCatalogModel: NRReadChapterCatalogModel?
if let recordModel = recordModel {
for (index, model) in self.viewModel.chapterCatalogList.enumerated() {
if model.id == recordModel.short_play_video_id {
@ -254,21 +252,23 @@ extension NRNovelReaderViewController {
if let page = recordModel.page {
row = page
}
//
if tempCatalogModel?.is_lock == true {
var tempIndex = 0
for (index, model) in self.viewModel.chapterCatalogList.enumerated() {
if model.is_lock == true {
break
}
tempIndex = index
}
section = tempIndex
row = 0
}
}
}
//
if tempCatalogModel?.is_lock == true {
var tempIndex = 0
for (index, model) in self.viewModel.chapterCatalogList.enumerated() {
if model.is_lock == true {
break
}
tempIndex = index
}
section = tempIndex
row = 0
}
return IndexPath(row: row, section: section)
}

View File

@ -167,7 +167,7 @@ extension NRNovelReadViewModel {
let lastTime = uploadRecordDate?.timeIntervalSince1970 ?? 0
let nowTime = Date().timeIntervalSince1970
if lastTime == 0 || nowTime - lastTime > 5 {//5
if lastTime == 0 || nowTime - lastTime > 1 {//5
uploadRecordDate = Date()
NRNovelAPI.requestUploadRecord(novelId, chapterId: catalogModel.id ?? "")
}

View File

@ -186,6 +186,9 @@ extension NRNovelReadViewModel {
private func _openRechargeView(_ payModel: NRPayDateModel, _ catalogModel: NRReadChapterCatalogModel) {
guard self.popView == nil else { return }
NRStatAPI.nr_requestEventStat(orderCode: nil, shortPlayId: self.novelId, videoId: catalogModel.id, eventKey: .payTemplateDialog, errorMsg: nil, otherParamenters: [
"event_name" : "pay open"
])
let view = NRDetailRechargeView()
view.payModel = payModel

View File

@ -115,4 +115,8 @@ extension NROrderRecordsPageViewController: JXSegmentedListContainerViewDataSour
return self.titles.count
}
func scrollViewClass(in listContainerView: JXSegmentedListContainerView) -> AnyClass {
return NRPagerScrollView.self
}
}

View File

@ -75,8 +75,8 @@ class NRNovelReadSetManager: NSObject {
return UIFont.font(ofSize: self.readSet.fontSize + 10, weight: .semibold)
}
var miniFontSize: CGFloat = 12
var maxFontSize: CGFloat = 24
let miniFontSize: CGFloat = 12
let maxFontSize: CGFloat = 24
var isNight: Bool {
return readSet.isNight

View File

@ -33,7 +33,7 @@ extension CGCoins {
let lastTime = uploadRecordDate?.timeIntervalSince1970 ?? 0
let nowTime = Date().timeIntervalSince1970
if lastTime == 0 || nowTime - lastTime > 5 {
if lastTime == 0 || nowTime - lastTime > 1 {
uploadRecordDate = Date()
XMust.requestUploadRecord(novelId, chapterId: catalogModel.id ?? "")
}