Files
Genarrative/apps/mobile-shell/src/host-bridge/navigation.ts
T
kdletters 387a1c26e3 完成全量检查整改
清理已跟踪原始日志与个人本地配置
修复前后端有效门禁、测试和构建问题
补齐生产 Jenkins、SpacetimeDB 本地命令与文档约束
收紧图片编辑器状态、附件与媒体引用测试
排除已下线旧创作入口测试并清理 warning
2026-07-17 16:56:46 +08:00

98 lines
2.4 KiB
TypeScript

import * as Linking from 'expo-linking';
import {
type HostBridgeError,
type HostBridgeRequest,
type NavigateNativePagePayload,
normalizeHostBridgeExternalUrlPayload,
type OpenExternalUrlPayload,
} from '../../../../packages/shared/src/contracts/hostBridge';
import {
openMobileShellExternalNavigation,
resolveMobileShellWebViewUrl,
} from '../shell/navigation';
import { buildMobileShellUrl } from '../shell/url';
import {
invalidRequest,
type MobileHostBridgeNavigation,
ok,
unsupported,
} from './protocol';
function logMobileHostBridgeNavigationFailure(label: string, _error: unknown) {
console.warn(`mobile HostBridge navigation failed for ${label}`);
}
export async function openMobileHostBridgeExternalUrl(
request: HostBridgeRequest,
) {
const externalUrlPayload = normalizeHostBridgeExternalUrlPayload(
(request.payload as OpenExternalUrlPayload | undefined)?.url,
);
if (!externalUrlPayload) {
throw invalidRequest('url must use an allowed external protocol');
}
let opened = false;
try {
opened = await openMobileShellExternalNavigation(
Linking,
externalUrlPayload.url,
);
} catch (error) {
logMobileHostBridgeNavigationFailure('external.open', error);
opened = false;
}
if (!opened) {
throw {
code: 'host_error',
message: 'external URL cannot be opened',
} satisfies HostBridgeError;
}
return ok(request, true);
}
export function openMobileHostBridgeNativePage(
request: HostBridgeRequest,
navigation: MobileHostBridgeNavigation | null,
) {
if (!navigation) {
throw unsupported('navigation.openNativePage');
}
const url = (request.payload as NavigateNativePagePayload | undefined)?.url;
if (typeof url !== 'string') {
throw invalidRequest('url is required');
}
const webViewUrl = resolveMobileShellWebViewUrl(
url,
navigation.allowedOrigin,
);
if (!webViewUrl) {
throw invalidRequest('url must be an allowed same-origin web path');
}
navigation.openWebViewUrl(
buildMobileShellUrl(
webViewUrl,
navigation.urlOptions,
navigation.baseWebUrlOptions,
),
);
return ok(request, true);
}
export function reloadMobileHostBridgeWebView(
request: HostBridgeRequest,
navigation: MobileHostBridgeNavigation | null,
) {
if (!navigation) {
throw unsupported('app.reloadWebView');
}
navigation.reloadWebView();
return ok(request, true);
}