Skip to main content

Vine/Server/Notification/
WebviewLifecycle.rs

1//! Cocoon → `webview.setTitle` / `webview.setIconPath` / `webview.setHtml` /
2//! `webview.postMessage` / `webview.updateView` / `webview.viewState` /
3//! `webview.dispose` notifications.
4//!
5//! Wire-shape canonicalisation: SkyBridge listeners read named keys
6//! (`Payload.viewId`, `Payload.html`, `Payload.message`). Cocoon's legacy
7//! positional `[Handle, Value]` arrays are projected to named aliases here so
8//! every producer shape lands on the same Sky channel. Mirrors the reshape
9//! `Track/Effect/CreateEffectForRequest/Webview.rs` applies on the request
10//! path.
11//!
12//! Suffix mapping: `setHtml` → `set-html` (kebab) to match the typed-RPC
13//! channel; other suffixes pass through camelCase.
14
15use serde_json::{Map, Value, json};
16
17use crate::{Host::VineHost, dev_log};
18
19pub async fn WebviewLifecycle(Host:&dyn VineHost, MethodName:&str, Parameter:&Value) {
20	let RawSuffix = &MethodName["webview.".len()..];
21
22	let Suffix = match RawSuffix {
23		"setHtml" => "set-html",
24
25		"postMessage" => "postMessage",
26
27		Other => Other,
28	};
29
30	let EventName = format!("sky://webview/{}", Suffix);
31
32	// Canonicalise positional [Handle, Value] arrays to named-key objects.
33	let CanonicalPayload:Value = if Parameter.is_object() {
34		Parameter.clone()
35	} else if let Some(First) = Parameter.get(0) {
36		if First.is_object() {
37			First.clone()
38		} else {
39			let mut Object = Map::new();
40
41			Object.insert("method".to_string(), Value::String(MethodName.to_string()));
42
43			Object.insert("handle".to_string(), First.clone());
44
45			Object.insert("args".to_string(), Parameter.clone());
46
47			if let Some(Second) = Parameter.get(1) {
48				let Alias = match MethodName {
49					"webview.setHtml" => "html",
50
51					"webview.postMessage" => "message",
52
53					"webview.registerView" | "webview.unregisterView" => "viewId",
54
55					"webview.registerCustomEditor" | "webview.unregisterCustomEditor" | "webview.create" => "viewType",
56
57					_ => "value",
58				};
59
60				Object.insert(Alias.to_string(), Second.clone());
61
62				if MethodName == "webview.create" {
63					if let Some(Third) = Parameter.get(2) {
64						Object.insert("title".to_string(), Third.clone());
65					}
66				}
67			}
68
69			Value::Object(Object)
70		}
71	} else {
72		json!({ "method": MethodName, "handle": Parameter.clone() })
73	};
74
75	dev_log!(
76		"grpc",
77		"[WebviewLifecycle] emit {} handle={:?}",
78		EventName,
79		CanonicalPayload.get("handle")
80	);
81
82	Host.EmitToRenderer(&EventName, CanonicalPayload);
83}