将 PDF 成品阅读控制器下沉为 RDPDFReaderView SDK,并修复手机横屏单页连续竖滑

SDK 化收尾:
- 新增 RDPDFReaderView 本地 pod(阅读容器、成品控制器、划线/注释、画笔、
  目录/设置面板、主题与持久化契约),Demo 精简为 PDFKit 页面提供者 + 持久化宿主
- Podfile/工程接入 RDPDFReaderView 与 SnapKit,示例书改用 PDF 阅读器示例文件

手机横屏单页竖滑修复:
- cell 高度改为宽度适配后的纸张高度(sizeForItemAt + 宿主按页提供纵横比),
  纵向超出一屏的内容由外层 collectionView 连续滚动承接,不再被裁掉
- 页面内部不再开启同向嵌套的兜底竖向拖动,修复外层滚动被吞、无法滚到下一页
- 修复 applyContentSize 先评估拖动开关后写 contentSize 的顺序缺陷
- 页码按视口中心命中 cell 计算,补 didEndDragging 兜底;旋转重锚点与
  transitionToPage 改用真实布局位置
- 横竖屏同为竖滑时也重建 cell 并刷新全部可见页的适配配置
- 横屏单页点击不再跳页,只显隐工具栏;翻页交给连续竖滑

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-07-15 18:49:44 +09:00
co-authored by Claude Fable 5
parent a17164d1a9
commit 1422461224
347 changed files with 9912 additions and 3941 deletions
@@ -1,6 +1,19 @@
import XCTest
extension XCUIApplication {
func launchAndOpenSamplePDF(
bookTitleQuery: String = "PDF阅读器示例",
resetsReaderState: Bool = true,
pdfTextSource: String? = nil
) {
launchAndOpenSampleBook(
bookTitleQuery: bookTitleQuery,
displayType: "pagecurl",
resetsReaderState: resetsReaderState,
pdfTextSource: pdfTextSource
)
}
func launchAndOpenSampleBook(
bookTitleQuery: String = "回归验证样本",
displayType: String? = nil,
@@ -12,7 +25,8 @@ extension XCUIApplication {
corruptsCache: Bool = false,
allowsInspectableWebViews: Bool = false,
enablesVerboseWebLogs: Bool = false,
searchKeyword: String? = nil
searchKeyword: String? = nil,
pdfTextSource: String? = nil
) {
var args = ["--demo-book-title", bookTitleQuery]
if resetsReaderState {
@@ -45,6 +59,9 @@ extension XCUIApplication {
if let searchKeyword {
args += ["--demo-search-keyword", searchKeyword]
}
if let pdfTextSource {
args += ["--demo-pdf-text-source", pdfTextSource]
}
launchArguments = args
launch()
}
@@ -74,7 +91,7 @@ extension XCUIApplication {
let deadline = Date().addingTimeInterval(timeout)
while Date() < deadline {
let content = otherElements[IDs.readerContent]
let content = otherElements[IDs.readerContent].firstMatch
if content.waitForExistence(timeout: 1) {
content.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
} else {
@@ -92,7 +109,7 @@ extension XCUIApplication {
for _ in 0..<3 {
guard buttons[IDs.readerBack].exists else { return }
let content = otherElements[IDs.readerContent]
let content = otherElements[IDs.readerContent].firstMatch
if content.waitForExistence(timeout: 2) {
content.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.6)).tap()
}
@@ -139,7 +156,7 @@ extension XCUIApplication {
return selectionText
}
let content = otherElements[IDs.readerContent]
let content = otherElements[IDs.readerContent].firstMatch
if content.exists {
content.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}