收口桌面壳WebView状态重放
桌面壳页面加载完成后回放生命周期状态 桌面壳页面加载完成后重装网络状态监听 桌面壳配置检查锁定页面状态重放路径 宿主壳方案和共享决策日志记录桌面状态重放约束
This commit is contained in:
@@ -1070,9 +1070,14 @@ const requiredMainSnippets = [
|
||||
'window.theme()',
|
||||
'WindowEvent::Focused',
|
||||
'WindowEvent::DragDrop',
|
||||
'PageLoadEvent',
|
||||
'host_bridge_event_script',
|
||||
'origin: window.location.origin',
|
||||
'source: window',
|
||||
'should_replay_desktop_webview_state_on_page_load',
|
||||
'PageLoadEvent::Finished',
|
||||
'replay_desktop_webview_state',
|
||||
'window.is_focused()',
|
||||
'resolve_desktop_network_status',
|
||||
'network.statusChanged',
|
||||
'file.imageDropped',
|
||||
@@ -1085,6 +1090,7 @@ const requiredMainSnippets = [
|
||||
'open_desktop_external_navigation',
|
||||
'.on_navigation(move |url|',
|
||||
'.on_new_window(move |url, _features|',
|
||||
'.on_page_load(|window, payload|',
|
||||
'DownloadEvent',
|
||||
'should_allow_desktop_webview_download',
|
||||
'DownloadEvent::Requested { .. } => false',
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::time::Duration;
|
||||
use tauri::menu::{Menu, MenuItem};
|
||||
use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent};
|
||||
use tauri::webview::{DownloadEvent, NewWindowResponse};
|
||||
use tauri::webview::{DownloadEvent, NewWindowResponse, PageLoadEvent};
|
||||
use tauri::DragDropEvent;
|
||||
use tauri::Manager;
|
||||
use tauri::Theme;
|
||||
@@ -1153,6 +1153,22 @@ fn register_desktop_network_events(window: &WebviewWindow) -> tauri::Result<()>
|
||||
window.eval(script)
|
||||
}
|
||||
|
||||
fn should_replay_desktop_webview_state_on_page_load(event: PageLoadEvent) -> bool {
|
||||
event == PageLoadEvent::Finished
|
||||
}
|
||||
|
||||
fn replay_desktop_webview_state(window: &WebviewWindow) {
|
||||
let focused = window.is_focused().unwrap_or(true);
|
||||
let (state, native_state) = if focused {
|
||||
("active", "focused")
|
||||
} else {
|
||||
("inactive", "blurred")
|
||||
};
|
||||
|
||||
let _ = emit_desktop_lifecycle_event(window, state, focused, native_state);
|
||||
let _ = register_desktop_network_events(window);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum DesktopTrayAction {
|
||||
ShowMainWindow,
|
||||
@@ -1800,6 +1816,11 @@ fn main() {
|
||||
open_desktop_external_navigation(&new_window_app_handle, &url);
|
||||
NewWindowResponse::Deny
|
||||
})
|
||||
.on_page_load(|window, payload| {
|
||||
if should_replay_desktop_webview_state_on_page_load(payload.event()) {
|
||||
replay_desktop_webview_state(&window);
|
||||
}
|
||||
})
|
||||
.on_download(|_webview, event| should_allow_desktop_webview_download(&event))
|
||||
.build()?;
|
||||
register_desktop_window_close_events(&window, tray_registered);
|
||||
@@ -2111,6 +2132,16 @@ mod tests {
|
||||
assert!(script.contains("\\\"focused\\\":true"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_page_load_replays_state_only_after_finished_load() {
|
||||
assert!(should_replay_desktop_webview_state_on_page_load(
|
||||
PageLoadEvent::Finished
|
||||
));
|
||||
assert!(!should_replay_desktop_webview_state_on_page_load(
|
||||
PageLoadEvent::Started
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn desktop_network_status_payload_reports_reachability() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
- 2026-06-18 原生壳生命周期事件:新增 `app.lifecycle` HostBridge capability,Expo 壳通过 React Native `AppState` 派发 `active` / `inactive` / `background`,Tauri 壳通过主窗口 focus / blur 派发 `active` / `inactive`;H5 只通过 `subscribeHostAppLifecycle()` 订阅统一状态,后续游戏循环、音频和轮询暂停 / 恢复不得直接依赖 Expo / Tauri 平台细节。
|
||||
- 2026-06-18 原生壳网络状态:新增 `network.status` 与 `network.statusChanged` HostBridge capability,Expo 壳通过 `expo-network` 查询和订阅真实系统网络状态,Tauri 壳通过短超时连接 `app.genarrative.world:443` 查询主站可达性,并通过 WebView `online` / `offline` 注入变化事件;H5 统一使用 `getHostNetworkStatus()` / `subscribeHostNetworkStatusChange()`,不得直接读取 Expo / Tauri 私有网络 API。
|
||||
- 2026-06-18 移动壳 WebView 状态重放:Expo WebView 每次同源主站页面成功加载后都会补发当前 `app.lifecycle` 与 `network.statusChanged` 状态,覆盖首载、受控刷新、H5 刷新和系统回收 WebView 进程后的新 JS 上下文;补发不新增 HostBridge capability,也不向 `about:blank`、外域或错误页注入宿主状态。
|
||||
- 2026-06-18 桌面壳 WebView 状态重放:Tauri 主 WebView 每次页面加载完成后都会回放当前 `app.lifecycle` 并重新安装 `network.statusChanged` 监听脚本,覆盖托盘刷新、`app.reloadWebView` 和 H5 自刷新后的新 JS 上下文;回放不新增 HostBridge capability,不开放 Tauri event 插件或额外 command。
|
||||
- 2026-06-18 外部生成队列轮询接入宿主网络状态:H5 新增 `useHostNetworkOnline()`,宿主未声明网络能力时按在线处理以保持浏览器和旧壳行为;宿主明确 `isConnected=false` 或 `isInternetReachable=false` 时,平台外部生成队列概览暂停 HTTP 轮询,恢复在线后重新刷新。该能力只减少离线请求,不改变外部生成队列、作品架、弹窗或后端任务状态事实。
|
||||
- 2026-06-18 桌面图片导入:新增 `file.importImage` 与 `file.imageDropped` HostBridge capability,Tauri 壳通过系统文件选择框和主窗口拖拽事件读取用户选择 / 拖入的真实图片,只允许 `image/png`、`image/jpeg`、`image/webp` 且单次不超过 10 MiB;H5 统一使用 `importHostImageFile()` / `subscribeHostImageDrop()`,宿主只回传文件名、MIME、base64 内容、字节数和可选坐标,不暴露本地绝对路径,也不开放通用文件系统。
|
||||
- 2026-06-18 移动图片导入:Expo 壳开始声明并实现 `file.importImage`,通过 `expo-image-picker` 请求相册权限并打开系统相册选择器,只允许 `image/png`、`image/jpeg`、`image/webp` 且单次不超过 10 MiB;成功只回传清洗后的文件名、MIME、base64 内容和字节数,不暴露设备本地 URI,用户取消返回 `cancelled` 并由 H5 facade 归为 `false`。
|
||||
|
||||
@@ -337,6 +337,8 @@ GameBridge 禁止:
|
||||
|
||||
2026-06-18 追加:H5 账号状态刷新开始消费 `app.reloadWebView`。用户登录成功、退出登录或其它身份边界变化需要整页重新初始化时,`AuthGate` 会优先请求 Tauri 主 WebViewWindow 刷新;宿主未声明或刷新失败时再回退浏览器刷新,Tauri 仍只暴露 `host_bridge_request` 这一受控命令入口。
|
||||
|
||||
2026-06-18 追加:桌面壳 WebView 每次页面加载完成后都会回放当前 `app.lifecycle` 并重新安装 `network.statusChanged` 监听脚本,覆盖托盘刷新、`app.reloadWebView` 和 H5 自刷新后的新 JS 上下文。回放仍只通过 HostBridge event,不开放 Tauri event 插件或额外 command。
|
||||
|
||||
2026-06-18 追加:桌面壳启用 Tauri 真实系统托盘,并复用品牌图标。托盘菜单只提供宿主壳级动作:显示主窗口、刷新主窗口和退出应用;左键点击托盘图标恢复并聚焦主窗口。该能力不进入 HostBridge capability 清单,不向 H5 暴露托盘 API、菜单 API、shell API 或任意窗口控制;如果当前桌面环境无法注册托盘,壳会继续启动主窗口。托盘注册成功时,用户点击主窗口关闭按钮会隐藏到托盘,必须通过托盘“退出”动作结束应用;托盘注册失败时不拦截关闭,避免窗口消失后没有恢复入口。
|
||||
|
||||
2026-06-18 追加:桌面壳启用 Tauri 单实例。用户重复启动桌面 App 时,新实例会退出并唤醒已有主窗口;该回调只执行显示、取消最小化和聚焦主窗口,不把第二实例的命令行参数、工作目录或深链内容作为事件透传给 H5。桌面深链若后续需要接入,必须单独定义受控来源、路径归一和 HostBridge / GameBridge 边界。
|
||||
|
||||
Reference in New Issue
Block a user