Reorganize docs and update reader search flows

This commit is contained in:
shenlei
2026-06-10 08:22:07 +08:00
parent 0e7c0577e3
commit d15187b730
72 changed files with 517 additions and 5214 deletions
+84 -10
View File
@@ -1,6 +1,6 @@
# ReadViewSDK 业务逻辑文档
> 最后更新:2026-06-04
> 最后更新:2026-06-09
---
@@ -345,34 +345,46 @@ RTL 模式下左右互换。工具栏显示时,左右区域变为 `.center`(
//
struct RDEPUBAnnotation {
let id: String
let bookIdentifier: String?
let kind: RDEPUBAnnotationKind // .bookmark, .highlight, .underline
let location: RDEPUBLocation
let text: String?
let color: String?
let note: String?
let rangeInfo: String? // CoreText
let chapterTitle: String?
let createdAt: Date
// computed: bookmark, highlight
}
//
struct RDEPUBBookmark {
let id: String
let bookIdentifier: String?
let location: RDEPUBLocation
let chapterTitle: String?
let note: String?
let createdAt: Date
}
//
struct RDEPUBHighlight {
let id: String
let bookIdentifier: String?
let location: RDEPUBLocation
let text: String
let style: RDEPUBHighlightStyle // .highlight, .underline
let color: String
let note: String?
let rangeInfo: String?
let createdAt: Date
}
```
### 6.2 选区处理流程
SDK 支持两条选区处理路径,分别对应 WebView 渲染和原生文本渲染:
**路径 AWebView 渲染(webInteractive / webFixedLayout**
```
用户长按 → WKWebView 选区变化
@@ -387,6 +399,32 @@ RDEPUBReaderAnnotationCoordinator
└─ 显示操作菜单(拷贝/高亮/批注)
```
**路径 B:原生文本渲染(textReflowable**
```
用户长按 → RDEPUBTextContentView.handleLongPress(_:)
├─ layoutIfNeeded() // 确保布局完成
RDEPUBTextSelectionController.handleLongPress(_:)
├─ RDEPUBPageInteractionController.characterIndexForViewPoint()
│ └─ CoreText CTLineGetStringIndexForPosition 字符命中
├─ 计算选区范围 (NSRange)
├─ isSelecting = true
用户拖拽 → handlePan(_:)
├─ 更新选区范围
├─ RDEPUBSelectionOverlayView 绘制选区高亮
└─ .ended/.cancelled/.failed → isSelecting = false(保留选区)
RDEPUBTextContentView delegate → RDEPUBReaderAnnotationCoordinator
├─ 创建 RDEPUBSelection(含 rangeInfo
└─ 显示操作菜单(拷贝/高亮/批注)
```
### 6.3 高亮渲染
文本模式下,高亮通过 NSAttributedString 属性注入:
@@ -415,17 +453,34 @@ CoreText 渲染时识别这些自定义属性并绘制高亮背景/下划线。
### 7.1 全文搜索
SDK 提供两个搜索引擎,分别服务于不同的渲染路径:
**文本渲染路径:`RDEPUBTextSearchEngine`**
`RDEPUBTextSearchEngine.search(keyword:)`
1. 遍历所有 linear spine 条目(html/xhtml 类型)
2. 读取 HTML,转为纯文本:
- 优先:`NSAttributedString(data:options:documentAttributes:)` with `.documentType: .html`
- 回退:正则去除 HTML 标签
3. 执行大小写不敏感的 `NSString.range(of:options:)` 搜索
1. 遍历 `RDEPUBTextBook.chapters` 中的所有章节
2. 对每个章节的 `attributedContent`(已渲染的 NSAttributedString)执行搜索
3. 使用 `NSString.range(of:options:.caseInsensitive)` 进行大小写不敏感搜索
4. 为每个匹配生成:
- `progression`0.0-1.0 的阅读进度
- `previewText`:匹配位置前后各 12 字符
- `rangeAnchor`:精确的文本锚点
- `rangeAnchor`:精确的文本锚点RDEPUBTextRangeAnchor
**纯文本文件搜索:`RDEPUBTextSearchEngine.searchWithoutPublication(textBook:keyword:)`**
静态方法,用于 `.txt` 文件(有 TextBook 但无 Publication)的搜索:
1. 遍历 TextBook 章节的 attributedContent
2. 跳过 publication 依赖的 href 规范化
3. 不生成 rangeAnchor(纯文本无 CoreText 锚点)
**WebView 渲染路径:`RDEPUBHTMLSearchEngine`**
1. 遍历所有 linear spine 条目(html/xhtml 类型)
2. 读取 HTML,转为纯文本(正则去除标签)
3. 执行大小写不敏感搜索
4. 通过 JS Bridge 在 WebView DOM 中绘制搜索高亮
### 7.2 搜索结果导航
@@ -439,7 +494,26 @@ struct RDEPUBSearchState {
}
```
WebView 通过 JS Bridge 接收搜索高亮数据,在 DOM 中绘制高亮矩形。
**搜索结果导航流程:**
`RDEPUBReaderSearchCoordinator` 协调搜索结果的前进/后退导航:
1. `goToNextMatch()` / `goToPreviousMatch()` 更新 `currentMatchIndex`
2. 根据匹配位置计算目标页码,触发页面跳转
3. 通知 `RDEPUBReaderController` 更新搜索计数显示
**搜索结果渲染:**
- **WebView 路径:** 通过 JS Bridge 接收搜索高亮数据,在 DOM 中绘制高亮矩形
- **原生文本路径:** `RDEPUBTextContentView` 根据 `rangeAnchor` 在 CoreText 绘制层高亮匹配文本
**搜索栏生命周期:**
搜索栏采用延迟安装模式:
1. `showSearchBar()` 设置 `isSearchBarVisible = true`,仅在工具栏可见时立即安装视图
2. 若工具栏隐藏,延迟到 `handleToolViewVisibilityChanged(isVisible: true)` 时安装
3. `installSearchBarView()` 负责实际的视图层级添加、约束、动画和焦点管理
---