接入原生壳剪贴板读取能力

新增 clipboard.readText HostBridge 契约和 H5 facade

移动端通过 expo-clipboard 读取纯文本剪贴板

桌面端通过 Tauri clipboard-manager 读取纯文本剪贴板

更新壳能力检查、测试、方案文档和共享决策记录
This commit is contained in:
2026-06-18 04:38:16 +08:00
parent bbfe4b7181
commit c7a24fba37
13 changed files with 158 additions and 4 deletions
@@ -20,6 +20,7 @@ import {
openHostShareGrid,
openWechatMiniProgramShareGridPage,
postWechatMiniProgramMessage,
readHostClipboardText,
refreshNativeAppHostRuntime,
requestHostHapticsImpact,
requestHostLogin,
@@ -594,6 +595,10 @@ describe('hostBridge', () => {
connectionType: 'ethernet',
nativeType: 'online',
}
: request.method === 'clipboard.readText'
? {
text: '作品号 PZ-1',
}
: request.method === 'file.importImage'
? {
action: 'selected',
@@ -614,6 +619,7 @@ describe('hostBridge', () => {
'navigation.openNativePage',
'auth.requestLogin',
'payment.request',
'clipboard.readText',
'clipboard.writeText',
'haptics.impact',
'app.openExternalUrl',
@@ -651,6 +657,9 @@ describe('hostBridge', () => {
await expect(
writeHostClipboardText({ text: '作品号 PZ-1' }),
).resolves.toBe(true);
await expect(readHostClipboardText()).resolves.toEqual({
text: '作品号 PZ-1',
});
await expect(requestHostHapticsImpact({ style: 'medium' })).resolves.toBe(
true,
);
@@ -728,6 +737,11 @@ describe('hostBridge', () => {
},
}),
});
expect(invoke).toHaveBeenCalledWith('host_bridge_request', {
request: expect.objectContaining({
method: 'clipboard.readText',
}),
});
expect(invoke).toHaveBeenCalledWith('host_bridge_request', {
request: expect.objectContaining({
method: 'haptics.impact',
@@ -835,6 +849,7 @@ describe('hostBridge', () => {
await expect(
writeHostClipboardText({ text: '作品号 PZ-1' }),
).resolves.toBe(false);
await expect(readHostClipboardText()).resolves.toBe(false);
await expect(requestHostHapticsImpact({ style: 'light' })).resolves.toBe(
false,
);
@@ -876,6 +891,7 @@ describe('hostBridge', () => {
test('普通浏览器不处理宿主文件导出', async () => {
await expect(getHostAppearanceColorScheme()).resolves.toBe(false);
await expect(readHostClipboardText()).resolves.toBe(false);
await expect(
exportHostTextFile({
fileName: '作品记录.txt',
+22
View File
@@ -1,6 +1,7 @@
import type {
AppearanceColorSchemeResult,
AppLifecycleEventPayload,
ClipboardReadTextResult,
FileExportImagePayload,
FileExportImageResult,
FileExportTextPayload,
@@ -20,6 +21,7 @@ import type {
import {
isHostBridgeCapability,
normalizeHostBridgeBadgeCount,
normalizeHostBridgeClipboardText,
normalizeHostBridgeColorScheme,
normalizeHostBridgeConnectionType,
normalizeHostBridgeExternalUrl,
@@ -96,6 +98,8 @@ export type HostClipboardWriteTextRequest = {
text: string;
};
export type HostClipboardReadTextResult = ClipboardReadTextResult;
export type HostHapticsImpactRequest = HapticsImpactPayload;
export type HostLocalNotificationRequest = LocalNotificationPayload;
@@ -698,6 +702,24 @@ export async function writeHostClipboardText({
}
}
export async function readHostClipboardText() {
if (!canUseNativeHostCapability('clipboard.readText')) {
return false;
}
try {
return normalizeHostBridgeClipboardText(
(
await requestNativeAppHostBridge<ClipboardReadTextResult>(
'clipboard.readText',
)
)?.text,
);
} catch {
return false;
}
}
export async function exportHostTextFile(
params: HostFileExportTextRequest,
) {