Mountain/Environment/WebviewProvider/
Lifecycle.rs1use CommonLibrary::{
9 Error::CommonError::CommonError,
10 IPC::SkyEvent::SkyEvent,
11 Webview::DTO::WebviewContentOptionsDTO::WebviewContentOptionsDTO,
12};
13use serde_json::{Value, json};
14use tauri::{Emitter, Manager, WebviewWindowBuilder};
15use uuid::Uuid;
16
17use super::super::{MountainEnvironment::MountainEnvironment, Utility};
18use crate::{ApplicationState::DTO::WebviewStateDTO::WebviewStateDTO, dev_log};
19
20pub(super) async fn create_webview_panel_impl(
22 env:&MountainEnvironment,
23
24 extension_data_value:Value,
25
26 view_type:String,
27
28 title:String,
29
30 _show_options_value:Value,
31
32 panel_options_value:Value,
33
34 content_options_value:Value,
35) -> Result<String, CommonError> {
36 let handle = Uuid::new_v4().to_string();
37
38 dev_log!(
39 "extensions",
40 "[WebviewProvider] Creating WebviewPanel with handle: {}, viewType: {}",
41 handle,
42 view_type
43 );
44
45 let content_options:WebviewContentOptionsDTO =
47 serde_json::from_value(content_options_value.clone()).map_err(|error| {
48 CommonError::InvalidArgument { ArgumentName:"ContentOptions".into(), Reason:error.to_string() }
49 })?;
50
51 let state = WebviewStateDTO {
52 Handle:handle.clone(),
53
54 ViewType:view_type.clone(),
55
56 Title:title.clone(),
57
58 ContentOptions:content_options,
59
60 PanelOptions:panel_options_value.clone(),
61
62 SideCarIdentifier:"cocoon-main".to_string(),
63
64 ExtensionIdentifier:extension_data_value
65 .get("id")
66 .and_then(|v| v.as_str())
67 .unwrap_or_default()
68 .to_string(),
69
70 IsActive:true,
71
72 IsVisible:true,
73 };
74
75 {
77 let mut webview_guard = env
78 .ApplicationState
79 .Feature
80 .Webviews
81 .ActiveWebviews
82 .lock()
83 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
84
85 webview_guard.insert(handle.clone(), state);
86 }
87
88 let title_clone = title.clone();
94
95 let WebviewHostUrl = crate::IPC::WindServiceHandlers::Utilities::LocalhostUrl::Get::Fn()
96 .map(|Base| format!("{}/Mountain/WebviewHost", Base))
97 .unwrap_or_else(|| "http://localhost:15536/Mountain/WebviewHost".to_string());
98
99 let WebviewUrlParsed = WebviewHostUrl
100 .parse::<url::Url>()
101 .map(tauri::WebviewUrl::External)
102 .unwrap_or_else(|_| tauri::WebviewUrl::App("WebviewHost.html".into()));
103
104 let _webview_window = WebviewWindowBuilder::new(&env.ApplicationHandle, &handle, WebviewUrlParsed)
105 .title(title)
106 .initialization_script(&format!(
107 "window.__WEBVIEW_INITIAL_STATE__ = {};",
108 json!({
109 "Handle": handle,
110 "ViewType": view_type,
111 "Title": title_clone
112 })
113 ))
114 .build()
115 .map_err(|error| {
116 dev_log!(
117 "extensions",
118 "error: [WebviewProvider] Failed to create Webview window: {}",
119 error
120 );
121
122 CommonError::UserInterfaceInteraction { Reason:error.to_string() }
123 })?;
124
125 crate::Environment::WebviewProvider::Messaging::setup_webview_message_listener_impl(env, handle.clone()).await?;
127
128 env.ApplicationHandle
130 .emit::<Value>(
131 SkyEvent::WebviewCreated.AsStr(),
132 json!({ "Handle": handle.clone(), "ViewType": view_type.clone(), "Title": title_clone }),
133 )
134 .map_err(|error| {
135 CommonError::IPCError { Description:format!("Failed to emit Webview creation event: {}", error) }
136 })?;
137
138 Ok(handle)
139}
140
141pub(super) async fn dispose_webview_panel_impl(env:&MountainEnvironment, handle:String) -> Result<(), CommonError> {
143 dev_log!("extensions", "[WebviewProvider] Disposing WebviewPanel: {}", handle);
144
145 let _ = crate::Environment::WebviewProvider::Messaging::remove_webview_message_listener_impl(env, &handle).await;
147
148 if let Some(webview_window) = env.ApplicationHandle.get_webview_window(&handle) {
150 if let Err(error) = webview_window.close() {
151 dev_log!(
152 "extensions",
153 "warn: [WebviewProvider] Failed to close Webview window: {}",
154 error
155 );
156 }
157 }
158
159 env.ApplicationState
161 .Feature
162 .Webviews
163 .ActiveWebviews
164 .lock()
165 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?
166 .remove(&handle);
167
168 env.ApplicationHandle
170 .emit::<Value>(SkyEvent::WebviewDisposed.AsStr(), json!({ "Handle": handle }))
171 .map_err(|error| {
172 CommonError::IPCError { Description:format!("Failed to emit Webview disposal event: {}", error) }
173 })?;
174
175 Ok(())
176}
177
178pub(super) async fn reveal_webview_panel_impl(
180 env:&MountainEnvironment,
181
182 handle:String,
183
184 _show_options_value:Value,
185) -> Result<(), CommonError> {
186 dev_log!("extensions", "[WebviewProvider] Revealing WebviewPanel: {}", handle);
187
188 if let Some(webview_window) = env.ApplicationHandle.get_webview_window(&handle) {
189 webview_window.show().map_err(|error| {
190 CommonError::UserInterfaceInteraction { Reason:format!("Failed to show Webview window: {}", error) }
191 })?;
192
193 webview_window.set_focus().map_err(|error| {
194 CommonError::UserInterfaceInteraction { Reason:format!("Failed to focus Webview window: {}", error) }
195 })?;
196
197 {
199 let mut webview_guard = env
200 .ApplicationState
201 .Feature
202 .Webviews
203 .ActiveWebviews
204 .lock()
205 .map_err(Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
206
207 if let Some(state) = webview_guard.get_mut(&handle) {
208 state.IsVisible = true;
209 }
210 }
211
212 env.ApplicationHandle
214 .emit::<Value>(SkyEvent::WebviewRevealed.AsStr(), json!({ "Handle": handle }))
215 .map_err(|error| {
216 CommonError::IPCError { Description:format!("Failed to emit Webview revealed event: {}", error) }
217 })?;
218 }
219
220 Ok(())
221}