feat: optimize reader caching and document formats
This commit is contained in:
@@ -45,8 +45,8 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
DTCoreText: 11b7fe2104f476f82e75a4e3dbdde74d7186cecb
|
||||
DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0
|
||||
RDEpubReaderView: 6bab24a23236a223b29a02f3d00b6ac7829a4b97
|
||||
RDPDFReaderView: ea8c225655c8fdc1f34d75026e05fa1e50744b36
|
||||
RDEpubReaderView: 5a09a7856f04b6f2f8610aa6fd965d35cadb8e17
|
||||
RDPDFReaderView: f7c2d0ea7c129aa4ab15ae7f9daad2974573d749
|
||||
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
|
||||
ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "RDEpubReaderView",
|
||||
"module_name": "RDEpubReaderView",
|
||||
"version": "0.0.2",
|
||||
"summary": "A reader view for EPUB and plain-text books",
|
||||
"summary": "A reader view for EPUB, TXT, MOBI, and CBZ books",
|
||||
"platforms": {
|
||||
"ios": "15.0"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "RDPDFReaderView",
|
||||
"module_name": "RDPDFReaderView",
|
||||
"version": "0.0.1",
|
||||
"summary": "Independent UIKit PDF reader interaction engine",
|
||||
"summary": "UIKit PDF reader supporting host images and direct PDFKit parsing",
|
||||
"platforms": {
|
||||
"ios": "15.0"
|
||||
},
|
||||
@@ -25,7 +25,8 @@
|
||||
},
|
||||
"frameworks": [
|
||||
"Vision",
|
||||
"CoreImage"
|
||||
"CoreImage",
|
||||
"PDFKit"
|
||||
],
|
||||
"requires_arc": true,
|
||||
"swift_version": "5.10"
|
||||
|
||||
Generated
+2
-2
@@ -45,8 +45,8 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
DTCoreText: 11b7fe2104f476f82e75a4e3dbdde74d7186cecb
|
||||
DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0
|
||||
RDEpubReaderView: 6bab24a23236a223b29a02f3d00b6ac7829a4b97
|
||||
RDPDFReaderView: ea8c225655c8fdc1f34d75026e05fa1e50744b36
|
||||
RDEpubReaderView: 5a09a7856f04b6f2f8610aa6fd965d35cadb8e17
|
||||
RDPDFReaderView: f7c2d0ea7c129aa4ab15ae7f9daad2974573d749
|
||||
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
|
||||
ZIPFoundation: dfd3d681c4053ff7e2f7350bc4e53b5dba3f5351
|
||||
|
||||
|
||||
+2152
-2123
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -5,7 +5,7 @@ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText/DTCoreText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation/DTFoundation.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView/RDPDFReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation/ZIPFoundation.framework/Headers" "$(SDKROOT)/usr/include/libxml2"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
|
||||
OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -l"xml2" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "RDEpubReaderView" -framework "RDPDFReaderView" -framework "SnapKit" -framework "Vision" -framework "ZIPFoundation"
|
||||
OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -l"xml2" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "PDFKit" -framework "QuartzCore" -framework "RDEpubReaderView" -framework "RDPDFReaderView" -framework "SnapKit" -framework "Vision" -framework "ZIPFoundation"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "-F${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
|
||||
Generated
+1
-1
@@ -5,7 +5,7 @@ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText/DTCoreText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation/DTFoundation.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView/RDEpubReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView/RDPDFReaderView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation/ZIPFoundation.framework/Headers" "$(SDKROOT)/usr/include/libxml2"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift
|
||||
OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -l"xml2" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "QuartzCore" -framework "RDEpubReaderView" -framework "RDPDFReaderView" -framework "SnapKit" -framework "Vision" -framework "ZIPFoundation"
|
||||
OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -l"xml2" -framework "CoreGraphics" -framework "CoreImage" -framework "CoreText" -framework "DTCoreText" -framework "DTFoundation" -framework "ImageIO" -framework "MediaPlayer" -framework "PDFKit" -framework "QuartzCore" -framework "RDEpubReaderView" -framework "RDPDFReaderView" -framework "SnapKit" -framework "Vision" -framework "ZIPFoundation"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DTCoreText" "-F${PODS_CONFIGURATION_BUILD_DIR}/DTFoundation" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDEpubReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView" "-F${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "-F${PODS_CONFIGURATION_BUILD_DIR}/ZIPFoundation"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
|
||||
OTHER_LDFLAGS = $(inherited) -framework "CoreImage" -framework "SnapKit" -framework "Vision"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "CoreImage" -framework "PDFKit" -framework "SnapKit" -framework "Vision"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RDPDFReaderView
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
|
||||
OTHER_LDFLAGS = $(inherited) -framework "CoreImage" -framework "SnapKit" -framework "Vision"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "CoreImage" -framework "PDFKit" -framework "SnapKit" -framework "Vision"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
1A2B3C4D00000015AABBCC01 /* AsyncChapterLoadingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2B3C4D00000016AABBCC01 /* AsyncChapterLoadingTests.swift */; };
|
||||
1A2B3C4D00000021AABBCC01 /* MemoryFootprintTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2B3C4D00000020AABBCC01 /* MemoryFootprintTests.swift */; };
|
||||
1A2B3C4D00000030AABBCC01 /* FixedLayoutRotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2B3C4D00000031AABBCC01 /* FixedLayoutRotationTests.swift */; };
|
||||
1A2B3C4D00000033AABBCC01 /* PDFDrawingModeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2B3C4D00000032AABBCC01 /* PDFDrawingModeTests.swift */; };
|
||||
23BB1155EA379786DAA10A89 /* DisplayTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB49AFCCBC2BE04C82B8F286 /* DisplayTypeTests.swift */; };
|
||||
369C9658D870DCAFC17EB7F7 /* SearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE01DBDCB8D790832A4DE3F /* SearchTests.swift */; };
|
||||
3BC5C96D7A0ACF35F2192CC7 /* XCUIApplication+Launch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4C44287820D68ED6570F8 /* XCUIApplication+Launch.swift */; };
|
||||
@@ -31,6 +32,18 @@
|
||||
C08FF8D030048DC5147729E9 /* ReaderOpenCloseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EDF066BA12974E6CFBE519F /* ReaderOpenCloseTests.swift */; };
|
||||
DE1437A969DA1C5F0CBB047D /* Pods_ReadViewDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 792DF85CE4A3DD80D67843C7 /* Pods_ReadViewDemo.framework */; };
|
||||
FEDB5937CEB858CB06E38E2D /* SettingsPanelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 201C2B482287866487EFAE66 /* SettingsPanelTests.swift */; };
|
||||
2B3C4D5E00000001AABBCC01 /* BookmarkChromeStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000001AABBCC02 /* BookmarkChromeStateTests.swift */; };
|
||||
2B3C4D5E00000002AABBCC01 /* BookmarkManagementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000002AABBCC02 /* BookmarkManagementTests.swift */; };
|
||||
2B3C4D5E00000003AABBCC01 /* ErrorAndEdgeCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000003AABBCC02 /* ErrorAndEdgeCaseTests.swift */; };
|
||||
2B3C4D5E00000004AABBCC01 /* HighlightsManagementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000004AABBCC02 /* HighlightsManagementTests.swift */; };
|
||||
2B3C4D5E00000005AABBCC01 /* LargeBookOnDemandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000005AABBCC02 /* LargeBookOnDemandTests.swift */; };
|
||||
2B3C4D5E00000006AABBCC01 /* LocationPersistenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000006AABBCC02 /* LocationPersistenceTests.swift */; };
|
||||
2B3C4D5E00000007AABBCC01 /* NavigationBackwardTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000007AABBCC02 /* NavigationBackwardTests.swift */; };
|
||||
2B3C4D5E00000008AABBCC01 /* SelectionAnnotateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000008AABBCC02 /* SelectionAnnotateTests.swift */; };
|
||||
2B3C4D5E00000009AABBCC01 /* SelectionMenuTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E00000009AABBCC02 /* SelectionMenuTests.swift */; };
|
||||
2B3C4D5E0000000AAABBCC01 /* SettingsEffectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E0000000AAABBCC02 /* SettingsEffectTests.swift */; };
|
||||
2B3C4D5E0000000BAABBCC01 /* TOCInteractionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E0000000BAABBCC02 /* TOCInteractionTests.swift */; };
|
||||
2B3C4D5E0000000CAABBCC01 /* ToolbarStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3C4D5E0000000CAABBCC02 /* ToolbarStateTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -58,6 +71,7 @@
|
||||
1A2B3C4D00000016AABBCC01 /* AsyncChapterLoadingTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AsyncChapterLoadingTests.swift; sourceTree = "<group>"; };
|
||||
1A2B3C4D00000020AABBCC01 /* MemoryFootprintTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MemoryFootprintTests.swift; sourceTree = "<group>"; };
|
||||
1A2B3C4D00000031AABBCC01 /* FixedLayoutRotationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FixedLayoutRotationTests.swift; sourceTree = "<group>"; };
|
||||
1A2B3C4D00000032AABBCC01 /* PDFDrawingModeTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PDFDrawingModeTests.swift; sourceTree = "<group>"; };
|
||||
201C2B482287866487EFAE66 /* SettingsPanelTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SettingsPanelTests.swift; sourceTree = "<group>"; };
|
||||
20BD15E5D8F04E7E9A239E14 /* ReaderAnnotationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ReaderAnnotationTests.swift; sourceTree = "<group>"; };
|
||||
3A43AED288BFCA3ADBA97DD7 /* Pods-ReadViewDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReadViewDemo.release.xcconfig"; path = "Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo.release.xcconfig"; sourceTree = "<group>"; };
|
||||
@@ -72,6 +86,18 @@
|
||||
CFE01DBDCB8D790832A4DE3F /* SearchTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SearchTests.swift; sourceTree = "<group>"; };
|
||||
DE070C1D2FBF0CC900ED065F /* ReadViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReadViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FB49AFCCBC2BE04C82B8F286 /* DisplayTypeTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DisplayTypeTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000001AABBCC02 /* BookmarkChromeStateTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BookmarkChromeStateTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000002AABBCC02 /* BookmarkManagementTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BookmarkManagementTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000003AABBCC02 /* ErrorAndEdgeCaseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ErrorAndEdgeCaseTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000004AABBCC02 /* HighlightsManagementTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HighlightsManagementTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000005AABBCC02 /* LargeBookOnDemandTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LargeBookOnDemandTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000006AABBCC02 /* LocationPersistenceTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocationPersistenceTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000007AABBCC02 /* NavigationBackwardTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationBackwardTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000008AABBCC02 /* SelectionAnnotateTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectionAnnotateTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E00000009AABBCC02 /* SelectionMenuTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectionMenuTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E0000000AAABBCC02 /* SettingsEffectTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SettingsEffectTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E0000000BAABBCC02 /* TOCInteractionTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TOCInteractionTests.swift; sourceTree = "<group>"; };
|
||||
2B3C4D5E0000000CAABBCC02 /* ToolbarStateTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ToolbarStateTests.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
@@ -187,6 +213,18 @@
|
||||
FB49AFCCBC2BE04C82B8F286 /* DisplayTypeTests.swift */,
|
||||
1A2B3C4D00000008AABBCC01 /* PageNavigationTests.swift */,
|
||||
A1C5E34F6B7192D400A1B235 /* PDFAnnotationTests.swift */,
|
||||
2B3C4D5E00000001AABBCC02 /* BookmarkChromeStateTests.swift */,
|
||||
2B3C4D5E00000002AABBCC02 /* BookmarkManagementTests.swift */,
|
||||
2B3C4D5E00000003AABBCC02 /* ErrorAndEdgeCaseTests.swift */,
|
||||
2B3C4D5E00000004AABBCC02 /* HighlightsManagementTests.swift */,
|
||||
2B3C4D5E00000005AABBCC02 /* LargeBookOnDemandTests.swift */,
|
||||
2B3C4D5E00000006AABBCC02 /* LocationPersistenceTests.swift */,
|
||||
2B3C4D5E00000007AABBCC02 /* NavigationBackwardTests.swift */,
|
||||
2B3C4D5E00000008AABBCC02 /* SelectionAnnotateTests.swift */,
|
||||
2B3C4D5E00000009AABBCC02 /* SelectionMenuTests.swift */,
|
||||
2B3C4D5E0000000AAABBCC02 /* SettingsEffectTests.swift */,
|
||||
2B3C4D5E0000000BAABBCC02 /* TOCInteractionTests.swift */,
|
||||
2B3C4D5E0000000CAABBCC02 /* ToolbarStateTests.swift */,
|
||||
20BD15E5D8F04E7E9A239E14 /* ReaderAnnotationTests.swift */,
|
||||
1A2B3C4D0000000AAABBCC01 /* ReaderAnnotationExtendedTests.swift */,
|
||||
9EDF066BA12974E6CFBE519F /* ReaderOpenCloseTests.swift */,
|
||||
@@ -202,6 +240,7 @@
|
||||
1A2B3C4D00000020AABBCC01 /* MemoryFootprintTests.swift */,
|
||||
1A2B3C4D00000016AABBCC01 /* AsyncChapterLoadingTests.swift */,
|
||||
1A2B3C4D00000031AABBCC01 /* FixedLayoutRotationTests.swift */,
|
||||
1A2B3C4D00000032AABBCC01 /* PDFDrawingModeTests.swift */,
|
||||
);
|
||||
path = ReaderUITests;
|
||||
sourceTree = "<group>";
|
||||
@@ -355,6 +394,18 @@
|
||||
23BB1155EA379786DAA10A89 /* DisplayTypeTests.swift in Sources */,
|
||||
1A2B3C4D00000007AABBCC01 /* PageNavigationTests.swift in Sources */,
|
||||
A1C5E34F6B7192D400A1B234 /* PDFAnnotationTests.swift in Sources */,
|
||||
2B3C4D5E00000001AABBCC01 /* BookmarkChromeStateTests.swift in Sources */,
|
||||
2B3C4D5E00000002AABBCC01 /* BookmarkManagementTests.swift in Sources */,
|
||||
2B3C4D5E00000003AABBCC01 /* ErrorAndEdgeCaseTests.swift in Sources */,
|
||||
2B3C4D5E00000004AABBCC01 /* HighlightsManagementTests.swift in Sources */,
|
||||
2B3C4D5E00000005AABBCC01 /* LargeBookOnDemandTests.swift in Sources */,
|
||||
2B3C4D5E00000006AABBCC01 /* LocationPersistenceTests.swift in Sources */,
|
||||
2B3C4D5E00000007AABBCC01 /* NavigationBackwardTests.swift in Sources */,
|
||||
2B3C4D5E00000008AABBCC01 /* SelectionAnnotateTests.swift in Sources */,
|
||||
2B3C4D5E00000009AABBCC01 /* SelectionMenuTests.swift in Sources */,
|
||||
2B3C4D5E0000000AAABBCC01 /* SettingsEffectTests.swift in Sources */,
|
||||
2B3C4D5E0000000BAABBCC01 /* TOCInteractionTests.swift in Sources */,
|
||||
2B3C4D5E0000000CAABBCC01 /* ToolbarStateTests.swift in Sources */,
|
||||
52A6A0C9941A4B5F9B88C6B0 /* ReaderAnnotationTests.swift in Sources */,
|
||||
1A2B3C4D00000009AABBCC01 /* ReaderAnnotationExtendedTests.swift in Sources */,
|
||||
C08FF8D030048DC5147729E9 /* ReaderOpenCloseTests.swift in Sources */,
|
||||
@@ -370,6 +421,7 @@
|
||||
1A2B3C4D00000021AABBCC01 /* MemoryFootprintTests.swift in Sources */,
|
||||
1A2B3C4D00000015AABBCC01 /* AsyncChapterLoadingTests.swift in Sources */,
|
||||
1A2B3C4D00000030AABBCC01 /* FixedLayoutRotationTests.swift in Sources */,
|
||||
1A2B3C4D00000033AABBCC01 /* PDFDrawingModeTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -10,19 +10,23 @@ enum PDFDemoImageTextSource: String {
|
||||
case none
|
||||
}
|
||||
|
||||
/// PDFKit 适配层:只负责把宿主 PDF 变成 SDK 的页面、缩略图和目录数据。
|
||||
private final class PDFDemoPageProvider: RDPDFReaderPageProvider, RDPDFReaderOutlineProviding {
|
||||
/// 模拟“宿主只能提供页面图片”的适配层,用于验证自定义加密 PDF 接入方式。
|
||||
private final class PDFDemoPageProvider: RDPDFReaderPageProvider, RDPDFReaderOutlineProviding, RDPDFReaderAsyncOutlineProviding {
|
||||
private let document: PDFDocument
|
||||
private let identifier: String
|
||||
private let title: String
|
||||
private let textSource: PDFDemoImageTextSource
|
||||
private var images: [Int: UIImage] = [:]
|
||||
private let renderQueue = DispatchQueue(label: "com.readviewsdk.demo-pdf-render", qos: .userInitiated)
|
||||
private let images = NSCache<NSNumber, UIImage>()
|
||||
private var outlineItemsCache: [RDPDFReaderOutlineItem]?
|
||||
|
||||
init(document: PDFDocument, identifier: String, title: String, textSource: PDFDemoImageTextSource) {
|
||||
self.document = document
|
||||
self.identifier = identifier
|
||||
self.title = title
|
||||
self.textSource = textSource
|
||||
images.countLimit = 6
|
||||
images.totalCostLimit = 96 * 1024 * 1024
|
||||
}
|
||||
|
||||
func readerBookDescriptor() -> RDPDFReaderBookDescriptor {
|
||||
@@ -35,19 +39,46 @@ private final class PDFDemoPageProvider: RDPDFReaderPageProvider, RDPDFReaderOut
|
||||
case .hostFixture: textRuns = fixtureTextRuns(for: index)
|
||||
case .vision, .none: textRuns = nil
|
||||
}
|
||||
completion(.init(index: index, image: image(at: index), textRuns: textRuns))
|
||||
renderQueue.async { [weak self] in
|
||||
guard let self else { return }
|
||||
let image = self.image(at: index)
|
||||
DispatchQueue.main.async { completion(.init(index: index, image: image, textRuns: textRuns)) }
|
||||
}
|
||||
}
|
||||
|
||||
func readerThumbnail(at index: Int, targetSize: CGSize, completion: @escaping (UIImage?) -> Void) {
|
||||
guard let page = document.page(at: index) else { completion(nil); return }
|
||||
let box = page.bounds(for: .mediaBox)
|
||||
let scale = min(targetSize.width / box.width, targetSize.height / box.height) * UIScreen.main.scale
|
||||
let size = CGSize(width: box.width * scale, height: box.height * scale)
|
||||
completion(render(page, size: size, scale: scale))
|
||||
renderQueue.async { [weak self] in
|
||||
guard let self, let page = self.document.page(at: index) else {
|
||||
DispatchQueue.main.async { completion(nil) }
|
||||
return
|
||||
}
|
||||
let box = page.bounds(for: .mediaBox)
|
||||
let scale = min(targetSize.width / box.width, targetSize.height / box.height) * UIScreen.main.scale
|
||||
let size = CGSize(width: box.width * scale, height: box.height * scale)
|
||||
let image = self.render(page, size: size, scale: scale)
|
||||
DispatchQueue.main.async { completion(image) }
|
||||
}
|
||||
}
|
||||
|
||||
func readerOutlineItems() -> [RDPDFReaderOutlineItem] {
|
||||
guard let root = document.outlineRoot else { return pageOutlineItems() }
|
||||
renderQueue.sync { outlineItemsLocked() }
|
||||
}
|
||||
|
||||
func readerOutlineItems(completion: @escaping ([RDPDFReaderOutlineItem]) -> Void) {
|
||||
renderQueue.async { [weak self] in
|
||||
guard let self else { return }
|
||||
let items = self.outlineItemsLocked()
|
||||
DispatchQueue.main.async { completion(items) }
|
||||
}
|
||||
}
|
||||
|
||||
private func outlineItemsLocked() -> [RDPDFReaderOutlineItem] {
|
||||
if let outlineItemsCache { return outlineItemsCache }
|
||||
guard let root = document.outlineRoot else {
|
||||
let items = pageOutlineItems()
|
||||
outlineItemsCache = items
|
||||
return items
|
||||
}
|
||||
var items: [RDPDFReaderOutlineItem] = []
|
||||
func append(_ outline: PDFOutline, level: Int) {
|
||||
for index in 0..<outline.numberOfChildren {
|
||||
@@ -60,7 +91,9 @@ private final class PDFDemoPageProvider: RDPDFReaderPageProvider, RDPDFReaderOut
|
||||
}
|
||||
}
|
||||
append(root, level: 0)
|
||||
return items.isEmpty ? pageOutlineItems() : items
|
||||
let resolved = items.isEmpty ? pageOutlineItems() : items
|
||||
outlineItemsCache = resolved
|
||||
return resolved
|
||||
}
|
||||
|
||||
func transformed(_ image: UIImage, for theme: RDPDFReaderThemeOption) -> UIImage {
|
||||
@@ -81,12 +114,14 @@ private final class PDFDemoPageProvider: RDPDFReaderPageProvider, RDPDFReaderOut
|
||||
}
|
||||
|
||||
private func image(at index: Int) -> UIImage? {
|
||||
if let image = images[index] { return image }
|
||||
if let image = images.object(forKey: NSNumber(value: index)) { return image }
|
||||
guard let page = document.page(at: index) else { return nil }
|
||||
let box = page.bounds(for: .mediaBox)
|
||||
let scale = max(2, UIScreen.main.scale)
|
||||
let image = render(page, size: CGSize(width: box.width * scale, height: box.height * scale), scale: scale)
|
||||
images[index] = image
|
||||
let cost = image.cgImage.map { $0.bytesPerRow * $0.height }
|
||||
?? Int(image.size.width * image.size.height * image.scale * image.scale * 4)
|
||||
images.setObject(image, forKey: NSNumber(value: index), cost: cost)
|
||||
return image
|
||||
}
|
||||
|
||||
@@ -118,6 +153,8 @@ final class PDFDemoReaderViewController: UIViewController, RDPDFReaderViewContro
|
||||
private let reader: RDPDFReaderViewController
|
||||
private var navigationBarHiddenBeforeReader: Bool?
|
||||
private var display = "pagecurl"
|
||||
private var lastPageIndex = 0
|
||||
private var lastCopiedText: String?
|
||||
private let stateLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.accessibilityIdentifier = "demo.reader.state"
|
||||
@@ -127,19 +164,44 @@ final class PDFDemoReaderViewController: UIViewController, RDPDFReaderViewContro
|
||||
}()
|
||||
|
||||
init(url: URL, bookIdentifier: String? = nil, textSource: PDFDemoImageTextSource = .vision) {
|
||||
guard let document = PDFDocument(url: url) else { fatalError("无法打开 PDF") }
|
||||
let identifier = bookIdentifier ?? url.lastPathComponent
|
||||
let provider = PDFDemoPageProvider(document: document, identifier: identifier, title: url.deletingPathExtension().lastPathComponent, textSource: textSource)
|
||||
let store = RDPDFReaderPersistenceStore(rootURL: Self.annotationStorageURL(for: identifier, legacyBookURL: url))
|
||||
var configuration = RDPDFReaderViewController.Configuration()
|
||||
configuration.enablesOCR = textSource == .vision
|
||||
configuration.missingTextSource = .region
|
||||
configuration.recognitionLanguages = ["zh-Hans", "en-US"]
|
||||
configuration.pageImageTransform = { [weak provider] image, theme in provider?.transformed(image, for: theme) ?? image }
|
||||
reader = RDPDFReaderViewController(pageProvider: provider, annotationPersistence: store, configuration: configuration)
|
||||
|
||||
if textSource != .vision {
|
||||
guard let document = PDFDocument(url: url) else { fatalError("无法打开 PDF") }
|
||||
let provider = PDFDemoPageProvider(
|
||||
document: document,
|
||||
identifier: identifier,
|
||||
title: url.deletingPathExtension().lastPathComponent,
|
||||
textSource: textSource
|
||||
)
|
||||
configuration.pageImageTransform = { [weak provider] image, theme in
|
||||
provider?.transformed(image, for: theme) ?? image
|
||||
}
|
||||
reader = RDPDFReaderViewController(
|
||||
pageProvider: provider,
|
||||
annotationPersistence: store,
|
||||
configuration: configuration
|
||||
)
|
||||
} else {
|
||||
do {
|
||||
reader = try RDPDFReaderViewController(
|
||||
pdfURL: url,
|
||||
bookIdentifier: identifier,
|
||||
annotationPersistence: store,
|
||||
configuration: configuration
|
||||
)
|
||||
} catch {
|
||||
fatalError("无法打开 PDF:\(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
reader.delegate = self
|
||||
title = provider.readerBookDescriptor().title
|
||||
title = url.deletingPathExtension().lastPathComponent
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
@@ -182,6 +244,11 @@ final class PDFDemoReaderViewController: UIViewController, RDPDFReaderViewContro
|
||||
|
||||
func pdfReaderViewController(_ controller: RDPDFReaderViewController, didChangePage pageIndex: Int) { updateState(page: pageIndex) }
|
||||
|
||||
func pdfReaderViewController(_ controller: RDPDFReaderViewController, didCopyText text: String) {
|
||||
lastCopiedText = text
|
||||
updateState(page: lastPageIndex)
|
||||
}
|
||||
|
||||
func pdfReaderViewController(_ controller: RDPDFReaderViewController, didFailAnnotationPersistence error: Error) {
|
||||
stateLabel.text = "reader=opened mode=pdf annotationStorage=error"
|
||||
guard presentedViewController == nil else { return }
|
||||
@@ -190,7 +257,16 @@ final class PDFDemoReaderViewController: UIViewController, RDPDFReaderViewContro
|
||||
present(alert, animated: true)
|
||||
}
|
||||
|
||||
private func updateState(page: Int) { stateLabel.text = "reader=opened mode=pdf page=\(page + 1) display=\(display)" }
|
||||
private func updateState(page: Int) {
|
||||
lastPageIndex = page
|
||||
var state = "reader=opened mode=pdf page=\(page + 1) display=\(display)"
|
||||
if let lastCopiedText {
|
||||
// 状态字段以空格分隔,文本需百分号编码;UI 测试端会解码还原。
|
||||
let encoded = lastCopiedText.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? ""
|
||||
state += " copy=success copiedText=\(encoded)"
|
||||
}
|
||||
stateLabel.text = state
|
||||
}
|
||||
|
||||
private static func annotationStorageURL(for bookIdentifier: String, legacyBookURL: URL) -> URL {
|
||||
let root = annotationStorageRoot()
|
||||
|
||||
@@ -112,7 +112,7 @@ final class ViewController: UIViewController {
|
||||
label.textAlignment = .center
|
||||
label.textColor = .secondaryLabel
|
||||
label.font = .systemFont(ofSize: 15)
|
||||
label.text = "book 目录下暂时没有可阅读的 txt 或 epub 文件"
|
||||
label.text = "book 目录下暂时没有可阅读的 EPUB、TXT、MOBI、CBZ 或 PDF 文件"
|
||||
label.accessibilityIdentifier = "demo.books.empty"
|
||||
return label
|
||||
}()
|
||||
@@ -165,7 +165,7 @@ final class ViewController: UIViewController {
|
||||
|
||||
private func updateChrome() {
|
||||
if books.isEmpty {
|
||||
statusLabel.text = "ReadViewSDK Demo\nbook 目录下未找到 txt 或 epub 文件"
|
||||
statusLabel.text = "ReadViewSDK Demo\nbook 目录下未找到 EPUB、TXT、MOBI、CBZ 或 PDF 文件"
|
||||
tableView.backgroundView = emptyStateLabel
|
||||
} else {
|
||||
statusLabel.text = "ReadViewSDK Demo\n已发现 \(books.count) 本本地图书,点击即可进入阅读器"
|
||||
@@ -191,7 +191,7 @@ final class ViewController: UIViewController {
|
||||
return fileURLs
|
||||
.filter { url in
|
||||
let ext = url.pathExtension.lowercased()
|
||||
return ext == "epub" || ext == "txt" || ext == "pdf"
|
||||
return RDReaderDocumentFormat.supports(url) || ext == "pdf"
|
||||
}
|
||||
.reduce(into: [URL]()) { result, url in
|
||||
if !result.contains(url) {
|
||||
|
||||
@@ -44,9 +44,9 @@ enum IDs {
|
||||
/// The text layer is the precise, image-coordinate based interaction surface.
|
||||
static let pdfTextLayer = "pdf.reader.text.layer"
|
||||
static let pdfOCRStatus = "pdf.reader.ocr.status"
|
||||
/// PDF 选区菜单与 EPUB 相同,使用系统编辑菜单,按菜单项标题(复制/高亮/注释)定位。
|
||||
/// PDF 选区菜单与 EPUB 相同,使用系统编辑菜单,按菜单项标题(复制/划线/注释)定位。
|
||||
static let pdfSelectionMenuCopy = "复制"
|
||||
static let pdfSelectionMenuHighlight = "高亮"
|
||||
static let pdfSelectionMenuHighlight = "划线"
|
||||
static let pdfSelectionMenuAnnotate = "注释"
|
||||
static let pdfCopyStatus = "pdf.reader.copy.status"
|
||||
|
||||
|
||||
@@ -119,7 +119,9 @@ final class HighlightsManagementTests: XCTestCase {
|
||||
let deleteControl = highlightsTable.buttons["删除"].firstMatch
|
||||
XCTAssertTrue(deleteControl.waitForExistence(timeout: 3), "编辑状态应显示删除控件")
|
||||
deleteControl.tap()
|
||||
app.buttons["删除"].lastMatch.tap()
|
||||
// 编辑态的行内“删除”与确认用的“删除”同名;确认按钮是最后出现的那个。
|
||||
let deleteButtons = app.buttons.matching(identifier: "删除")
|
||||
deleteButtons.element(boundBy: max(0, deleteButtons.count - 1)).tap()
|
||||
|
||||
XCTAssertTrue(app.staticTexts[IDs.readerHighlightsEmptyLabel].waitForExistence(timeout: 5), "删除后应显示空状态")
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ final class LocationPersistenceTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testHighlightNavigationSurvivesFontChoiceChange() throws {
|
||||
app.launchAndOpenSampleBook(resetsReaderState: true, pageNumber: 3)
|
||||
app.launchAndOpenSampleBook(pageNumber: 3, resetsReaderState: true)
|
||||
app.waitForReader(timeout: 12)
|
||||
|
||||
let initialState = app.waitForDemoReaderState(timeout: 8, description: "初始位于第 3 页") { state in
|
||||
|
||||
@@ -58,6 +58,46 @@ final class PDFDrawingModeTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
/// 放大状态下同一规则:未选中工具单指拖动画面,选中画笔后单指只用于绘制。
|
||||
func testZoomedPageDragsOnlyWhenDrawingToolIsDeselected() {
|
||||
app.launchAndOpenSampleBook(bookTitleQuery: "英汉大词典", displayType: "pagecurl")
|
||||
app.waitForReader()
|
||||
|
||||
let content = app.otherElements[IDs.readerContent].firstMatch
|
||||
XCTAssertTrue(content.waitForExistence(timeout: 8), "PDF 阅读页面未出现")
|
||||
|
||||
app.showReaderChromeIfNeeded(requiredButtonIDs: [IDs.pdfDrawing])
|
||||
let drawing = app.buttons[IDs.pdfDrawing]
|
||||
XCTAssertTrue(drawing.waitForExistence(timeout: 5), "画笔入口未出现")
|
||||
drawing.tap()
|
||||
|
||||
let pen = app.buttons[IDs.pdfDrawingPen]
|
||||
XCTAssertTrue(pen.waitForExistence(timeout: 5), "画笔工具未出现")
|
||||
|
||||
// 未选中工具 → 双指放大
|
||||
content.pinch(withScale: 2.5, velocity: 1)
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(1.0))
|
||||
let zoomedFrame = content.frame
|
||||
XCTAssertGreaterThan(zoomedFrame.width, app.windows.firstMatch.frame.width * 1.2, "画笔面板打开时无法双指放大页面")
|
||||
|
||||
// 未选中工具 → 单指拖动应移动页面
|
||||
let start = content.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))
|
||||
let end = content.coordinate(withNormalizedOffset: CGVector(dx: 0.3, dy: 0.3))
|
||||
start.press(forDuration: 0.05, thenDragTo: end)
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.8))
|
||||
let draggedFrame = content.frame
|
||||
XCTAssertNotEqual(draggedFrame.origin, zoomedFrame.origin, "未选中工具时,放大页面无法单指拖动")
|
||||
|
||||
// 选中画笔 → 单指应绘制而非拖动
|
||||
pen.tap()
|
||||
let frameBeforeStroke = content.frame
|
||||
let strokeStart = content.coordinate(withNormalizedOffset: CGVector(dx: 0.45, dy: 0.45))
|
||||
let strokeEnd = content.coordinate(withNormalizedOffset: CGVector(dx: 0.6, dy: 0.6))
|
||||
strokeStart.press(forDuration: 0.05, thenDragTo: strokeEnd)
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.8))
|
||||
XCTAssertEqual(content.frame.origin, frameBeforeStroke.origin, "选中画笔后,单指仍拖动了放大页面而不是绘制")
|
||||
}
|
||||
|
||||
private func waitForLandscapeLayout() -> Bool {
|
||||
let deadline = Date().addingTimeInterval(8)
|
||||
while Date() < deadline {
|
||||
@@ -69,8 +109,12 @@ final class PDFDrawingModeTests: XCTestCase {
|
||||
}
|
||||
|
||||
private func scrollToAnotherPage(_ content: XCUIElement, from page: Int) -> Bool {
|
||||
let window = app.windows.firstMatch
|
||||
for _ in 0..<5 {
|
||||
content.swipeUp()
|
||||
// 从屏幕上半部拖动,避开底部画笔工具条区域。
|
||||
let start = window.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.35))
|
||||
let end = window.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.05))
|
||||
start.press(forDuration: 0.05, thenDragTo: end, withVelocity: .fast, thenHoldForDuration: 0)
|
||||
let deadline = Date().addingTimeInterval(1.5)
|
||||
while Date() < deadline {
|
||||
if let current = app.currentDemoReaderState()?.page, current != page { return true }
|
||||
|
||||
Reference in New Issue
Block a user