ReaderHive/ReaderHive/Class/Novel/VM/NRNovelReadViewModel+Data.swift
2025-12-29 09:01:07 +08:00

292 lines
11 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// NRNovelReadViewModel+Data.swift
// ReaderHive
//
// Created by on 2025/12/5.
//
import UIKit
///
var kNRReadRecordFolderName: String {
let userId = NRLoginManager.manager.userInfo?.customer_id ?? ""
return "novel_read_record/\(userId)"
}
//MARK:
extension NRNovelReadViewModel {
///
func getPageData(_ indexPath: IndexPath) -> (NRReadChapterCatalogModel?, NRReadPageModel?) {
let section = indexPath.section
let row = indexPath.row
guard section >= 0, row >= 0 else { return (nil, nil) }
guard chapterCatalogList.count > section else { return (nil, nil) }
let catalogModel = chapterCatalogList[section]
guard let chapterModel = catalogModel.chapterModel else { return (catalogModel, nil) }
let pageCount = chapterModel.pageList?.count ?? 0
guard pageCount > row, let pageModel = chapterModel.pageList?[row] else { return (catalogModel, nil) }
pageModel.indexPath = indexPath
return (catalogModel, pageModel)
}
///
func getCurrentPageData() -> (NRReadChapterCatalogModel?, NRReadPageModel?) {
return getPageData(self.currentPageIndexPath)
}
///
func getBelowPageData() -> (NRReadChapterCatalogModel?, NRReadPageModel?) {
var section = self.currentPageIndexPath.section
var row = self.currentPageIndexPath.row + 1
let (catalogModel, pageModel) = getPageData(IndexPath(row: row, section: section))
//
if let catalogModel = catalogModel, let pageModel = pageModel {
return (catalogModel, pageModel)
}
//
section += 1
row = 0
return getPageData(IndexPath(row: row, section: section))
}
///
func getAbovePageData() -> (NRReadChapterCatalogModel?, NRReadPageModel?) {
var section = self.currentPageIndexPath.section
var row = self.currentPageIndexPath.row - 1
///
if row < 0 {
section -= 1
guard section >= 0 else { return (nil, nil) }
guard chapterCatalogList.count > section else { return (nil, nil) }
let catalogModel = chapterCatalogList[section]
row = (catalogModel.chapterModel?.pageList?.count ?? 0) - 1
}
///
if section < 0 {
return (nil, nil)
}
return getPageData(IndexPath(row: row, section: section))
}
///
func parserAllDataAndReloadPage(dismissMenu: Bool = true) {
///
self.chapterCatalogList.forEach {
$0.parserAllData()
}
self.checkCurrentIndexPath(haveText: true)
if let vc = self.vc?.getCurrentReadController() {
self.vc?.setViewController(displayController: vc, isAbove: false, animated: false, dismissMenu: dismissMenu)
}
}
///
///
func checkCurrentIndexPath(haveText: Bool = false) {
var currentRow = self.currentPageIndexPath.row
var currentSection = self.currentPageIndexPath.section
if chapterCatalogList.count <= currentSection {
currentSection = chapterCatalogList.count - 1
}
let catalogModel = chapterCatalogList[currentSection]
let listCount = catalogModel.chapterModel?.pageList?.count ?? 0
if listCount <= currentRow, listCount > 0 {
currentRow = listCount - 1
}
if haveText {
let currentPage = catalogModel.chapterModel?.pageList?[currentRow]
if currentPage?.pageType != .textPart {
currentRow = currentRow - 1
}
}
self.currentPageIndexPath = IndexPath(row: currentRow, section: currentSection)
}
/// 0-1
func skip(chapterIndex: Int, chapterProgress: CGFloat = 0, dismissMenu: Bool = true) {
let (catalogModel, _) = getPageData(IndexPath(row: 0, section: chapterIndex))
guard let catalogModel = catalogModel else { return }
if let chapterModel = catalogModel.chapterModel {
guard let displayController = vc?.getReadController(catalogModel: catalogModel, pageModel: chapterModel.pageList?.first) else { return }
self.vc?.setViewController(displayController: displayController, isAbove: false, animated: false, dismissMenu: dismissMenu)
//
if chapterModel.novel_txt == nil {
Task {
guard let _ = await self.requestChapterData(catalogModel, isToast: true) else { return }
await MainActor.run {
self.vc?.reloadData()
}
}
}
} else { //
Task {
guard let _ = await self.requestChapterData(catalogModel, isToast: true) else { return }
await MainActor.run {
self.skip(chapterIndex: chapterIndex, chapterProgress: chapterProgress, dismissMenu: dismissMenu)
}
}
}
}
///
func skipToNextChapter() {
let section = self.currentPageIndexPath.section + 1
self.skip(chapterIndex: section, dismissMenu: false)
}
///
func skipToPrevChapter() {
let section = self.currentPageIndexPath.section - 1
self.skip(chapterIndex: section, dismissMenu: false)
}
///
func saveReadRecord() {
guard novelId.count > 0 else { return }
let (catalogModel, pageModel) = getCurrentPageData()
//
guard catalogModel?.is_lock == false else { return }
guard let catalogModel = catalogModel, let pageModel = pageModel else { return }
guard pageModel.pageType == .textPart else { return }
let model = NRNovelReadRecordModel()
model.short_play_video_id = catalogModel.id
model.episode = catalogModel.episode
model.page = pageModel.page?.intValue
NRKeyedArchiver.archiver(folderName: kNRReadRecordFolderName, fileName: novelId, object: model)
if self.lastUploadCatalogId == nil || self.lastUploadCatalogId != catalogModel.id {
self.lastUploadCatalogId = catalogModel.id
Task {
let result = await NRNovelAPI.requestUploadRecord(novelId, chapterId: catalogModel.id ?? "")
if !result {
self.lastUploadCatalogId = nil
}
}
}
}
///
func getReadRecord() -> NRNovelReadRecordModel? {
guard novelId.count > 0 else { return nil }
var recordModel = NRKeyedArchiver.unarchiver(folderName: kNRReadRecordFolderName, fileName: novelId, as: NRNovelReadRecordModel.self)
//
if self.novelModel?.progress?.short_play_video_id != "0", self.novelModel?.progress?.short_play_video_id != recordModel?.short_play_video_id {
recordModel = self.novelModel?.progress
}
return recordModel
}
///
func setEmptyData() {
for model in self.chapterCatalogList {
if model.chapterModel == nil {
model.parserEmpty()
}
}
}
}
//MARK:
extension NRNovelReadViewModel {
///
func requestNovelDetail() async {
let (model, _, _) = await NRNovelAPI.requestDetail(self.novelId)
guard let model = model else { return }
await MainActor.run {
self.novelModel = model
}
}
///
func requestChapterCatalogList() async {
guard let list = await NRNovelAPI.requestChapterCatalogList(id: self.novelId) else { return }
await MainActor.run {
self.chapterCatalogList = list
self.setEmptyData()
}
}
///
@discardableResult
func requestChapterData(_ catalogModel: NRReadChapterCatalogModel, isToast: Bool = false) async -> NRReadChapterModel? {
guard let chapterId = catalogModel.id else { return nil }
let (model, code) = await NRNovelAPI.requestChapterData(novelId: self.novelId, chapterId: chapterId, isToast: isToast)
Task {//线
await NRLoginManager.manager.updateUserInfo()
}
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
if catalogModel.is_lock == true {
catalogModel.is_lock = false
}
return model
}
return nil
}
///
func preloadChapterData() {
Task {
await loadBelowChapterData()
await loadAboveChapterData()
}
}
///
func loadBelowChapterData() async {
//
let (currentCatalogModel, _) = getCurrentPageData()
guard let currentCatalogModel = currentCatalogModel else { return }
guard currentCatalogModel.chapterModel?.novel_txt != nil else { return }
let (catalogModel, _) = getPageData(IndexPath(row: 0, section: self.currentPageIndexPath.section + 1))
guard let catalogModel = catalogModel else { return }
if catalogModel.chapterModel?.novel_txt == nil {
await requestChapterData(catalogModel)
}
}
///
func loadAboveChapterData() async {
let (catalogModel, _) = getPageData(IndexPath(row: 0, section: self.currentPageIndexPath.section - 1))
guard let catalogModel = catalogModel else { return }
if catalogModel.chapterModel?.novel_txt == nil {
await requestChapterData(catalogModel)
}
}
}