接入桌面壳窗口标题同步
HostBridge 契约新增 app.setTitle 方法和标题 payload Tauri 桌面壳通过主窗口 API 同步非空窗口标题 桌面壳能力清单和配置守卫声明 app.setTitle 补充标题校验测试并更新宿主壳方案和团队共享决策记录
This commit is contained in:
@@ -34,7 +34,7 @@ const requiredUrlParts = [
|
||||
'hostShell=tauri_desktop',
|
||||
'hostPlatform=unknown',
|
||||
'bridgeVersion=1',
|
||||
'hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,clipboard.writeText',
|
||||
'hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,app.setTitle,clipboard.writeText',
|
||||
];
|
||||
|
||||
for (const part of requiredUrlParts) {
|
||||
@@ -55,8 +55,10 @@ const requiredMainSnippets = [
|
||||
'tauri_plugin_clipboard_manager::init()',
|
||||
'"share.open"',
|
||||
'"share.setTarget"',
|
||||
'"app.setTitle"',
|
||||
'"clipboard.writeText"',
|
||||
'"copied_to_clipboard"',
|
||||
'set_title',
|
||||
];
|
||||
|
||||
for (const permission of requiredPermissions) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use std::sync::Mutex;
|
||||
use tauri::Manager;
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
use tauri_plugin_opener::OpenerExt;
|
||||
|
||||
@@ -71,6 +72,7 @@ fn capabilities() -> Vec<&'static str> {
|
||||
"share.open",
|
||||
"share.setTarget",
|
||||
"app.openExternalUrl",
|
||||
"app.setTitle",
|
||||
"clipboard.writeText",
|
||||
]
|
||||
}
|
||||
@@ -157,6 +159,15 @@ fn normalize_external_url(raw_url: &str) -> Option<String> {
|
||||
Some(url.to_string())
|
||||
}
|
||||
|
||||
fn normalize_window_title(raw_title: &str) -> Option<String> {
|
||||
let title = raw_title.trim();
|
||||
if title.is_empty() || title.chars().any(char::is_control) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(title.chars().take(80).collect())
|
||||
}
|
||||
|
||||
fn payload_string<'a>(value: &'a Value, field: &str) -> Option<&'a str> {
|
||||
value
|
||||
.get(field)
|
||||
@@ -296,6 +307,23 @@ fn host_bridge_request(
|
||||
Err(error) => failed(request.id, "host_error", error.to_string()),
|
||||
}
|
||||
}
|
||||
"app.setTitle" => {
|
||||
let title = match required_string_payload(&request, "title")
|
||||
.ok()
|
||||
.and_then(normalize_window_title)
|
||||
{
|
||||
Some(title) => title,
|
||||
None => return failed(request.id, "invalid_request", "title is required"),
|
||||
};
|
||||
|
||||
match app.get_webview_window("main") {
|
||||
Some(window) => match window.set_title(&title) {
|
||||
Ok(()) => ok(request.id, json!(true)),
|
||||
Err(error) => failed(request.id, "host_error", error.to_string()),
|
||||
},
|
||||
None => failed(request.id, "host_error", "main window not found"),
|
||||
}
|
||||
}
|
||||
"share.setTarget" => {
|
||||
let target = request
|
||||
.payload
|
||||
@@ -381,6 +409,10 @@ mod tests {
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.contains(&json!("share.setTarget")));
|
||||
assert!(result["capabilities"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.contains(&json!("app.setTitle")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -433,6 +465,25 @@ mod tests {
|
||||
assert_eq!(normalize_external_url("/relative/path"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn window_title_normalization_requires_visible_text() {
|
||||
assert_eq!(
|
||||
normalize_window_title(" Genarrative "),
|
||||
Some("Genarrative".to_string())
|
||||
);
|
||||
assert_eq!(normalize_window_title(""), None);
|
||||
assert_eq!(normalize_window_title("Genarrative\nDev"), None);
|
||||
|
||||
let long_title = "甲".repeat(120);
|
||||
assert_eq!(
|
||||
normalize_window_title(&long_title)
|
||||
.expect("truncated title")
|
||||
.chars()
|
||||
.count(),
|
||||
80
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn share_text_uses_direct_share_payload() {
|
||||
let state = DesktopShareState::default();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"build": {
|
||||
"beforeDevCommand": "npm --prefix ../.. run dev:web",
|
||||
"beforeBuildCommand": "npm --prefix ../.. run build:raw && npm run typecheck",
|
||||
"devUrl": "http://127.0.0.1:3000/?clientRuntime=native_app&clientType=native_app&hostShell=tauri_desktop&hostPlatform=unknown&hostVersion=0.1.0&bridgeVersion=1&hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,clipboard.writeText",
|
||||
"devUrl": "http://127.0.0.1:3000/?clientRuntime=native_app&clientType=native_app&hostShell=tauri_desktop&hostPlatform=unknown&hostVersion=0.1.0&bridgeVersion=1&hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,app.setTitle,clipboard.writeText",
|
||||
"frontendDist": "../../../dist"
|
||||
},
|
||||
"app": {
|
||||
@@ -14,7 +14,7 @@
|
||||
{
|
||||
"create": false,
|
||||
"label": "main",
|
||||
"url": "index.html?clientRuntime=native_app&clientType=native_app&hostShell=tauri_desktop&hostPlatform=unknown&hostVersion=0.1.0&bridgeVersion=1&hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,clipboard.writeText",
|
||||
"url": "index.html?clientRuntime=native_app&clientType=native_app&hostShell=tauri_desktop&hostPlatform=unknown&hostVersion=0.1.0&bridgeVersion=1&hostCapabilities=host.getRuntime,share.open,share.setTarget,app.openExternalUrl,app.setTitle,clipboard.writeText",
|
||||
"title": "Genarrative",
|
||||
"width": 1280,
|
||||
"height": 820,
|
||||
|
||||
Reference in New Issue
Block a user