Skip to main content

Mountain/IPC/WindServiceHandlers/TreeView/
GetChildren.rs

1#![allow(unused_variables, dead_code, unused_imports)]
2
3//! Wire method: `tree:getChildren`.
4//! Renderer-side tree-view child lookup. Mirrors the Cocoon→Mountain
5//! `GetTreeChildren` gRPC path but is invoked directly by the Wind/Sky
6//! tree-view bridge so the UI can request children without waiting for
7//! Cocoon to ask first.
8//!
9//! Waits up to 5 s for the Cocoon gRPC connection (boot-race guard) then
10//! dispatches `$provideTreeChildren` with a 5 s timeout. On timeout or
11//! extension rejection the workbench receives `{ items: [] }` and schedules
12//! its own retry when the view scrolls back into view.
13
14use std::sync::Arc;
15
16use serde_json::{Value, json};
17use tauri::AppHandle;
18
19use crate::RunTime::ApplicationRunTime::ApplicationRunTime;
20
21pub async fn Fn(
22	ApplicationHandle:AppHandle,
23
24	RunTime:Arc<ApplicationRunTime>,
25
26	Arguments:Vec<Value>,
27) -> Result<Value, String> {
28	let ViewId = Arguments
29		.first()
30		.and_then(|V| V.get("viewId").or_else(|| V.get(0)))
31		.and_then(Value::as_str)
32		.unwrap_or("")
33		.to_string();
34
35	let ItemHandle = Arguments
36		.first()
37		.and_then(|V| V.get("treeItemHandle").or_else(|| V.get(1)))
38		.and_then(Value::as_str)
39		.unwrap_or("")
40		.to_string();
41
42	crate::dev_log!(
43		"tree-view",
44		"[TreeView] invoke:getChildren view={} parent={}",
45		ViewId,
46		ItemHandle
47	);
48
49	if ViewId.is_empty() {
50		return Err("tree:getChildren requires viewId".to_string());
51	}
52
53	let Parameters = json!({
54		"viewId": ViewId,
55		"treeItemHandle": ItemHandle,
56	});
57
58	// Boot-race: the workbench's Explorer view fires `tree:getChildren` ~700
59	// log lines before Cocoon's gRPC client finishes handshaking. Without
60	// this wait the first call returns `ClientNotConnected`, the workbench
61	// caches an empty list, and the Explorer never recovers without a manual
62	// refresh. 5000 ms chosen from boot-trace observation.
63	let _ = crate::Vine::Client::WaitForClientConnection::Fn("cocoon-main", 5000).await;
64
65	match crate::Vine::Client::SendRequest::Fn(
66		"cocoon-main",
67		"$provideTreeChildren".to_string(),
68		Parameters,
69		// 5000 ms: real cold-boot tree calls take 700-2200 ms
70		// ([DEV:TREE-LATENCY] clangd.ast=2181, gitlens=1652, npm=1560).
71		5000,
72	)
73	.await
74	{
75		Ok(Value_) => {
76			match &Value_ {
77				Value::Object(_) | Value::Array(_) => Ok(Value_),
78
79				// Non-conforming shape: force to {items:[]} so the renderer
80				// always has iterable data and avoids TypeError crashes.
81				_ => Ok(json!({ "items": [] })),
82			}
83		},
84
85		Err(Error) => {
86			// Log first failure per view; silence repeats so the dev log
87			// doesn't fill with identical lines while the user browses
88			// nodes from a misbehaving extension.
89			crate::IPC::DevLog::DebugOnce::Fn(
90				"tree-view",
91				&format!("get-children-error:{}", ViewId),
92				&format!(
93					"[TreeView] invoke:getChildren error view={} err={:?} (further occurrences silenced)",
94					ViewId, Error
95				),
96			);
97
98			Ok(json!({ "items": [] }))
99		},
100	}
101}