feat(reader): 增强阅读器功能与 UI 测试支持

- 新增字体选择(系统/宋体/圆体/等宽)与暗色图片柔化配置
- 文本选择改为自定义手势+操作栏(拷贝/高亮/批注)
- 添加 accessibilityIdentifier 支持自动化 UI 测试
- 新增 UITests 覆盖阅读器打开/关闭、工具栏、设置面板、批注等
- 添加 Demo 测试用 EPUB 书源(宝山辽墓材料与释读)
- 新增文档:UI 自动化测试、功能开发计划、阅读器规划
This commit is contained in:
shen
2026-05-31 23:56:54 +08:00
parent 44202357c0
commit 1efb9d172f
268 changed files with 4991 additions and 44 deletions
@@ -7,14 +7,41 @@
objects = {
/* Begin PBXBuildFile section */
23BB1155EA379786DAA10A89 /* DisplayTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB49AFCCBC2BE04C82B8F286 /* DisplayTypeTests.swift */; };
3BC5C96D7A0ACF35F2192CC7 /* XCUIApplication+Launch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4C44287820D68ED6570F8 /* XCUIApplication+Launch.swift */; };
4509ED928F228F43888E063D /* ReaderToolbarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADF0A18AD034B74A482A4C1 /* ReaderToolbarTests.swift */; };
52A6A0C9941A4B5F9B88C6B0 /* ReaderAnnotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20BD15E5D8F04E7E9A239E14 /* ReaderAnnotationTests.swift */; };
63B2852E59996922386A3111 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00F495E17B90CCF1C7FE8C27 /* AccessibilityIdentifiers.swift */; };
9AAFB855EC7AC09D1E0B6742 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 697A5BCF0D93DBEC18E21A09 /* Foundation.framework */; };
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 */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
053B5CD55E42BCD8E4E77C14 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DE070C152FBF0CC900ED065F /* Project object */;
proxyType = 1;
remoteGlobalIDString = DE070C1C2FBF0CC900ED065F;
remoteInfo = ReadViewDemo;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
00F495E17B90CCF1C7FE8C27 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.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>"; };
423988C9F7F09A1B78D97CC1 /* Pods-ReadViewDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReadViewDemo.debug.xcconfig"; path = "Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo.debug.xcconfig"; sourceTree = "<group>"; };
697A5BCF0D93DBEC18E21A09 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
74B4C44287820D68ED6570F8 /* XCUIApplication+Launch.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "XCUIApplication+Launch.swift"; sourceTree = "<group>"; };
792DF85CE4A3DD80D67843C7 /* Pods_ReadViewDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReadViewDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8FFD606A5A1CBDCC3CA87F1C /* ReadViewDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReadViewDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9EDF066BA12974E6CFBE519F /* ReaderOpenCloseTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ReaderOpenCloseTests.swift; sourceTree = "<group>"; };
BADF0A18AD034B74A482A4C1 /* ReaderToolbarTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ReaderToolbarTests.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>"; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
@@ -39,6 +66,14 @@
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
3B8BD3932B95613EF7F4A449 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9AAFB855EC7AC09D1E0B6742 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DE070C1A2FBF0CC900ED065F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -50,10 +85,28 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0F03902FB2E1DBD16B6E862F /* iOS */ = {
isa = PBXGroup;
children = (
697A5BCF0D93DBEC18E21A09 /* Foundation.framework */,
);
name = iOS;
sourceTree = "<group>";
};
5354236B404004825520D52F /* Helpers */ = {
isa = PBXGroup;
children = (
00F495E17B90CCF1C7FE8C27 /* AccessibilityIdentifiers.swift */,
74B4C44287820D68ED6570F8 /* XCUIApplication+Launch.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
9F8446930C35441C7E9A4DFF /* Frameworks */ = {
isa = PBXGroup;
children = (
792DF85CE4A3DD80D67843C7 /* Pods_ReadViewDemo.framework */,
0F03902FB2E1DBD16B6E862F /* iOS */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -74,6 +127,7 @@
DE070C1E2FBF0CC900ED065F /* Products */,
BAF21F51585EC06F8713C5C6 /* Pods */,
9F8446930C35441C7E9A4DFF /* Frameworks */,
E31A99F5F070435147BC13CC /* ReadViewDemoUITests */,
);
sourceTree = "<group>";
};
@@ -81,13 +135,53 @@
isa = PBXGroup;
children = (
DE070C1D2FBF0CC900ED065F /* ReadViewDemo.app */,
8FFD606A5A1CBDCC3CA87F1C /* ReadViewDemoUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
E31A99F5F070435147BC13CC /* ReadViewDemoUITests */ = {
isa = PBXGroup;
children = (
5354236B404004825520D52F /* Helpers */,
EACA0D274176D594361EF6B9 /* ReaderUITests */,
);
path = ReadViewDemoUITests;
sourceTree = "<group>";
};
EACA0D274176D594361EF6B9 /* ReaderUITests */ = {
isa = PBXGroup;
children = (
FB49AFCCBC2BE04C82B8F286 /* DisplayTypeTests.swift */,
20BD15E5D8F04E7E9A239E14 /* ReaderAnnotationTests.swift */,
9EDF066BA12974E6CFBE519F /* ReaderOpenCloseTests.swift */,
BADF0A18AD034B74A482A4C1 /* ReaderToolbarTests.swift */,
201C2B482287866487EFAE66 /* SettingsPanelTests.swift */,
);
path = ReaderUITests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
7BE8E325ADE250D48D1A997A /* ReadViewDemoUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = ADC5920FDF58B08AA59F7567 /* Build configuration list for PBXNativeTarget "ReadViewDemoUITests" */;
buildPhases = (
3033E27A4E50D8AF46B7388D /* Sources */,
3B8BD3932B95613EF7F4A449 /* Frameworks */,
ADEE76F68D081663B23CD0BB /* Resources */,
);
buildRules = (
);
dependencies = (
B0E4ACDE6B79427A20B5BE9A /* PBXTargetDependency */,
);
name = ReadViewDemoUITests;
productName = ReadViewDemoUITests;
productReference = 8FFD606A5A1CBDCC3CA87F1C /* ReadViewDemoUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
DE070C1C2FBF0CC900ED065F /* ReadViewDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = DE070C302FBF0CCA00ED065F /* Build configuration list for PBXNativeTarget "ReadViewDemo" */;
@@ -140,11 +234,19 @@
projectRoot = "";
targets = (
DE070C1C2FBF0CC900ED065F /* ReadViewDemo */,
7BE8E325ADE250D48D1A997A /* ReadViewDemoUITests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
ADEE76F68D081663B23CD0BB /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
DE070C1B2FBF0CC900ED065F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -185,10 +287,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReadViewDemo/Pods-ReadViewDemo-frameworks.sh\"\n";
@@ -197,6 +303,20 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3033E27A4E50D8AF46B7388D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63B2852E59996922386A3111 /* AccessibilityIdentifiers.swift in Sources */,
3BC5C96D7A0ACF35F2192CC7 /* XCUIApplication+Launch.swift in Sources */,
23BB1155EA379786DAA10A89 /* DisplayTypeTests.swift in Sources */,
52A6A0C9941A4B5F9B88C6B0 /* ReaderAnnotationTests.swift in Sources */,
C08FF8D030048DC5147729E9 /* ReaderOpenCloseTests.swift in Sources */,
4509ED928F228F43888E063D /* ReaderToolbarTests.swift in Sources */,
FEDB5937CEB858CB06E38E2D /* SettingsPanelTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DE070C192FBF0CC900ED065F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -206,7 +326,63 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
B0E4ACDE6B79427A20B5BE9A /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = ReadViewDemo;
target = DE070C1C2FBF0CC900ED065F /* ReadViewDemo */;
targetProxy = 053B5CD55E42BCD8E4E77C14 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
258209CBC2293BAD3EF2B836 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = NO;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = MG4Z7FU83W;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
PRODUCT_BUNDLE_IDENTIFIER = cn.shen.ReadViewDemoUITests;
PRODUCT_MODULE_NAME = ReadViewDemoUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = TouchLinked_dev;
SDKROOT = iphoneos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = ReadViewDemo;
VALIDATE_PRODUCT = YES;
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
2995C92FBA100970A8A427B4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = NO;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = MG4Z7FU83W;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
PRODUCT_BUNDLE_IDENTIFIER = cn.shen.ReadViewDemoUITests;
PRODUCT_MODULE_NAME = ReadViewDemoUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = TouchLinked_dev;
SDKROOT = iphoneos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = ReadViewDemo;
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
DE070C312FBF0CCA00ED065F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 423988C9F7F09A1B78D97CC1 /* Pods-ReadViewDemo.debug.xcconfig */;
@@ -407,6 +583,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
ADC5920FDF58B08AA59F7567 /* Build configuration list for PBXNativeTarget "ReadViewDemoUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
258209CBC2293BAD3EF2B836 /* Release */,
2995C92FBA100970A8A427B4 /* Debug */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DE070C182FBF0CC900ED065F /* Build configuration list for PBXProject "ReadViewDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (