接入移动壳返回栈事件
移动壳声明 host.events 和 navigation.canGoBack 能力 Expo WebView 导航状态变化时向 H5 注入返回栈事件 H5 native_app transport 支持订阅 HostBridge 事件 补充事件订阅测试、移动壳能力测试和配置守卫 更新宿主壳方案和团队共享决策记录
This commit is contained in:
@@ -16,6 +16,12 @@ import { buildMobileShellUrl } from './src/mobileShellUrl';
|
||||
const defaultWebUrl = 'http://127.0.0.1:3000/';
|
||||
const hostVersion = '0.1.0';
|
||||
|
||||
function buildHostBridgeMessageScript(message: unknown) {
|
||||
return `window.dispatchEvent(new MessageEvent('message', { data: ${JSON.stringify(
|
||||
JSON.stringify(message),
|
||||
)} })); true;`;
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const webViewRef = useRef<WebView>(null);
|
||||
const [canGoBack, setCanGoBack] = useState(false);
|
||||
@@ -91,9 +97,7 @@ export default function App() {
|
||||
const handleMessage = (event: WebViewMessageEvent) => {
|
||||
void handleMobileHostBridgeMessage(event.nativeEvent.data, (response) => {
|
||||
webViewRef.current?.injectJavaScript(
|
||||
`window.dispatchEvent(new MessageEvent('message', { data: ${JSON.stringify(
|
||||
JSON.stringify(response),
|
||||
)} })); true;`,
|
||||
buildHostBridgeMessageScript(response),
|
||||
);
|
||||
});
|
||||
};
|
||||
@@ -118,7 +122,19 @@ export default function App() {
|
||||
originWhitelist={[allowedWebOrigin]}
|
||||
onMessage={handleMessage}
|
||||
onShouldStartLoadWithRequest={handleShouldStartLoad}
|
||||
onNavigationStateChange={(event) => setCanGoBack(event.canGoBack)}
|
||||
onNavigationStateChange={(event) => {
|
||||
setCanGoBack(event.canGoBack);
|
||||
webViewRef.current?.injectJavaScript(
|
||||
buildHostBridgeMessageScript({
|
||||
bridge: 'GenarrativeHostBridge',
|
||||
version: 1,
|
||||
event: 'navigation.canGoBack',
|
||||
payload: {
|
||||
canGoBack: event.canGoBack,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}}
|
||||
setSupportMultipleWindows={false}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -41,6 +41,8 @@ for (const snippet of [
|
||||
"Linking.addEventListener('url'",
|
||||
'buildMobileShellUrlFromDeepLink',
|
||||
'configureMobileHostBridgeNavigation',
|
||||
'navigation.canGoBack',
|
||||
'buildHostBridgeMessageScript',
|
||||
]) {
|
||||
if (!appSource.includes(snippet)) {
|
||||
throw new Error(`mobile shell App missing ${snippet}`);
|
||||
|
||||
@@ -101,6 +101,11 @@ describe('handleMobileHostBridgeMessage', () => {
|
||||
expect(
|
||||
(okResponse.result as { capabilities: string[] }).capabilities,
|
||||
).toContain('navigation.openNativePage');
|
||||
expect(
|
||||
(okResponse.result as { capabilities: string[] }).capabilities,
|
||||
).toEqual(
|
||||
expect.arrayContaining(['host.events', 'navigation.canGoBack']),
|
||||
);
|
||||
});
|
||||
|
||||
test('navigation.openNativePage 把同源路径切到移动壳 WebView', async () => {
|
||||
|
||||
@@ -22,9 +22,11 @@ import { resolveMobileShellWebViewUrl } from './mobileShellNavigation';
|
||||
|
||||
export const MOBILE_HOST_CAPABILITIES: HostBridgeCapability[] = [
|
||||
'host.getRuntime',
|
||||
'host.events',
|
||||
'share.open',
|
||||
'share.setTarget',
|
||||
'navigation.openNativePage',
|
||||
'navigation.canGoBack',
|
||||
'app.openExternalUrl',
|
||||
'clipboard.writeText',
|
||||
'haptics.impact',
|
||||
|
||||
Reference in New Issue
Block a user