Mountain/Environment/
CustomEditorProvider.rs

1// File: Mountain/Source/Environment/CustomEditorProvider.rs
2// Role: Implements the `CustomEditorProvider` trait for the
3// `MountainEnvironment`. Responsibilities:
4//   - Manage the registration and state of custom editor providers.
5//   - Mediate the "resolve" process, calling back to the extension host to get
6//     the content for a custom editor instance.
7
8//! # CustomEditorProvider Implementation
9//!
10//! Implements the `CustomEditorProvider` trait for the `MountainEnvironment`.
11//! This provider orchestrates the lifecycle of custom, non-text editors that
12//! are contributed by extensions.
13
14#![allow(non_snake_case, non_camel_case_types)]
15
16use std::sync::Arc;
17
18use Common::{
19	CustomEditor::CustomEditorProvider::CustomEditorProvider,
20	Environment::Requires::Requires,
21	Error::CommonError::CommonError,
22	IPC::{DTO::ProxyTarget::ProxyTarget, IPCProvider::IPCProvider},
23};
24use async_trait::async_trait;
25use log::{info, warn};
26use serde_json::{Value, json};
27use url::Url;
28
29use super::MountainEnvironment::MountainEnvironment;
30
31#[async_trait]
32impl CustomEditorProvider for MountainEnvironment {
33	async fn RegisterCustomEditorProvider(&self, _ViewType:String, _OptionsValue:Value) -> Result<(), CommonError> {
34		info!("[CustomEditorProvider] Registering provider for view type: {}", _ViewType);
35		// In a full implementation, this would store provider details, such as
36		// its capabilities and the sidecar it belongs to, in ApplicationState.
37		// For now, we assume all providers are in the main sidecar.
38		Ok(())
39	}
40
41	async fn UnregisterCustomEditorProvider(&self, _ViewType:String) -> Result<(), CommonError> {
42		info!("[CustomEditorProvider] Unregistering provider for view type: {}", _ViewType);
43		// This would remove the provider's registration from ApplicationState.
44		Ok(())
45	}
46
47	async fn OnSaveCustomDocument(&self, _ViewType:String, _ResourceURI:Url) -> Result<(), CommonError> {
48		warn!("[CustomEditorProvider] OnSaveCustomDocument is not fully implemented.");
49		// This would typically trigger a call to the extension host to perform the
50		// save, which would then read data from the webview and write it to the file.
51		Ok(())
52	}
53
54	async fn ResolveCustomEditor(
55		&self,
56		ViewType:String,
57		ResourceURI:Url,
58		WebViewPanelHandle:String,
59	) -> Result<(), CommonError> {
60		info!(
61			"[CustomEditorProvider] Resolving custom editor for '{}' on resource '{}'",
62			ViewType, ResourceURI
63		);
64
65		// This is the core logic:
66		// 1. Find the sidecar that registered this ViewType. For now, assume
67		//    "cocoon-main".
68		// 2. Make an RPC call to that sidecar's implementation of
69		//    `$resolveCustomEditor`.
70		// 3. The sidecar will then call back to the host with `setHtml`, `postMessage`,
71		//    etc. to populate the webview associated with the `WebViewPanelHandle`.
72
73		let IPCProvider:Arc<dyn IPCProvider> = self.Require();
74		let ResourceURIComponents = json!({ "external": ResourceURI.to_string() });
75		let RPCMethod = format!("{}$resolveCustomEditor", ProxyTarget::ExtHostCustomEditors.GetTargetPrefix());
76		let RPCParameters = json!([ResourceURIComponents, ViewType, WebViewPanelHandle]);
77
78		// This is a fire-and-forget notification. The sidecar is expected to
79		// call back to the host to populate the webview.
80		IPCProvider
81			.SendNotificationToSideCar("cocoon-main".to_string(), RPCMethod, RPCParameters)
82			.await
83	}
84}