feat: EPUB阅读器搜索、注释、CFI模块及大书远距跳转优化

- 实现EPUB阅读器搜索功能及选中注释功能
- 优化CFI模块,修复代码审查发现的11个问题
- 实现大书远距目录跳转与后台补全优化方案
- 优化设置面板与章节运行时联动
- 重构及大量改进优化
This commit is contained in:
shenlei
2026-06-22 20:26:34 +08:00
parent f50495ad91
commit c65c190b71
178 changed files with 11380 additions and 6728 deletions
@@ -1,56 +1,24 @@
//
// RDReaderFlowLayout.swift
// RDReaderDemo
//
// Created by yangsq on 2021/8/6.
//
// UICollectionViewFlowLayout
// item +
//
//
// RDReaderView RDReaderView
//
import UIKit
///
///
public protocol RDReaderFlowLayoutDataSoure: NSObjectProtocol {
///
/// - Parameters:
/// - flowLayout:
/// - pageIndex:
/// - Returns: nil 使collectionView.frame.height
func heigtOfVerticalScrollPage(flowLayout: RDReaderFlowLayout, pageIndex: Int) -> CGFloat?
}
///
///
@objc public protocol RDReaderFlowLayoutDelegate: NSObjectProtocol {
///
/// - Parameters:
/// - flowLayout:
/// - pageIndex:
func pageNum(flowLayout: RDReaderFlowLayout, pageIndex: Int)
}
///
/// - horizontalScroll12
/// - verticalScroll
///
/// ``displayType``
/// ``isLandscapeDualPage`` ``coverPageIndex``
public class RDReaderFlowLayout: UICollectionViewFlowLayout {
/// 使
var displayType: RDReaderView.DisplayType = .horizontalScroll {
didSet {
invalidateLayout()
}
}
///
///
var isLandscapeDualPage: Bool = false {
didSet {
if oldValue != isLandscapeDualPage {
@@ -59,8 +27,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
///
///
var coverPageIndex: Int? = nil {
didSet {
if oldValue != coverPageIndex {
@@ -69,11 +35,8 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
/// prepare bounds
private var lastPreparedBoundsSize: CGSize = .zero
///
/// +21
var pagesPerScreen: Int {
guard isLandscapeDualPage else { return 1 }
switch displayType {
@@ -87,24 +50,14 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
///
weak var dataSource: RDReaderFlowLayoutDataSoure? = nil
///
weak var delegate: RDReaderFlowLayoutDelegate? = nil
///
private var hasCoverPageInDualMode: Bool {
return pagesPerScreen > 1 && coverPageIndex != nil
}
/// item frame
///
/// - Parameters:
/// - index: item
/// - screenWidth:
/// - halfWidth:
/// - height:
/// - Returns: item frame
private func coverAwareFrame(for index: Int, screenWidth: CGFloat, halfWidth: CGFloat, height: CGFloat) -> CGRect {
guard let coverIndex = coverPageIndex else {
let pairIdx = index / 2
@@ -125,11 +78,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
return CGRect(x: x, y: 0, width: halfWidth, height: height)
}
/// item
/// - Parameters:
/// - offset:
/// - screenWidth:
/// - Returns: item
private func coverAwareStartIndex(for offset: CGFloat, screenWidth: CGFloat) -> Int {
let pps = pagesPerScreen
guard let coverIdx = coverPageIndex, hasCoverPageInDualMode else {
@@ -147,7 +95,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
/// delegate
private var currentPage: Int = 0 {
didSet {
@@ -157,15 +104,12 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
///
/// - Parameter displayType:
init(displayType: RDReaderView.DisplayType) {
self.displayType = displayType
super.init()
}
/// item
public override func prepare() {
super.prepare()
guard let collectionView = self.collectionView else {
@@ -203,8 +147,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
/// bounds 使
/// true true
public override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
if newBounds.size != lastPreparedBoundsSize {
return true
@@ -219,9 +161,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
/// collectionView
///
/// +
public override var collectionViewContentSize: CGSize {
var size = super.collectionViewContentSize
guard let collectionView = collectionView else {
@@ -243,9 +182,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
return size
}
///
/// item
/// cell
public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributes = super.layoutAttributesForElements(in: rect)
guard let collectionView = collectionView else {
@@ -279,7 +215,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
})
}
if self.displayType == .horizontalScroll {
let pps = pagesPerScreen
@@ -325,10 +260,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
return attributes
}
/// contentOffset
///
/// - Parameter count:
/// - Returns: contentOffset
func currentContentOffset(count: Int) -> CGPoint {
guard let collectionView = collectionView else {
return .zero
@@ -368,7 +299,6 @@ public class RDReaderFlowLayout: UICollectionViewFlowLayout {
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}