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

新增 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

View File

@@ -13,6 +13,7 @@ import {
} from 'react-native';
import {
type ClipboardReadTextResult,
type ClipboardWriteTextPayload,
type FileExportImagePayload,
type FileExportImageResult,
@@ -30,6 +31,7 @@ import {
type HostBridgeResponse,
type NavigateNativePagePayload,
normalizeHostBridgeBadgeCount,
normalizeHostBridgeClipboardText,
normalizeHostBridgeColorScheme,
normalizeHostBridgeExportFileName,
normalizeHostBridgeExternalUrl,
@@ -74,6 +76,7 @@ export const MOBILE_HOST_CAPABILITIES: HostBridgeCapability[] = [
'network.status',
'network.statusChanged',
'clipboard.writeText',
'clipboard.readText',
'file.exportText',
'file.exportImage',
'file.importImage',
@@ -229,6 +232,20 @@ async function writeClipboard(payload: unknown) {
return true;
}
async function readClipboard(): Promise<ClipboardReadTextResult> {
const result = normalizeHostBridgeClipboardText(
await Clipboard.getStringAsync(),
);
if (!result) {
throw {
code: 'host_error',
message: 'clipboard text unavailable',
} satisfies HostBridgeError;
}
return result;
}
async function exportTextFile(payload: unknown): Promise<FileExportTextResult> {
const exportPayload = payload as FileExportTextPayload | undefined;
const content = exportPayload?.content;
@@ -606,6 +623,8 @@ async function handleRequest(request: HostBridgeRequest) {
return ok(request, await getMobileNetworkStatus());
case 'clipboard.writeText':
return ok(request, await writeClipboard(request.payload));
case 'clipboard.readText':
return ok(request, await readClipboard());
case 'file.exportText':
return ok(request, await exportTextFile(request.payload));
case 'file.exportImage':