接入原生壳外观查询能力

新增 HostBridge appearance.getColorScheme 只读契约和 H5 facade

Expo 壳通过 React Native Appearance 读取系统配色

Tauri 壳通过主窗口 theme 读取桌面配色

补齐外观查询测试、漂移检查和架构文档
This commit is contained in:
2026-06-18 02:00:49 +08:00
parent 6b39bdbe19
commit 45eec17007
13 changed files with 164 additions and 15 deletions
+24 -9
View File
@@ -8,6 +8,7 @@ import {
canUseNativeHostCapability,
exportHostImageFile,
exportHostTextFile,
getHostAppearanceColorScheme,
getHostRuntime,
getNativeAppHostRuntime,
isWechatMiniProgramWebViewRuntime,
@@ -421,15 +422,18 @@ describe('hostBridge', () => {
version: 1,
id: request.id,
ok: true,
result: request.method === 'host.getRuntime'
? {
shell: 'tauri_desktop',
platform: 'linux',
hostVersion: '0.1.0',
bridgeVersion: 1,
capabilities: ['host.getRuntime'],
}
: true,
result:
request.method === 'host.getRuntime'
? {
shell: 'tauri_desktop',
platform: 'linux',
hostVersion: '0.1.0',
bridgeVersion: 1,
capabilities: ['host.getRuntime'],
}
: request.method === 'appearance.getColorScheme'
? { colorScheme: 'dark' }
: true,
};
});
window.history.replaceState(
@@ -437,6 +441,7 @@ describe('hostBridge', () => {
'',
nativeAppPath([
'host.getRuntime',
'appearance.getColorScheme',
'navigation.openNativePage',
'auth.requestLogin',
'payment.request',
@@ -456,6 +461,9 @@ describe('hostBridge', () => {
};
await expect(navigateHostNativePage('/settings')).resolves.toBe(true);
await expect(getHostAppearanceColorScheme()).resolves.toEqual({
colorScheme: 'dark',
});
await expect(requestHostLogin()).resolves.toBe(true);
await expect(
requestHostPayment({
@@ -495,6 +503,11 @@ describe('hostBridge', () => {
}),
).resolves.toBe(true);
expect(invoke).toHaveBeenCalledWith('host_bridge_request', {
request: expect.objectContaining({
method: 'appearance.getColorScheme',
}),
});
expect(invoke).toHaveBeenCalledWith('host_bridge_request', {
request: expect.objectContaining({
method: 'navigation.openNativePage',
@@ -599,6 +612,7 @@ describe('hostBridge', () => {
};
await expect(navigateHostNativePage('/settings')).resolves.toBe(false);
await expect(getHostAppearanceColorScheme()).resolves.toBe(false);
await expect(requestHostLogin()).resolves.toBe(false);
await expect(
requestHostPayment({
@@ -642,6 +656,7 @@ describe('hostBridge', () => {
});
test('普通浏览器不处理宿主文件导出', async () => {
await expect(getHostAppearanceColorScheme()).resolves.toBe(false);
await expect(
exportHostTextFile({
fileName: '作品记录.txt',
+22
View File
@@ -1,4 +1,5 @@
import type {
AppearanceColorSchemeResult,
FileExportImagePayload,
FileExportImageResult,
FileExportTextPayload,
@@ -14,6 +15,7 @@ import type {
import {
isHostBridgeCapability,
normalizeHostBridgeBadgeCount,
normalizeHostBridgeColorScheme,
normalizeHostBridgeExternalUrl,
} from '../../../packages/shared/src/contracts/hostBridge';
import type {
@@ -95,6 +97,8 @@ export type HostShareOpenRequest = ShareOpenPayload;
export type HostExternalUrlRequest = OpenExternalUrlPayload;
export type HostAppearanceColorSchemeSnapshot = AppearanceColorSchemeResult;
const HOST_RUNTIME_REFRESH_TIMEOUT_MS = 3000;
let cachedNativeHostRuntime: HostBridgeRuntimeResult | null = null;
@@ -764,3 +768,21 @@ export async function setHostAppBadgeCount({
return false;
}
}
export async function getHostAppearanceColorScheme() {
if (!canUseNativeHostCapability('appearance.getColorScheme')) {
return false;
}
try {
const result =
await requestNativeAppHostBridge<AppearanceColorSchemeResult>(
'appearance.getColorScheme',
);
return {
colorScheme: normalizeHostBridgeColorScheme(result?.colorScheme),
} satisfies HostAppearanceColorSchemeSnapshot;
} catch {
return false;
}
}