收口移动剪贴板边界
将 Expo 剪贴板读写收口到 clipboard 模块 让 HostBridge dispatch 只负责剪贴板 payload 分发 同步原生壳结构门禁和架构文档清单
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import * as Clipboard from 'expo-clipboard';
|
||||
|
||||
import {
|
||||
type ClipboardReadTextResult,
|
||||
type HostBridgeError,
|
||||
normalizeHostBridgeClipboardText,
|
||||
} from '../../../../packages/shared/src/contracts/hostBridge';
|
||||
|
||||
export async function writeMobileClipboardText(rawText: unknown) {
|
||||
const clipboardText = normalizeHostBridgeClipboardText(rawText);
|
||||
if (!clipboardText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await Clipboard.setStringAsync(clipboardText.text);
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function readMobileClipboardText(): Promise<ClipboardReadTextResult> {
|
||||
const result = normalizeHostBridgeClipboardText(
|
||||
await Clipboard.getStringAsync(),
|
||||
);
|
||||
if (!result) {
|
||||
throw {
|
||||
code: 'host_error',
|
||||
message: 'clipboard text unavailable',
|
||||
} satisfies HostBridgeError;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as Clipboard from 'expo-clipboard';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
import * as Linking from 'expo-linking';
|
||||
import {
|
||||
@@ -8,7 +7,6 @@ import {
|
||||
} from 'react-native';
|
||||
|
||||
import {
|
||||
type ClipboardReadTextResult,
|
||||
type ClipboardWriteTextPayload,
|
||||
type HapticsImpactPayload,
|
||||
HOST_BRIDGE_BADGE_COUNT_MAX,
|
||||
@@ -17,7 +15,6 @@ import {
|
||||
type HostBridgeRequest,
|
||||
type NavigateNativePagePayload,
|
||||
normalizeHostBridgeBadgeCount,
|
||||
normalizeHostBridgeClipboardText,
|
||||
normalizeHostBridgeColorScheme,
|
||||
normalizeHostBridgeExternalUrlPayload,
|
||||
normalizeHostBridgeHapticsImpactStyle,
|
||||
@@ -53,6 +50,10 @@ import { resetQrScannerForTest, scanQrCode } from './scanner';
|
||||
import { openShare } from './share';
|
||||
import { buildMobileShellUrl } from '../shell/url';
|
||||
import { showMobileLocalNotification } from './notifications';
|
||||
import {
|
||||
readMobileClipboardText,
|
||||
writeMobileClipboardText,
|
||||
} from './clipboard';
|
||||
|
||||
let currentShareTarget: unknown = null;
|
||||
let navigation: MobileHostBridgeNavigation | null = null;
|
||||
@@ -82,31 +83,17 @@ async function openExternalUrl(payload: unknown) {
|
||||
}
|
||||
|
||||
async function writeClipboard(payload: unknown) {
|
||||
const clipboardText = normalizeHostBridgeClipboardText(
|
||||
(payload as ClipboardWriteTextPayload | undefined)?.text,
|
||||
);
|
||||
if (!clipboardText) {
|
||||
if (
|
||||
!(await writeMobileClipboardText(
|
||||
(payload as ClipboardWriteTextPayload | undefined)?.text,
|
||||
))
|
||||
) {
|
||||
throw invalidRequest('text is required');
|
||||
}
|
||||
|
||||
await Clipboard.setStringAsync(clipboardText.text);
|
||||
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 runHaptics(payload: unknown) {
|
||||
const style = normalizeHostBridgeHapticsImpactStyle(
|
||||
(payload as HapticsImpactPayload | undefined)?.style,
|
||||
@@ -227,7 +214,7 @@ export async function dispatchMobileHostBridgeRequest(
|
||||
case 'clipboard.writeText':
|
||||
return ok(request, await writeClipboard(request.payload));
|
||||
case 'clipboard.readText':
|
||||
return ok(request, await readClipboard());
|
||||
return ok(request, await readMobileClipboardText());
|
||||
case 'file.exportText':
|
||||
return ok(request, await exportTextFile(request.payload));
|
||||
case 'file.importText':
|
||||
|
||||
Reference in New Issue
Block a user