diff --git a/ReaderHive.xcodeproj/project.pbxproj b/ReaderHive.xcodeproj/project.pbxproj index e499dec..6353219 100644 --- a/ReaderHive.xcodeproj/project.pbxproj +++ b/ReaderHive.xcodeproj/project.pbxproj @@ -93,6 +93,11 @@ 85ACA3F92F28A7CD009D52B0 /* NRNovelReadViewModel+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85ACA3F82F28A7C8009D52B0 /* NRNovelReadViewModel+View.swift */; }; 85B5B3982F30732800700E83 /* NRPayRetainAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B3972F30732800700E83 /* NRPayRetainAlert.swift */; }; 85B5B39A2F30790600700E83 /* NRBorderLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B3992F30790600700E83 /* NRBorderLabel.swift */; }; + 85B5B39C2F31DAC100700E83 /* NRNovelReadRecommendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B39B2F31DAC100700E83 /* NRNovelReadRecommendViewController.swift */; }; + 85B5B39E2F31F36100700E83 /* NRNovelReadFinishInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B39D2F31F36100700E83 /* NRNovelReadFinishInfoView.swift */; }; + 85B5B3A02F331D8700700E83 /* NRNovelReadRecommendCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B39F2F331D8700700E83 /* NRNovelReadRecommendCell.swift */; }; + 85B5B3A22F34378600700E83 /* NRNovelReadFinishTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B3A12F34378600700E83 /* NRNovelReadFinishTextCell.swift */; }; + 85B5B3A42F3445BC00700E83 /* NRNovelReadFinishFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B5B3A32F3445BC00700E83 /* NRNovelReadFinishFooterView.swift */; }; 85C1786B2F050AA400A8A76E /* Poppins-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 85C178682F050AA400A8A76E /* Poppins-Medium.ttf */; }; 85C1786C2F050AA400A8A76E /* Poppins-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 85C1786A2F050AA400A8A76E /* Poppins-SemiBold.ttf */; }; 85C1786D2F050AA400A8A76E /* Poppins-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 85C178672F050AA400A8A76E /* Poppins-Bold.ttf */; }; @@ -606,6 +611,11 @@ 85ACA3F82F28A7C8009D52B0 /* NRNovelReadViewModel+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NRNovelReadViewModel+View.swift"; sourceTree = ""; }; 85B5B3972F30732800700E83 /* NRPayRetainAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRPayRetainAlert.swift; sourceTree = ""; }; 85B5B3992F30790600700E83 /* NRBorderLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRBorderLabel.swift; sourceTree = ""; }; + 85B5B39B2F31DAC100700E83 /* NRNovelReadRecommendViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadRecommendViewController.swift; sourceTree = ""; }; + 85B5B39D2F31F36100700E83 /* NRNovelReadFinishInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadFinishInfoView.swift; sourceTree = ""; }; + 85B5B39F2F331D8700700E83 /* NRNovelReadRecommendCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadRecommendCell.swift; sourceTree = ""; }; + 85B5B3A12F34378600700E83 /* NRNovelReadFinishTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadFinishTextCell.swift; sourceTree = ""; }; + 85B5B3A32F3445BC00700E83 /* NRNovelReadFinishFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRNovelReadFinishFooterView.swift; sourceTree = ""; }; 85C178672F050AA400A8A76E /* Poppins-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Bold.ttf"; sourceTree = ""; }; 85C178682F050AA400A8A76E /* Poppins-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Medium.ttf"; sourceTree = ""; }; 85C178692F050AA400A8A76E /* Poppins-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-Regular.ttf"; sourceTree = ""; }; @@ -2189,6 +2199,10 @@ F34990C62EDFCE500039E939 /* NRNovelReadGradeView.swift */, F34990FC2EE124CF0039E939 /* NRNovelReadStarGradeView.swift */, F34990F82EE118FC0039E939 /* NRNovelReadFinishHeaderView.swift */, + 85B5B3A32F3445BC00700E83 /* NRNovelReadFinishFooterView.swift */, + 85B5B39D2F31F36100700E83 /* NRNovelReadFinishInfoView.swift */, + 85B5B39F2F331D8700700E83 /* NRNovelReadRecommendCell.swift */, + 85B5B3A12F34378600700E83 /* NRNovelReadFinishTextCell.swift */, ); path = Reader; sourceTree = ""; @@ -2202,6 +2216,7 @@ F34990F42EE0346B0039E939 /* NRNovelReadBaseViewController.swift */, F34348F82ED855AA00AA7E70 /* NRNovelReadContentViewController.swift */, F34990F22EE02FD60039E939 /* NRNovelReadFinishViewController.swift */, + 85B5B39B2F31DAC100700E83 /* NRNovelReadRecommendViewController.swift */, ); path = Read; sourceTree = ""; @@ -2617,6 +2632,7 @@ 85606A922EEBB336005D989D /* NRCoinsPackConfirmItemView.swift in Sources */, 0398106A2ED0505D0006E317 /* NRNetworkReachableManager.swift in Sources */, F34348C32ED6A20700AA7E70 /* NRExploreNovelContentViewController.swift in Sources */, + 85B5B3A02F331D8700700E83 /* NRNovelReadRecommendCell.swift in Sources */, 85CF94232EEC08F4006467E3 /* NRCoinsPackClaimView.swift in Sources */, F34991292EE285660039E939 /* NRShowRecommendPop.swift in Sources */, 0373D9642ED5ABBC0017DCC7 /* NREmpty.swift in Sources */, @@ -2684,6 +2700,7 @@ F3B859892EE97E1F0095A9CC /* NRRewardCoinsViewController.swift in Sources */, 85CF945C2EF28433006467E3 /* NROpenAppModel.swift in Sources */, 039810CE2ED47A130006E317 /* CGMutablePath+NRRoundedCorner.swift in Sources */, + 85B5B39C2F31DAC100700E83 /* NRNovelReadRecommendViewController.swift in Sources */, F34348E72ED7F91C00AA7E70 /* NSNumber+NRAdd.swift in Sources */, F3B8597F2EE96F810095A9CC /* NRConsumptionRecordsViewController.swift in Sources */, F34349122EDA84F100AA7E70 /* NRProgressView.swift in Sources */, @@ -2836,6 +2853,7 @@ 85CF95F92EF3CC93006467E3 /* GAMRecommendThimraView.swift in Sources */, 85CF95FA2EF3CC93006467E3 /* EMEditView.swift in Sources */, 85CF95FB2EF3CC93006467E3 /* ITBaseController.swift in Sources */, + 85B5B3A22F34378600700E83 /* NRNovelReadFinishTextCell.swift in Sources */, 85CF95FC2EF3CC93006467E3 /* REMustManagerCell.swift in Sources */, 85CF95FD2EF3CC93006467E3 /* ECenterClaimView.swift in Sources */, 85CF95FE2EF3CC93006467E3 /* AGWElyonResult.swift in Sources */, @@ -2905,6 +2923,7 @@ 85CF963E2EF3CC93006467E3 /* NCYAterfallUnechoView.swift in Sources */, 85CF963F2EF3CC93006467E3 /* DLTitleView.swift in Sources */, 85CF96402EF3CC93006467E3 /* JVibeoView.swift in Sources */, + 85B5B39E2F31F36100700E83 /* NRNovelReadFinishInfoView.swift in Sources */, 85CF96412EF3CC93006467E3 /* CJBbfdebaffdController.swift in Sources */, 85CF96422EF3CC93006467E3 /* QMTextModuleCell.swift in Sources */, 85CF96432EF3CC93006467E3 /* BSModityAshed.swift in Sources */, @@ -2914,6 +2933,7 @@ 85CF96472EF3CC93006467E3 /* DRegisterEdit.swift in Sources */, 85CF96482EF3CC93006467E3 /* LYWindowLocalizableView.swift in Sources */, 85CF96492EF3CC93006467E3 /* HKIBrightnessView.swift in Sources */, + 85B5B3A42F3445BC00700E83 /* NRNovelReadFinishFooterView.swift in Sources */, 85CF964A2EF3CC93006467E3 /* BMGNovelView.swift in Sources */, F34349282EDD815D00AA7E70 /* NRNovelCatalogCell.swift in Sources */, 039810D22ED54F190006E317 /* NRHomeNovelListTextCell.swift in Sources */, diff --git a/ReaderHive/Base/Networking/API/NRNovelAPI.swift b/ReaderHive/Base/Networking/API/NRNovelAPI.swift index ba3f0bf..0ce3ed8 100644 --- a/ReaderHive/Base/Networking/API/NRNovelAPI.swift +++ b/ReaderHive/Base/Networking/API/NRNovelAPI.swift @@ -261,6 +261,46 @@ struct NRNovelAPI { } } + static func requestReadFinishRecommand(novelId: String) async -> NRNovelModel? { + + await withCheckedContinuation { continuation in + var param = NRNetwork.Parameters(path: "/novel/getRecommandOneDetails") + param.method = .get + param.parameters = [ + "short_play_id" : novelId, + ] + + NRNetwork.request(parameters: param) { (response: NRNetwork.Response) in + if response.isSuccess { + continuation.resume(returning: response.data) + } else { + continuation.resume(returning: nil) + } + } + } + + } + + static func requestReadRecommand(type: Int) async -> [NRNovelModel]? { + + await withCheckedContinuation { continuation in + var param = NRNetwork.Parameters(path: "/novel/getTypeRecommand") + param.method = .get + param.parameters = [ + "type" : type, + ] + + NRNetwork.request(parameters: param) { (response: NRNetwork.Response>) in + if response.isSuccess { + continuation.resume(returning: response.data?.list) + } else { + continuation.resume(returning: nil) + } + } + } + + } + } diff --git a/ReaderHive/Base/Networking/NRUrlPath.swift b/ReaderHive/Base/Networking/NRUrlPath.swift index 1ce4ed6..899571c 100644 --- a/ReaderHive/Base/Networking/NRUrlPath.swift +++ b/ReaderHive/Base/Networking/NRUrlPath.swift @@ -8,10 +8,10 @@ import UIKit #if DEBUG -//let NRBaseURL = "https://api-novel-test.guyantv.com" -//let NRBaseURLPrefix = "" -let NRBaseURL = "https://api-readerhive.readerhive.net" -let NRBaseURLPrefix = "/readerhive" +let NRBaseURL = "https://api-novel-test.guyantv.com" +let NRBaseURLPrefix = "" +//let NRBaseURL = "https://api-readerhive.readerhive.net" +//let NRBaseURLPrefix = "/readerhive" #else let NRBaseURL = "https://api-readerhive.readerhive.net" let NRBaseURLPrefix = "/readerhive" diff --git a/ReaderHive/Class/Home/V/NRStarGradeView.swift b/ReaderHive/Class/Home/V/NRStarGradeView.swift index d8beb74..5b5d67c 100644 --- a/ReaderHive/Class/Home/V/NRStarGradeView.swift +++ b/ReaderHive/Class/Home/V/NRStarGradeView.swift @@ -30,6 +30,13 @@ class NRStarGradeView: UIView { } } + var textColor = UIColor.black { + didSet { + settings.textColor = textColor + cosmosView.settings = settings + } + } + var filledImage: UIImage? = UIImage(named: "star_icon_02") { didSet { settings.filledImage = filledImage @@ -73,7 +80,7 @@ class NRStarGradeView: UIView { settings.starMargin = 4 settings.fillMode = fillMode settings.textFont = .font(ofSize: 12, weight: .regular) - settings.textColor = .black + settings.textColor = textColor settings.textMargin = 4 settings.minTouchRating = 1 settings.updateOnTouch = true diff --git a/ReaderHive/Class/Novel/M/NRNovelModel.swift b/ReaderHive/Class/Novel/M/NRNovelModel.swift index 8a7aa36..bf1448e 100644 --- a/ReaderHive/Class/Novel/M/NRNovelModel.swift +++ b/ReaderHive/Class/Novel/M/NRNovelModel.swift @@ -51,6 +51,8 @@ class NRNovelModel: NSObject, SmartCodable { var progress: NRNovelReadRecordModel? + var chapterInfo: NRReadChapterModel? + static func mappingForKey() -> [SmartKeyTransformer]? { return [ diff --git a/ReaderHive/Class/Novel/M/NRReadChapterCatalogModel.swift b/ReaderHive/Class/Novel/M/NRReadChapterCatalogModel.swift index 6037a94..e074c29 100644 --- a/ReaderHive/Class/Novel/M/NRReadChapterCatalogModel.swift +++ b/ReaderHive/Class/Novel/M/NRReadChapterCatalogModel.swift @@ -27,7 +27,25 @@ class NRReadChapterCatalogModel: NSObject, SmartCodable { ///章节详情 @IgnoredKey - var chapterModel: NRReadChapterModel? + var chapterModel: NRReadChapterModel? { + didSet { + chapterModel?.recommandPage = recommandPage + chapterModel?.finishPage = finishPage + } + } + + @IgnoredKey + var recommandPage: NRReadPageModel? { + didSet { + chapterModel?.recommandPage = recommandPage + } + } + @IgnoredKey + var finishPage: NRReadPageModel? { + didSet { + chapterModel?.finishPage = finishPage + } + } ///解析一个空白页面 func parserEmpty() { diff --git a/ReaderHive/Class/Novel/M/NRReadChapterModel.swift b/ReaderHive/Class/Novel/M/NRReadChapterModel.swift index 26469e9..c41c9f7 100644 --- a/ReaderHive/Class/Novel/M/NRReadChapterModel.swift +++ b/ReaderHive/Class/Novel/M/NRReadChapterModel.swift @@ -41,7 +41,10 @@ class NRReadChapterModel: NSObject, SmartCodable { @IgnoredKey var pageCount: Int = 0 - + @IgnoredKey + var recommandPage: NRReadPageModel? + @IgnoredKey + var finishPage: NRReadPageModel? static func mappingForKey() -> [SmartKeyTransformer]? { @@ -52,23 +55,32 @@ class NRReadChapterModel: NSObject, SmartCodable { ///解析数据 func parser() { - let tempAttributes = NRNovelReadSetManager.manager.attributes(isTitle: false, isPageing: true) + let tempAttributes = NRNovelReadSetManager.manager.textAttributes() guard !NSDictionary(dictionary: attributes).isEqual(to: tempAttributes) else { return } attributes = tempAttributes fullContent = fullContentAttrString() - var tempPageModel: NRReadPageModel? - if pageList?.last?.pageType != .textPart { - tempPageModel = pageList?.last - } + pageList = NRReadParser.pageing(attrString: fullContent, rect: NRNovelReadSetManager.manager.readRect) pageCount = pageList?.count ?? 0 - if let model = tempPageModel { - pageList?.append(model) + if let pageModel = self.recommandPage { + let pagePoint = pageModel.pagePoint ?? 0 + let page = Int(CGFloat(pageCount) * pagePoint) + pageList?.insert(pageModel, at: page) } + + if let pageModel = self.finishPage { + pageList?.append(pageModel) + } + } + + ///只解析文本,不解析标题 + func parserText(attributes: [NSAttributedString.Key : Any] = NRNovelReadSetManager.manager.textAttributes()) { + self.fullContent = NSMutableAttributedString(string: novel_txt ?? "", attributes: attributes) + pageList = NRReadParser.pageing(attrString: fullContent, rect: NRNovelReadSetManager.manager.readRect) } ///解析一个空白页面 @@ -86,9 +98,9 @@ class NRReadChapterModel: NSObject, SmartCodable { /// 完整内容排版 private func fullContentAttrString() ->NSMutableAttributedString { let name = "\n\(self.name ?? "")\n\n" - let titleString = NSMutableAttributedString(string: name, attributes: NRNovelReadSetManager.manager.attributes(isTitle: true)) + let titleString = NSMutableAttributedString(string: name, attributes: NRNovelReadSetManager.manager.titleAttributes()) - let contentString = NSMutableAttributedString(string: novel_txt ?? "", attributes: NRNovelReadSetManager.manager.attributes(isTitle: false)) + let contentString = NSMutableAttributedString(string: novel_txt ?? "", attributes: NRNovelReadSetManager.manager.textAttributes()) titleString.append(contentString) diff --git a/ReaderHive/Class/Novel/M/NRReadPageModel.swift b/ReaderHive/Class/Novel/M/NRReadPageModel.swift index 58399af..8a78ea7 100644 --- a/ReaderHive/Class/Novel/M/NRReadPageModel.swift +++ b/ReaderHive/Class/Novel/M/NRReadPageModel.swift @@ -12,6 +12,7 @@ class NRReadPageModel: NSObject { enum PageType { case textPart case readFinish + case recommend } var pageType: PageType = .textPart @@ -27,11 +28,20 @@ class NRReadPageModel: NSObject { var indexPath: IndexPath = IndexPath(row: 0, section: 0) + ///用来保存特殊数据的位置信息 + ///所在章节的位置 +// var chapterIndex: Int? + ///用来保存特殊数据的位置信息 + ///所在章节的页面位置0-1 + var pagePoint: CGFloat? + + var pageTitle: String? + var recommendList: [NRNovelModel]? + // MARK: 快捷获取 /// 获取显示内容(考虑可能会变换字体颜色的情况) - var showContent: NSAttributedString { - let textColor = NRNovelReadSetManager.manager.textColor + func showContent(textColor: UIColor = NRNovelReadSetManager.manager.textColor) -> NSAttributedString { let tempShowContent = NSMutableAttributedString(attributedString: content) tempShowContent.addAttributes([.foregroundColor : textColor], range: NSMakeRange(0, content.length)) return tempShowContent diff --git a/ReaderHive/Class/Novel/V/Reader/NRNovelReadContentBottomView.swift b/ReaderHive/Class/Novel/V/Reader/NRNovelReadContentBottomView.swift index 57756fb..90cf8fa 100644 --- a/ReaderHive/Class/Novel/V/Reader/NRNovelReadContentBottomView.swift +++ b/ReaderHive/Class/Novel/V/Reader/NRNovelReadContentBottomView.swift @@ -47,7 +47,7 @@ class NRNovelReadContentBottomView: UIView { return label }() - private lazy var pageLabel: UILabel = { + private(set) lazy var pageLabel: UILabel = { let label = UILabel() label.font = .font(ofSize: 12, weight: .regular) label.textColor = .black diff --git a/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishFooterView.swift b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishFooterView.swift new file mode 100644 index 0000000..56a4943 --- /dev/null +++ b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishFooterView.swift @@ -0,0 +1,85 @@ +// +// NRNovelReadFinishFooterView.swift +// ReaderHive +// +// Created by 澜声世纪 on 2026/2/5. +// + +import UIKit +import SnapKit +import YYCategories + +class NRNovelReadFinishFooterView: UIView { + + + var clickRefresh: (() -> Void)? + var clickRead: (() -> Void)? + + private lazy var refreshButton: UIButton = { + var configuration = UIButton.Configuration.plain() + configuration.background.cornerRadius = 24 + configuration.background.backgroundColor = .white + configuration.image = UIImage(named: "refresh_icon_02") + configuration.imagePadding = 8 + configuration.attributedTitle = AttributedString("reader_shuffle".localized, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 14, weight: .medium), + .foregroundColor : UIColor.F_9710_D + ])) + + let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in + self?.clickRefresh?() + })) + return button + }() + + private lazy var readButton: UIButton = { + var configuration = UIButton.Configuration.plain() + configuration.background.cornerRadius = 24 + configuration.background.image = UIImage(named: "gradient_color_01") + configuration.attributedTitle = AttributedString("reader_continue_reading".localized, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 14, weight: .medium), + .foregroundColor : UIColor.white + ])) + + let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in + self?.clickRead?() + })) + + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + nr_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + + +extension NRNovelReadFinishFooterView { + + private func nr_setupUI() { + addSubview(refreshButton) + addSubview(readButton) + + refreshButton.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalToSuperview().offset(8) + make.height.equalTo(48) + make.width.equalTo(120) + make.bottom.equalTo(-(UIScreen.safeBottom + 10)) + } + + readButton.snp.makeConstraints { make in + make.left.equalTo(refreshButton.snp.right).offset(12) + make.right.equalToSuperview().offset(-16) + make.centerY.height.equalTo(refreshButton) + } + } + +} diff --git a/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishHeaderView.swift b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishHeaderView.swift index f86a633..48b18a5 100644 --- a/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishHeaderView.swift +++ b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishHeaderView.swift @@ -9,51 +9,30 @@ import UIKit import SnapKit import YYCategories -class NRNovelReadFinishHeaderView: UICollectionReusableView { +class NRNovelReadFinishHeaderView: UIView { var novelModel: NRNovelModel? { didSet { - coverImageView.nr_setImage(novelModel?.image_url) +// coverImageView.nr_setImage(novelModel?.image_url) gradeView.model = novelModel } } + var recommendNovelModel: NRNovelModel? { + didSet { + self.recommendInfoView.novelModel = recommendNovelModel + self.recommendNovelNameLabel.text = recommendNovelModel?.chapterInfo?.name + } + } + var didChangeContentHeight: ((_ height: CGFloat) -> Void)? + var clickRefresh: (() -> Void)? - private lazy var contentView: NRScrollView = { - let contentView = NRScrollView() - contentView.addObserver(self, forKeyPath: "contentSize", context: nil) - return contentView - }() - private lazy var coverBgView: UIView = { - let view = NRGradientView() - view.colors = [UIColor.FFC_64_A.cgColor, UIColor.FFF_7_BE.cgColor, UIColor.FFC_982.cgColor] - view.startPoint = .init(x: 0, y: 0.5) - view.endPoint = .init(x: 1, y: 0.5) - view.layer.cornerRadius = 8 - view.layer.masksToBounds = true - return view - }() - - private lazy var coverImageView: NRImageView = { - let imageView = NRImageView() - imageView.layer.cornerRadius = 7 - return imageView - }() - - private lazy var coverGradientLayer: CAGradientLayer = { - let layer = CAGradientLayer() - layer.colors = [UIColor.black.cgColor, UIColor.clear.cgColor] - layer.startPoint = CGPoint(x: 0.5, y: 0.4) - layer.endPoint = CGPoint(x: 0.5, y: 1.0) - layer.cornerRadius = 8 - return layer - }() - - private lazy var coverDecorateView: UIView = { - let imageView = UIImageView(image: UIImage(named: "decorate_image_01")) - return imageView + private lazy var scrollView: NRScrollView = { + let scrollView = NRScrollView() + scrollView.addObserver(self, forKeyPath: "contentSize", context: nil) + return scrollView }() private lazy var titleLabel: NRLabel = { @@ -80,6 +59,9 @@ class NRNovelReadFinishHeaderView: UICollectionReusableView { private lazy var gradeView: NRNovelReadStarGradeView = { let view = NRNovelReadStarGradeView() + view.backgroundColor = .white + view.layer.borderColor = UIColor.black.withAlphaComponent(0.05).cgColor + view.layer.borderWidth = 1 return view }() @@ -89,16 +71,24 @@ class NRNovelReadFinishHeaderView: UICollectionReusableView { return view }() - lazy var listTitleLabel: UILabel = { + private lazy var recommendInfoView: NRNovelReadFinishInfoView = { + let view = NRNovelReadFinishInfoView() + view.clickRefresh = { [weak self] in + guard let self = self else { return } + self.clickRefresh?() + } + return view + }() + + private lazy var recommendNovelNameLabel: UILabel = { let label = UILabel() label.font = .font(ofSize: 16, weight: .semibold) label.textColor = .black - label.text = "reader_book_finished_list_title".localized return label }() deinit { - self.contentView.removeObserver(self, forKeyPath: "contentSize") + self.scrollView.removeObserver(self, forKeyPath: "contentSize") } override init(frame: CGRect) { @@ -108,8 +98,7 @@ class NRNovelReadFinishHeaderView: UICollectionReusableView { override func layoutSubviews() { super.layoutSubviews() - coverGradientLayer.frame = coverBgView.bounds - coverBgView.layer.mask = coverGradientLayer + } required init?(coder: NSCoder) { @@ -118,8 +107,7 @@ class NRNovelReadFinishHeaderView: UICollectionReusableView { override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "contentSize" { - let height = self.contentView.contentSize.height + 1 - self.didChangeContentHeight?(height) + self.didChangeContentHeight?(self.scrollView.contentSize.height) } } @@ -128,70 +116,54 @@ class NRNovelReadFinishHeaderView: UICollectionReusableView { extension NRNovelReadFinishHeaderView { private func nr_setupUI() { - addSubview(contentView) - contentView.addSubview(coverBgView) - coverBgView.addSubview(coverImageView) - contentView.addSubview(coverDecorateView) - contentView.addSubview(titleLabel) - contentView.addSubview(textLabel) - contentView.addSubview(gradeView) - contentView.addSubview(lineView) - contentView.addSubview(listTitleLabel) + addSubview(scrollView) + scrollView.addSubview(titleLabel) + scrollView.addSubview(textLabel) + scrollView.addSubview(gradeView) + scrollView.addSubview(lineView) + scrollView.addSubview(recommendInfoView) + scrollView.addSubview(recommendNovelNameLabel) - contentView.snp.makeConstraints { make in + scrollView.snp.makeConstraints { make in make.edges.equalToSuperview() } - coverBgView.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalToSuperview().offset(16) - make.width.equalTo(100) - make.height.equalTo(150) - } - - coverImageView.snp.makeConstraints { make in - make.left.equalToSuperview().offset(2) - make.top.equalToSuperview().offset(2) - make.center.equalToSuperview() - } - - coverDecorateView.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.bottom.equalTo(coverBgView).offset(12) - } - titleLabel.snp.makeConstraints { make in make.centerX.equalToSuperview() - make.top.equalTo(coverBgView.snp.bottom).offset(20) -// make.right.lessThanOrEqualToSuperview().offset(-16) + make.top.equalToSuperview().offset(2) make.right.lessThanOrEqualTo(gradeView) } textLabel.snp.makeConstraints { make in make.centerX.equalToSuperview() - make.top.equalTo(titleLabel.snp.bottom).offset(6) + make.top.equalTo(titleLabel.snp.bottom).offset(5) make.right.lessThanOrEqualTo(gradeView) } gradeView.snp.makeConstraints { make in make.left.equalToSuperview().offset(16) make.centerX.equalToSuperview() - make.top.equalTo(textLabel.snp.bottom).offset(25) + make.top.equalTo(textLabel.snp.bottom).offset(20) } lineView.snp.makeConstraints { make in make.left.equalToSuperview().offset(16) make.centerX.equalToSuperview() - make.top.equalTo(gradeView.snp.bottom).offset(24) + make.top.equalTo(gradeView.snp.bottom).offset(20) make.height.equalTo(1) } - listTitleLabel.snp.makeConstraints { make in - make.left.equalToSuperview().offset(16) - make.top.equalTo(lineView.snp.bottom).offset(16) - make.bottom.equalToSuperview().offset(-16) + recommendInfoView.snp.makeConstraints { make in + make.left.centerX.equalToSuperview() + make.top.equalTo(lineView.snp.bottom) } + recommendNovelNameLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.right.lessThanOrEqualTo(recommendInfoView).offset(-16) + make.top.equalTo(recommendInfoView.snp.bottom).offset(12) + make.bottom.equalToSuperview().offset(-8) + } } } diff --git a/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishInfoView.swift b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishInfoView.swift new file mode 100644 index 0000000..22866e0 --- /dev/null +++ b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishInfoView.swift @@ -0,0 +1,168 @@ +// +// NRNovelReadFinishInfoView.swift +// ReaderHive +// +// Created by 澜声世纪 on 2026/2/3. +// + +import UIKit +import SnapKit + +class NRNovelReadFinishInfoView: UIView { + + var clickRefresh: (() -> Void)? + + + var novelModel: NRNovelModel? { + didSet { + coverImageView.nr_setImage(novelModel?.image_url) + let rate = novelModel?.rate ?? 0 + nameLabel.text = novelModel?.name + starView.grade = rate / 2 + starView.text = NSNumber(value: Float(rate)).toString(maximumFractionDigits: 1, minimumFractionDigits: 1) + + hotView.setNeedsUpdateConfiguration() + tagStackView.nr_removeAllArrangedSubview() + tagStackView.addArrangedSubview(hotView) + + novelModel?.category?.forEach { + guard let view = createCategoryView($0) else { return } + tagStackView.addArrangedSubview(view) + } + } + } + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 16, weight: .semibold) + label.textColor = .black + label.text = "reader_book_more".localized + return label + }() + + private lazy var refreshButton: UIButton = { + let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in + guard let self = self else { return } + self.clickRefresh?() + })) + button.setImage(UIImage(named: "refresh_icon_01"), for: .normal) + return button + }() + + private lazy var coverImageView: NRImageView = { + let imageView = NRImageView() + imageView.layer.cornerRadius = 4 + return imageView + }() + + private lazy var nameLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 14, weight: .medium) + label.textColor = .black + return label + }() + + private lazy var starView: NRStarGradeView = { + let view = NRStarGradeView() + return view + }() + + private lazy var tagStackView: UIStackView = { + let view = UIStackView() + view.axis = .horizontal + view.spacing = 8 + return view + }() + + private lazy var hotView: UIButton = { + var configuration = UIButton.Configuration.plain() + configuration.image = UIImage(named: "hot_icon_01") + configuration.imagePadding = 1 + configuration.contentInsets = .init(top: 0, leading: 8, bottom: 0, trailing: 8) + configuration.background.backgroundColor = .black.withAlphaComponent(0.05) + + let button = UIButton(configuration: configuration) + button.isUserInteractionEnabled = false + button.layer.cornerRadius = 10 + button.layer.masksToBounds = true + button.configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + let num = CGFloat(novelModel?.heats ?? 0) + let text = NSNumber(value: num).formattedNumber() + + button.configuration?.attributedTitle = AttributedString(text, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 10, weight: .regular), + .foregroundColor : UIColor.black.withAlphaComponent(0.5) + ])) + } + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + tagStackView.addArrangedSubview(hotView) + + nr_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func createCategoryView(_ text: String?) -> UIView? { + guard let text = text, text.count > 0 else { return nil } + + let view = NRHomeCategoryTagView() + view.text = text + return view + } +} + +extension NRNovelReadFinishInfoView { + + private func nr_setupUI() { + addSubview(titleLabel) + addSubview(refreshButton) + addSubview(coverImageView) + addSubview(nameLabel) + addSubview(starView) + addSubview(tagStackView) + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalToSuperview().offset(12) + } + + refreshButton.snp.makeConstraints { make in + make.centerY.equalTo(titleLabel) + make.right.equalToSuperview().offset(-16) + } + + coverImageView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalTo(titleLabel.snp.bottom).offset(12) + make.width.equalTo(48) + make.height.equalTo(72) + make.bottom.equalToSuperview() + } + + nameLabel.snp.makeConstraints { make in + make.left.equalTo(coverImageView.snp.right).offset(12) + make.top.equalTo(coverImageView).offset(0) + make.right.lessThanOrEqualToSuperview().offset(-16) + } + + starView.snp.makeConstraints { make in + make.left.equalTo(nameLabel) + make.top.equalTo(nameLabel.snp.bottom).offset(9) + } + + tagStackView.snp.makeConstraints { make in + make.bottom.equalTo(coverImageView) + make.left.equalTo(nameLabel) + make.height.equalTo(20) + } + } + +} diff --git a/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishTextCell.swift b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishTextCell.swift new file mode 100644 index 0000000..518e0a8 --- /dev/null +++ b/ReaderHive/Class/Novel/V/Reader/NRNovelReadFinishTextCell.swift @@ -0,0 +1,50 @@ +// +// NRNovelReadFinishTextCell.swift +// ReaderHive +// +// Created by 澜声世纪 on 2026/2/5. +// + +import UIKit +import SnapKit + +class NRNovelReadFinishTextCell: NRTableViewCell { + + var pageModel: NRReadPageModel? { + didSet { + label.attributedText = pageModel?.content + } + } + + private lazy var label: UILabel = { + let label = UILabel() + label.textColor = ._666666 + label.numberOfLines = 0 + return label + }() + + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + nr_setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension NRNovelReadFinishTextCell { + + private func nr_setupUI() { + contentView.addSubview(label) + + label.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.right.lessThanOrEqualToSuperview().offset(-16) + make.top.bottom.equalToSuperview() + } + } + +} diff --git a/ReaderHive/Class/Novel/V/Reader/NRNovelReadRecommendCell.swift b/ReaderHive/Class/Novel/V/Reader/NRNovelReadRecommendCell.swift new file mode 100644 index 0000000..ee125e8 --- /dev/null +++ b/ReaderHive/Class/Novel/V/Reader/NRNovelReadRecommendCell.swift @@ -0,0 +1,176 @@ +// +// NRNovelReadRecommendCell.swift +// ReaderHive +// +// Created by 澜声世纪 on 2026/2/4. +// + +import UIKit +import SnapKit + +class NRNovelReadRecommendCell: UICollectionViewCell { + + + var clickRead: ((_ model: NRNovelModel) -> Void)? + + var novelModel: NRNovelModel? { + didSet { + coverImageView.nr_setImage(novelModel?.image_url) + nameLabel.text = novelModel?.name + categoryView.text = novelModel?.category?.first + desLabel.text = novelModel?.nr_description + + let star = novelModel?.rate ?? 0 + starView.grade = star / 2 + starView.text = NSNumber(value: star).toString(maximumFractionDigits: 1, minimumFractionDigits: 1) + } + } + + + + private lazy var coverImageView: NRImageView = { + let imageView = NRImageView() + imageView.layer.cornerRadius = 4 + return imageView + }() + + private lazy var nameLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 14, weight: .medium) + return label + }() + + private lazy var categoryView: NRHomeCategoryTagView = { + let view = NRHomeCategoryTagView() + return view + }() + + private lazy var starView: NRStarGradeView = { + let view = NRStarGradeView() + return view + }() + + private lazy var desLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 10, weight: .regular) + label.numberOfLines = 2 + return label + }() + + private lazy var readView: UILabel = { + let label = UILabel() + label.text = "reader_read_now".localized + label.font = .font(ofSize: 14, weight: .medium) + label.layer.cornerRadius = 4 + label.layer.masksToBounds = true + label.textAlignment = .center + return label + }() + + private lazy var button: UIButton = { + let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in + guard let self = self else { return } + guard let model = self.novelModel else { return } + self.clickRead?(model) + })) + return button + }() + + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override init(frame: CGRect) { + super.init(frame: frame) + NotificationCenter.default.addObserver(self, selector: #selector(didChangedThemeNotification), name: NRNovelReadSetManager.didChangedThemeNotification, object: nil) + + self.contentView.layer.cornerRadius = 8 + self.contentView.layer.masksToBounds = true + self.contentView.layer.borderWidth = 1 + + didChangedThemeNotification() + + nr_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func didChangedThemeNotification() { + if NRNovelReadSetManager.manager.isNight { + self.contentView.layer.borderColor = UIColor.white.withAlphaComponent(0.15).cgColor + self.contentView.backgroundColor = .black.withAlphaComponent(0.5) + self.nameLabel.textColor = .white + self.readView.textColor = .FFEFD_4 + self.readView.backgroundColor = .F_9710_D + self.desLabel.textColor = .white.withAlphaComponent(0.5) + self.starView.textColor = .white + self.categoryView.backgroundColor = .white.withAlphaComponent(0.15) + self.categoryView.categoryLabel.textColor = .white.withAlphaComponent(0.5) + } else { + self.contentView.layer.borderColor = UIColor.black.withAlphaComponent(0.05).cgColor + self.contentView.backgroundColor = .white.withAlphaComponent(0.5) + self.nameLabel.textColor = .black + self.readView.textColor = .F_9710_D + self.readView.backgroundColor = .FFEFD_4 + self.desLabel.textColor = .black.withAlphaComponent(0.5) + self.starView.textColor = .black + self.categoryView.backgroundColor = .black.withAlphaComponent(0.05) + self.categoryView.categoryLabel.textColor = .black.withAlphaComponent(0.5) + } + } +} + +extension NRNovelReadRecommendCell { + private func nr_setupUI() { + contentView.addSubview(coverImageView) + contentView.addSubview(nameLabel) + contentView.addSubview(readView) + contentView.addSubview(categoryView) + contentView.addSubview(starView) + contentView.addSubview(desLabel) + contentView.addSubview(button) + + coverImageView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(8) + make.top.equalToSuperview().offset(8) + make.bottom.equalToSuperview().offset(-8) + make.width.equalTo(80) + } + + nameLabel.snp.makeConstraints { make in + make.left.equalTo(coverImageView.snp.right).offset(12) + make.right.lessThanOrEqualToSuperview().offset(-8) + make.top.equalTo(coverImageView) + } + + categoryView.snp.makeConstraints { make in + make.left.equalTo(nameLabel) + make.top.equalTo(nameLabel.snp.bottom).offset(8) + } + + starView.snp.makeConstraints { make in + make.centerY.equalTo(categoryView) + make.left.equalTo(categoryView.snp.right).offset(8) + } + + desLabel.snp.makeConstraints { make in + make.left.equalTo(nameLabel) + make.right.lessThanOrEqualToSuperview().offset(-8) + make.top.equalTo(categoryView.snp.bottom).offset(8) + } + + readView.snp.makeConstraints { make in + make.left.equalTo(nameLabel) + make.right.equalToSuperview().offset(-8) + make.bottom.equalTo(coverImageView) + make.height.equalTo(24) + } + + button.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } +} diff --git a/ReaderHive/Class/Novel/VC/Read/NRNovelReadContentViewController.swift b/ReaderHive/Class/Novel/VC/Read/NRNovelReadContentViewController.swift index d9ac36a..b25ed30 100644 --- a/ReaderHive/Class/Novel/VC/Read/NRNovelReadContentViewController.swift +++ b/ReaderHive/Class/Novel/VC/Read/NRNovelReadContentViewController.swift @@ -45,13 +45,13 @@ class NRNovelReadContentViewController: NRNovelReadBaseViewController { bottomView.catalogModel = self.catalogModel bottomView.pageModel = self.pageModel - readView.content = pageModel?.showContent + readView.content = pageModel?.showContent() nr_setupUI() } @objc private func didChangedThemeNotification() { - readView.content = pageModel?.showContent + readView.content = pageModel?.showContent() } } diff --git a/ReaderHive/Class/Novel/VC/Read/NRNovelReadFinishViewController.swift b/ReaderHive/Class/Novel/VC/Read/NRNovelReadFinishViewController.swift index 0c08cd6..20a3e04 100644 --- a/ReaderHive/Class/Novel/VC/Read/NRNovelReadFinishViewController.swift +++ b/ReaderHive/Class/Novel/VC/Read/NRNovelReadFinishViewController.swift @@ -7,15 +7,12 @@ import UIKit import SnapKit +import YYText class NRNovelReadFinishViewController: NRNovelReadBaseViewController { - lazy var dataArr: [NRNovelModel] = [] { - didSet { - self.collectionView.reloadData() - } - } + private var recommandNovelModel: NRNovelModel? private lazy var backButton: UIButton = { let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in @@ -27,34 +24,55 @@ class NRNovelReadFinishViewController: NRNovelReadBaseViewController { return button }() - private lazy var collectionViewLayout: UICollectionViewFlowLayout = { - let itemWidth = (UIScreen.width - 32 - 40) / 3 - let itemHeight = 150 / 100 * itemWidth + 68 - - let layout = UICollectionViewFlowLayout() - layout.itemSize = .init(width: itemWidth, height: itemHeight) - layout.minimumLineSpacing = 18 - layout.minimumInteritemSpacing = 20 - layout.sectionInset = .init(top: 0, left: 16, bottom: 0, right: 16) - layout.headerReferenceSize = .init(width: UIScreen.width, height: 390) - return layout + + + private lazy var tableView: NRTableView = { + let tableView = NRTableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.separatorStyle = .none + tableView.register(NRNovelReadFinishTextCell.self, forCellReuseIdentifier: "cell") + return tableView }() - private lazy var collectionView: NRCollectionView = { - let collectionView = NRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) - collectionView.delegate = self - collectionView.dataSource = self - collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.safeBottom + 10, right: 0) - collectionView.register(NRNovelDetailMoreLikeCell.self, forCellWithReuseIdentifier: "cell") - collectionView.register(NRNovelReadFinishHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "header") - return collectionView + private lazy var headerView: NRNovelReadFinishHeaderView = { + let view = NRNovelReadFinishHeaderView() + view.frame = .init(x: 0, y: 0, width: UIScreen.width, height: 1) + view.novelModel = self.viewModel?.novelModel + view.didChangeContentHeight = { [weak self] height in + guard let self = self else { return } + self.tableView.tableHeaderView = nil + self.headerView.frame = .init(x: 0, y: 0, width: UIScreen.width, height: height) + self.tableView.tableHeaderView = self.headerView + } + view.clickRefresh = { [weak self] in + self?.handleRefresh() + } + return view }() + private lazy var footerView: NRNovelReadFinishFooterView = { + let view = NRNovelReadFinishFooterView(frame: .init(x: 0, y: 0, width: UIScreen.width, height: 68 + UIScreen.safeBottom)) + view.clickRefresh = { [weak self] in + self?.handleRefresh() + } + view.clickRead = { [weak self] in + guard let self = self else { return } + guard let id = self.recommandNovelModel?.id else { return } + let vc = NRNovelReaderViewController() + vc.novelId = id + vc.targetIndex = 1 + self.navigationController?.pushViewController(vc, animated: true) + } + return view + }() + + + override func viewDidLoad() { super.viewDidLoad() backgroundImageView.image = UIImage(named: "bg_image_04") - self.view.backgroundColor = .white - + self.view.backgroundColor = .F_2_EFEE // let tap = UITapGestureRecognizer { _ in // @@ -79,14 +97,42 @@ class NRNovelReadFinishViewController: NRNovelReadBaseViewController { override var preferredStatusBarStyle: UIStatusBarStyle { return .darkContent } + + private func handleRefresh() { + Task { + guard await requestDataArr() else { return } + + CATransaction.setCompletionBlock { + self.tableView.setContentOffset(.zero, animated: true) + } + + CATransaction.begin() + self.tableView.reloadData() + CATransaction.commit() + } + } } extension NRNovelReadFinishViewController { private func nr_setupUI() { + self.tableView.tableHeaderView = self.headerView + self.tableView.tableFooterView = self.footerView + view.addSubview(backButton) - view.addSubview(collectionView) + view.addSubview(tableView) +// scrollView.addSubview(headerView) +// scrollView.addSubview(infoView) +// scrollView.addSubview(novelNameLabel) +// scrollView.addSubview(novelTextLabel) +// scrollView.addSubview(refreshButton) +// scrollView.addSubview(readButton) + +// backgroundImageView.snp.remakeConstraints { make in +// make.left.right.equalToSuperview() +// make.top.equalTo(UIScreen.safeTop) +// } backButton.snp.makeConstraints { make in make.left.equalToSuperview().offset(6) @@ -95,54 +141,81 @@ extension NRNovelReadFinishViewController { make.width.equalTo(36) } - collectionView.snp.makeConstraints { make in + tableView.snp.makeConstraints { make in make.left.right.equalToSuperview() - make.top.equalToSuperview().offset(UIScreen.navBarHeight) + make.top.equalTo(backButton.snp.bottom) make.bottom.equalToSuperview() } + +// refreshButton.snp.makeConstraints { make in +// make.left.equalToSuperview().offset(16) +// make.top.equalTo(novelTextLabel.snp.bottom).offset(8) +// make.height.equalTo(48) +// make.width.equalTo(120) +// make.bottom.equalTo(-(UIScreen.safeBottom + 10)) +// } + +// readButton.snp.makeConstraints { make in +// make.left.equalTo(refreshButton.snp.right).offset(12) +// make.right.equalTo(infoView).offset(-16) +// make.centerY.height.equalTo(refreshButton) +// } + } } -//MARK: UICollectionViewDelegate UICollectionViewDataSource -extension NRNovelReadFinishViewController: UICollectionViewDelegate, UICollectionViewDataSource { - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! NRNovelDetailMoreLikeCell - cell.model = self.dataArr[indexPath.row] +//MARK: UITableViewDelegate & UITableViewDataSource +extension NRNovelReadFinishViewController: UITableViewDelegate, UITableViewDataSource { + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NRNovelReadFinishTextCell + cell.pageModel = self.recommandNovelModel?.chapterInfo?.pageList?[indexPath.row] return cell } - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return self.dataArr.count + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.recommandNovelModel?.chapterInfo?.pageList?.count ?? 0 } - func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { - let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "header", for: indexPath) as! NRNovelReadFinishHeaderView - view.didChangeContentHeight = { [weak self] height in - guard let self = self else { return } - self.collectionViewLayout.headerReferenceSize = .init(width: UIScreen.width, height: height) - } - view.novelModel = self.viewModel?.novelModel - return view - } - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let model = dataArr[indexPath.row] - let vc = NRNovelDetailViewController() - vc.novelId = model.id ?? "" - self.viewModel?.vc?.navigationController?.pushViewController(vc, animated: true) - } - - } extension NRNovelReadFinishViewController { - private func requestDataArr() async { - guard let list = await NRNovelAPI.requestDetailRecommandData() else { return } - self.dataArr = list - self.collectionView.reloadData() + private func requestDataArr() async -> Bool { +// guard let list = await NRNovelAPI.requestDetailRecommandData() else { return } +// self.dataArr = list +// self.collectionView.reloadData() + + guard let id = self.viewModel?.novelId else { return false } + + guard let model = await NRNovelAPI.requestReadFinishRecommand(novelId: id) else { return false } + self.recommandNovelModel = model + let chapterModel = model.chapterInfo + chapterModel?.parserText(attributes: [ + .font : UIFont.font(ofSize: 16, weight: .regular), + .foregroundColor : UIColor._666666 + ]) + + self.headerView.recommendNovelModel = model + + + + self.tableView.reloadData() + +// let text = NSAttributedString(string: chapterModel?.novel_txt ?? "", attributes: [ +// .font : UIFont.font(ofSize: 16, weight: .regular), +// .foregroundColor : UIColor._666666 +// ]) +// let textContainer = YYTextContainer(size: .init(width: UIScreen.width - 32, height: CGFloat(MAXFLOAT))) +// let textLayout = YYTextLayout(container: textContainer, text: text) +// +// self.novelTextLabel.textLayout = textLayout +// +// self.novelTextLabel.snp.updateConstraints { make in +// make.height.equalTo(textLayout?.textBoundingSize.height ?? 0) +// } + + return true } } diff --git a/ReaderHive/Class/Novel/VC/Read/NRNovelReadRecommendViewController.swift b/ReaderHive/Class/Novel/VC/Read/NRNovelReadRecommendViewController.swift new file mode 100644 index 0000000..f219a91 --- /dev/null +++ b/ReaderHive/Class/Novel/VC/Read/NRNovelReadRecommendViewController.swift @@ -0,0 +1,179 @@ +// +// NRNovelReadRecommendViewController.swift +// ReaderHive +// +// Created by 澜声世纪 on 2026/2/3. +// + +import UIKit +import SnapKit + +class NRNovelReadRecommendViewController: NRNovelReadBaseViewController { + + lazy var topView: NRNovelReadContentTopView = { + let view = NRNovelReadContentTopView() + return view + }() + + lazy var bottomView: NRNovelReadContentBottomView = { + let view = NRNovelReadContentBottomView() + view.pageLabel.isHidden = true + return view + }() + + lazy var containerView: UIView = { + let view = UIView() + return view + }() + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.itemSize = .init(width: UIScreen.width - 32, height: 136) + layout.minimumLineSpacing = 16 + layout.minimumInteritemSpacing = 16 + return layout + }() + + private lazy var collectionView: NRCollectionView = { + let collectionView = NRCollectionView(frame: .zero, collectionViewLayout: self.collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsVerticalScrollIndicator = false + collectionView.register(NRNovelReadRecommendCell.self, forCellWithReuseIdentifier: "cell") + return collectionView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 16, weight: .bold) + return label + }() + + private lazy var continueButton: UIButton = { + var configuration = UIButton.Configuration.plain() + configuration.imagePadding = 12 + configuration.imagePlacement = .trailing + configuration.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0) + + let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in + + })) + button.isUserInteractionEnabled = false + button.configurationUpdateHandler = { [weak self] button in + var textColor: UIColor + if NRNovelReadSetManager.manager.isNight { + button.configuration?.image = UIImage(named: "arrow_right_icon_08") + textColor = .white.withAlphaComponent(0.25) + } else { + button.configuration?.image = UIImage(named: "arrow_right_icon_09") + textColor = .black.withAlphaComponent(0.15) + } + button.configuration?.attributedTitle = AttributedString("reader_swipe_reading".localized, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 18, weight: .medium), + .foregroundColor : textColor + ])) + + } + return button + }() + + @MainActor deinit { + NotificationCenter.default.removeObserver(self) + } + + override func viewDidLoad() { + super.viewDidLoad() + self.backgroundImageView.isHidden = true + self.view.backgroundColor = .clear + + NotificationCenter.default.addObserver(self, selector: #selector(didChangedThemeNotification), name: NRNovelReadSetManager.didChangedThemeNotification, object: nil) + + topView.viewModel = self.viewModel + topView.catalogModel = self.catalogModel + topView.pageModel = self.pageModel + bottomView.viewModel = self.viewModel + bottomView.catalogModel = self.catalogModel + bottomView.pageModel = self.pageModel + + self.titleLabel.text = self.pageModel?.pageTitle + + nr_setupUI() + + didChangedThemeNotification() + } + + @objc private func didChangedThemeNotification() { + if NRNovelReadSetManager.manager.isNight { + titleLabel.textColor = .white + } else { + titleLabel.textColor = .black + } + continueButton.setNeedsUpdateConfiguration() + } + +} + +extension NRNovelReadRecommendViewController { + + private func nr_setupUI() { + view.addSubview(topView) + view.addSubview(bottomView) + view.addSubview(containerView) + containerView.addSubview(collectionView) + containerView.addSubview(titleLabel) + containerView.addSubview(continueButton) + + + topView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + } + + bottomView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + } + + containerView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalTo(topView.snp.bottom) + make.bottom.equalTo(bottomView.snp.top) + } + + collectionView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.centerY.equalToSuperview().offset(-25) + make.height.equalTo(collectionViewLayout.itemSize.height * 3 + collectionViewLayout.minimumLineSpacing * 2) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.bottom.equalTo(collectionView.snp.top).offset(-16) + } + + continueButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(collectionView.snp.bottom).offset(35) + } + + } + +} + +//MARK: UICollectionViewDelegate UICollectionViewDataSource +extension NRNovelReadRecommendViewController: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! NRNovelReadRecommendCell + cell.novelModel = self.pageModel?.recommendList?[indexPath.row] + cell.clickRead = { [weak self] model in + guard let self = self else { return } + let vc = NRNovelReaderViewController() + vc.novelId = model.id ?? "0" + self.navigationController?.pushViewController(vc, animated: true) + } + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return self.pageModel?.recommendList?.count ?? 0 + } +} diff --git a/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController+Page.swift b/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController+Page.swift index 78988fc..0ccc469 100644 --- a/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController+Page.swift +++ b/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController+Page.swift @@ -168,7 +168,9 @@ extension NRNovelReaderViewController { guard let catalogModel = catalogModel, let pageModel = pageModel else { return nil } let vc: NRNovelReadBaseViewController if pageModel.pageType == .readFinish { - vc = NRNovelReadFinishViewController() + vc = self.finishVC + } else if pageModel.pageType == .recommend { + vc = NRNovelReadRecommendViewController() } else { vc = NRNovelReadContentViewController() } diff --git a/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController.swift b/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController.swift index e799a4f..2880215 100644 --- a/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController.swift +++ b/ReaderHive/Class/Novel/VC/Read/NRNovelReaderViewController.swift @@ -39,6 +39,15 @@ class NRNovelReaderViewController: NRViewController { } } + var targetIndex: Int? { + set { + self.viewModel.targetIndex = newValue + } + get { + return self.viewModel.targetIndex + } + } + var oldBrightness: CGFloat = UIScreen.main.brightness private(set) lazy var viewModel: NRNovelReadViewModel = { @@ -70,6 +79,11 @@ class NRNovelReaderViewController: NRViewController { return vc }() + private(set) lazy var finishVC: NRNovelReadFinishViewController = { + let vc = NRNovelReadFinishViewController() + return vc + }() + private lazy var readContentView: UIView = { let view = UIView() return view @@ -142,18 +156,18 @@ class NRNovelReaderViewController: NRViewController { } override var childForStatusBarHidden: UIViewController? { - if let _ = self.pageViewController.viewControllers?.first as? NRNovelReadContentViewController { - return nil + if let vc = self.pageViewController.viewControllers?.first as? NRNovelReadFinishViewController { + return vc } else { - return self.pageViewController.viewControllers?.first + return nil } } override var childForStatusBarStyle: UIViewController? { - if let _ = self.pageViewController.viewControllers?.first as? NRNovelReadContentViewController { - return nil + if let vc = self.pageViewController.viewControllers?.first as? NRNovelReadFinishViewController { + return vc } else { - return self.pageViewController.viewControllers?.first + return nil } } @@ -187,6 +201,7 @@ extension NRNovelReaderViewController { return; } self.view.ly_hideEmpty() + addChild(self.pageViewController) view.addSubview(readContentView) view.addSubview(topView) @@ -239,6 +254,8 @@ extension NRNovelReaderViewController { let currentCatalogModel = self.viewModel.chapterCatalogList[indexPath.section] + await self.viewModel.requestReadRecommand(type: 1) + await self.viewModel.requestReadRecommand(type: 2) //获取章节数据 await self.viewModel.requestChapterData(currentCatalogModel) @@ -260,7 +277,11 @@ extension NRNovelReaderViewController { //匹配历史记录的索引 var section = 0 var row = 0 - if let catalogModel = self.targetCatalogModel { + + if let targetIndex = self.targetIndex { + section = targetIndex + self.targetIndex = nil + } else if let catalogModel = self.targetCatalogModel { for (index, model) in self.viewModel.chapterCatalogList.enumerated() { if model.id == catalogModel.id { section = index diff --git a/ReaderHive/Class/Novel/VM/NRNovelReadViewModel+Data.swift b/ReaderHive/Class/Novel/VM/NRNovelReadViewModel+Data.swift index 5a368a4..f70dcb3 100644 --- a/ReaderHive/Class/Novel/VM/NRNovelReadViewModel+Data.swift +++ b/ReaderHive/Class/Novel/VM/NRNovelReadViewModel+Data.swift @@ -105,10 +105,19 @@ extension NRNovelReadViewModel { currentRow = listCount - 1 } if haveText { - let currentPage = catalogModel.chapterModel?.pageList?[currentRow] - if currentPage?.pageType != .textPart { + var currentPage = catalogModel.chapterModel?.pageList?[currentRow] + + while currentPage != nil, currentPage?.pageType != .textPart, currentRow > 0 { currentRow = currentRow - 1 + currentPage = catalogModel.chapterModel?.pageList?[currentRow] } + + + + +// if currentPage?.pageType != .textPart { +// currentRow = currentRow - 1 +// } } self.currentPageIndexPath = IndexPath(row: currentRow, section: currentSection) @@ -218,6 +227,8 @@ extension NRNovelReadViewModel { func requestChapterCatalogList() async { guard let list = await NRNovelAPI.requestChapterCatalogList(id: self.novelId) else { return } await MainActor.run { + let model = list.last + model?.finishPage = NRReadPageModel.createReadFinishModel() self.chapterCatalogList = list self.setEmptyData() } @@ -235,13 +246,9 @@ extension NRNovelReadViewModel { if code == 200 { guard let model = model else { return nil } - model.parser() - ///判断为最后一个章节 - if chapterId == self.chapterCatalogList.last?.id { - model.pageList?.append(NRReadPageModel.createReadFinishModel()) - } catalogModel.chapterModel = model + catalogModel.chapterModel?.parser() if catalogModel.is_lock == true { catalogModel.is_lock = false @@ -314,5 +321,27 @@ extension NRNovelReadViewModel { NRStatAPI.nr_requestWatchNovelDuration(novelId: self.novelId, duration: duration, percent: Int(percent)) } + + func requestReadRecommand(type: Int) async { + guard let list = await NRNovelAPI.requestReadRecommand(type: type) else { return } + var index: Int? + + let pageModel = NRReadPageModel() + pageModel.pageType = .recommend + pageModel.recommendList = list + if type == 1 { + index = self.chapterCatalogList.count - 2 + pageModel.pagePoint = 0.5 + pageModel.pageTitle = "reader_book_more".localized + } else { + index = self.chapterCatalogList.count - 1 + pageModel.pagePoint = 1 + pageModel.pageTitle = "reader_editors_choice".localized + } + if let index = index, index > 0 { + let catalogModel = self.chapterCatalogList[index] + catalogModel.recommandPage = pageModel + } + } } - +//MARK: 网络请求END diff --git a/ReaderHive/Class/Novel/VM/NRNovelReadViewModel.swift b/ReaderHive/Class/Novel/VM/NRNovelReadViewModel.swift index b5b0751..e330ad0 100644 --- a/ReaderHive/Class/Novel/VM/NRNovelReadViewModel.swift +++ b/ReaderHive/Class/Novel/VM/NRNovelReadViewModel.swift @@ -17,6 +17,7 @@ class NRNovelReadViewModel: NSObject { @objc dynamic var novelModel: NRNovelModel? ///目标数据,用于首次进入时,进入指定章节 var targetCatalogModel: NRReadChapterCatalogModel? + var targetIndex: Int? weak var vc: NRNovelReaderViewController? weak var topView: NRNovelReadTopView? diff --git a/ReaderHive/Libs/NovelTool/NRNovelReadSetManager.swift b/ReaderHive/Libs/NovelTool/NRNovelReadSetManager.swift index ca7748d..123c73c 100644 --- a/ReaderHive/Libs/NovelTool/NRNovelReadSetManager.swift +++ b/ReaderHive/Libs/NovelTool/NRNovelReadSetManager.swift @@ -135,8 +135,26 @@ class NRNovelReadSetManager: NSObject { } /// 字体属性 - /// isPaging: 为YES的时候只需要返回跟分页相关的属性即可 (原因:包含UIColor,小数点相关的...不可返回,因为无法进行比较) - func attributes(isTitle:Bool, isPageing:Bool = false) ->[NSAttributedString.Key:Any] { + func titleAttributes() ->[NSAttributedString.Key : Any] { + // 段落配置 + let paragraphStyle = NSMutableParagraphStyle() + + // 当前行间距(lineSpacing)的倍数(可根据字体大小变化修改倍数) + paragraphStyle.lineHeightMultiple = 1.0 + + // 行间距 + paragraphStyle.lineSpacing = 0 + + // 段间距 + paragraphStyle.paragraphSpacing = 0 + + // 对其 + paragraphStyle.alignment = .center + + return [.font: self.titleFont, .paragraphStyle: paragraphStyle] + } + + func textAttributes() ->[NSAttributedString.Key:Any] { // 段落配置 let paragraphStyle = NSMutableParagraphStyle() @@ -144,51 +162,28 @@ class NRNovelReadSetManager: NSObject { // 当前行间距(lineSpacing)的倍数(可根据字体大小变化修改倍数) paragraphStyle.lineHeightMultiple = 1.0 - if isTitle { - - // 行间距 - paragraphStyle.lineSpacing = 0 - - // 段间距 - paragraphStyle.paragraphSpacing = 0 - - // 对其 - paragraphStyle.alignment = .center - - }else{ - - // 行间距 - paragraphStyle.lineSpacing = lineSpacing - - // 换行模式(避免每页尾部留空白) -// paragraphStyle.lineBreakMode = .byCharWrapping - paragraphStyle.lineBreakMode = .byWordWrapping - - // 段间距 - paragraphStyle.paragraphSpacing = paragraphSpacing - - // 对其 - paragraphStyle.alignment = .justified - } - let font: UIFont + // 行间距 + paragraphStyle.lineSpacing = lineSpacing - if isTitle { - font = self.titleFont - } else { - font = self.textFont - } + // 换行模式(避免每页尾部留空白) + // paragraphStyle.lineBreakMode = .byCharWrapping + paragraphStyle.lineBreakMode = .byWordWrapping - if isPageing { - - return [.font: font, .paragraphStyle: paragraphStyle] - - }else{ - - return [.foregroundColor: textColor, .font: font, .paragraphStyle: paragraphStyle] - } + // 段间距 + paragraphStyle.paragraphSpacing = paragraphSpacing + + // 对其 + paragraphStyle.alignment = .justified + + + let font: UIFont = self.textFont + + return [.font: font, .paragraphStyle: paragraphStyle] } + + func emptyAttributes() -> [NSAttributedString.Key:Any] { // 段落配置 let paragraphStyle = NSMutableParagraphStyle() diff --git a/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/Contents.json b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/Contents.json similarity index 73% rename from ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/Contents.json rename to ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/Contents.json index f180462..65072c7 100644 --- a/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/Contents.json +++ b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "阅读完成徽章@2x.png", + "filename" : "快进,滑动@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "阅读完成徽章@3x.png", + "filename" : "快进,滑动@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/快进,滑动@2x.png b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/快进,滑动@2x.png new file mode 100644 index 0000000..cd1e662 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/快进,滑动@2x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/快进,滑动@3x.png b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/快进,滑动@3x.png new file mode 100644 index 0000000..276b54b Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_08.imageset/快进,滑动@3x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/Contents.json b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/Contents.json new file mode 100644 index 0000000..65072c7 --- /dev/null +++ b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "快进,滑动@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "快进,滑动@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/快进,滑动@2x.png b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/快进,滑动@2x.png new file mode 100644 index 0000000..06ccfee Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/快进,滑动@2x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/快进,滑动@3x.png b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/快进,滑动@3x.png new file mode 100644 index 0000000..8f354b0 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/arrow_right_icon_09.imageset/快进,滑动@3x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/Contents.json b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/Contents.json index 2accd77..a3b1c4f 100644 --- a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/Contents.json +++ b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "阅读完成页背景@2x.png", + "filename" : "阅读完成页背景2@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "阅读完成页背景@3x.png", + "filename" : "阅读完成页背景2@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景2@2x.png b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景2@2x.png new file mode 100644 index 0000000..58bbe10 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景2@2x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景2@3x.png b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景2@3x.png new file mode 100644 index 0000000..8db2fb4 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景2@3x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景@2x.png b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景@2x.png deleted file mode 100644 index ab0841b..0000000 Binary files a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景@2x.png and /dev/null differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景@3x.png b/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景@3x.png deleted file mode 100644 index 020fd8b..0000000 Binary files a/ReaderHive/Source/Assets.xcassets/Image/bg_image_04.imageset/阅读完成页背景@3x.png and /dev/null differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/阅读完成徽章@2x.png b/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/阅读完成徽章@2x.png deleted file mode 100644 index 411096a..0000000 Binary files a/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/阅读完成徽章@2x.png and /dev/null differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/阅读完成徽章@3x.png b/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/阅读完成徽章@3x.png deleted file mode 100644 index 685997f..0000000 Binary files a/ReaderHive/Source/Assets.xcassets/Image/decorate_image_01.imageset/阅读完成徽章@3x.png and /dev/null differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/Contents.json b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/Contents.json new file mode 100644 index 0000000..792d6f0 --- /dev/null +++ b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "刷新@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "刷新@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/刷新@2x.png b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/刷新@2x.png new file mode 100644 index 0000000..51539cb Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/刷新@2x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/刷新@3x.png b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/刷新@3x.png new file mode 100644 index 0000000..f8f0b07 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_01.imageset/刷新@3x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/Contents.json b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/Contents.json new file mode 100644 index 0000000..792d6f0 --- /dev/null +++ b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "刷新@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "刷新@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/刷新@2x.png b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/刷新@2x.png new file mode 100644 index 0000000..1e69c95 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/刷新@2x.png differ diff --git a/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/刷新@3x.png b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/刷新@3x.png new file mode 100644 index 0000000..0443b34 Binary files /dev/null and b/ReaderHive/Source/Assets.xcassets/Image/refresh_icon_02.imageset/刷新@3x.png differ diff --git a/ReaderHive/Source/en.lproj/Localizable.strings b/ReaderHive/Source/en.lproj/Localizable.strings index c6572bd..40ca6c8 100644 --- a/ReaderHive/Source/en.lproj/Localizable.strings +++ b/ReaderHive/Source/en.lproj/Localizable.strings @@ -153,6 +153,10 @@ "reader_my_vip_tips" = "Unrestricted access to all series!"; "reader_visitor" = "Visitor"; "free_coins" = "free coins"; +"reader_shuffle" = "Shuffle"; +"reader_continue_reading" = "Continue Reading"; +"reader_editors_choice" = "Editor's Choice for You"; +"reader_swipe_reading" = "Swipe to continue reading"; "vip_retain_alert_text" = "Unlock every show you love!"; "reader_log_out_content" = "Are you sure you want to log out?";