1use std::sync::Arc;
7
8use serde_json::Value;
9use tauri::{AppHandle, Emitter};
10use ::Vine::Host::{ApplicationStateAccess, IPCProvider, RendererEmitter, VineHost};
11
12use crate::{Vine::Server::MountainVinegRPCService::MountainVinegRPCService, dev_log};
13
14struct MountainApplicationStateAccess;
18
19impl ApplicationStateAccess for MountainApplicationStateAccess {
20 fn EmbedderName(&self) -> &'static str { "Mountain" }
21}
22
23static MOUNTAIN_APP_STATE:MountainApplicationStateAccess = MountainApplicationStateAccess;
24
25pub struct TauriRendererEmitter {
32 Handle:AppHandle,
33}
34
35impl TauriRendererEmitter {
36 pub fn New(Handle:AppHandle) -> Self { Self { Handle } }
37}
38
39impl RendererEmitter for TauriRendererEmitter {
40 fn Emit(&self, Channel:&str, Payload:Value) {
41 if let Err(Error) = self.Handle.emit(Channel, Payload) {
42 dev_log!("sky-emit", "[SkyEmit] fail channel={} error={}", Channel, Error);
43 }
44 }
45}
46
47struct MountainIPCProvider;
51
52impl IPCProvider for MountainIPCProvider {
53 fn SendRequest(
54 &self,
55
56 Channel:&str,
57
58 _Payload:Value,
59 ) -> futures::future::BoxFuture<'_, ::Vine::Error::Result<Value>> {
60 let Channel = Channel.to_string();
61
62 Box::pin(async move {
63 dev_log!(
64 "grpc",
65 "warn: [VineHost] IPCProvider::SendRequest channel={} - not wired",
66 Channel
67 );
68
69 Ok(Value::Null)
70 })
71 }
72
73 fn SendNotification(&self, Channel:&str, Method:&str, Payload:Value) {
74 let Ch = Channel.to_string();
75
76 let M = Method.to_string();
77
78 tauri::async_runtime::spawn(async move {
79 let _ = ::Vine::Client::SendNotification::Fn(Ch, M, Payload).await;
80 });
81 }
82}
83
84impl VineHost for MountainVinegRPCService {
85 fn ApplicationState(&self) -> &dyn ApplicationStateAccess { &MOUNTAIN_APP_STATE }
86
87 fn EmitToRenderer(&self, Channel:&str, Payload:Value) {
88 if let Err(Error) = self.ApplicationHandle().emit(Channel, Payload) {
89 dev_log!("sky-emit", "[SkyEmit] fail channel={} error={}", Channel, Error);
90 }
91 }
92
93 fn RendererEmitter(&self) -> Arc<dyn RendererEmitter> {
94 Arc::new(TauriRendererEmitter::New(self.ApplicationHandle().clone()))
95 }
96
97 fn IPCProvider(&self) -> Arc<dyn IPCProvider> { Arc::new(MountainIPCProvider) }
98
99 fn UnregisterProvider(&self, Handle:u32) {
100 self.RunTime()
101 .Environment
102 .ApplicationState
103 .Extension
104 .ProviderRegistration
105 .UnregisterProvider(Handle);
106 }
107
108 fn RegisterCommandInRegistry(&self, CommandId:&str, SideCarIdentifier:&str) {
109 use crate::Environment::CommandProvider::CommandHandler;
110
111 if let Ok(mut Registry) = self
112 .RunTime()
113 .Environment
114 .ApplicationState
115 .Extension
116 .Registry
117 .CommandRegistry
118 .lock()
119 {
120 Registry.insert(
121 CommandId.to_string(),
122 CommandHandler::Proxied {
123 SideCarIdentifier:SideCarIdentifier.to_string(),
124 CommandIdentifier:CommandId.to_string(),
125 },
126 );
127 }
128 }
129
130 fn UnregisterCommandInRegistry(&self, CommandId:&str) {
131 if let Ok(mut Registry) = self
132 .RunTime()
133 .Environment
134 .ApplicationState
135 .Extension
136 .Registry
137 .CommandRegistry
138 .lock()
139 {
140 Registry.remove(CommandId);
141 }
142 }
143
144 fn SpawnSendTextToTerminal(&self, TerminalId:u64, Text:String) {
145 use CommonLibrary::{Environment::Requires::Requires, Terminal::TerminalProvider::TerminalProvider};
146
147 let Provider:Arc<dyn TerminalProvider> = self.RunTime().Environment.Require();
148
149 tauri::async_runtime::spawn(async move {
150 let _ = Provider.SendTextToTerminal(TerminalId, Text).await;
151 });
152 }
153
154 fn SpawnDisposeTerminal(&self, TerminalId:u64) {
155 use CommonLibrary::{Environment::Requires::Requires, Terminal::TerminalProvider::TerminalProvider};
156
157 let Provider:Arc<dyn TerminalProvider> = self.RunTime().Environment.Require();
158
159 tauri::async_runtime::spawn(async move {
160 let _ = Provider.DisposeTerminal(TerminalId).await;
161 });
162 }
163
164 fn CreateTerminal<'a>(&'a self, Options:&'a Value) -> futures::future::BoxFuture<'a, Option<Value>> {
165 use CommonLibrary::{Environment::Requires::Requires, Terminal::TerminalProvider::TerminalProvider};
166
167 let Provider:Arc<dyn TerminalProvider> = self.RunTime().Environment.Require();
168
169 let Opts = Options.clone();
170
171 Box::pin(async move { Provider.CreateTerminal(Opts).await.ok() })
172 }
173
174 fn RegisterScmInRegistry(&self, Handle:u32, ScmId:&str, Label:&str, ExtId:&str) {
175 use CommonLibrary::LanguageFeature::DTO::ProviderType::ProviderType;
176 use serde_json::json;
177
178 use crate::ApplicationState::DTO::ProviderRegistrationDTO::ProviderRegistrationDTO;
179
180 let Dto = ProviderRegistrationDTO {
181 Handle,
182
183 ProviderType:ProviderType::SourceControl,
184
185 Selector:json!([{ "scmId": ScmId }]),
186
187 SideCarIdentifier:"cocoon-main".to_string(),
188
189 ExtensionIdentifier:json!(ExtId),
190
191 Options:Some(json!({ "scmId": ScmId, "label": Label })),
192 };
193
194 self.RunTime()
195 .Environment
196 .ApplicationState
197 .Extension
198 .ProviderRegistration
199 .RegisterProvider(Handle, Dto);
200 }
201
202 fn CreateSourceControl<'a>(&'a self, Payload:Value) -> futures::future::BoxFuture<'a, ()> {
203 use CommonLibrary::SourceControlManagement::SourceControlManagementProvider::SourceControlManagementProvider;
204
205 let RunTime = self.RunTime().clone();
206
207 Box::pin(async move {
208 if let Err(E) = RunTime.Environment.CreateSourceControl(Payload).await {
209 dev_log!("grpc", "warn: [VineHost] CreateSourceControl failed: {}", E);
210 }
211 })
212 }
213
214 fn UpdateSourceControlGroup<'a>(&'a self, ScmHandle:u32, Payload:Value) -> futures::future::BoxFuture<'a, ()> {
215 use CommonLibrary::SourceControlManagement::SourceControlManagementProvider::SourceControlManagementProvider;
216
217 let RunTime = self.RunTime().clone();
218
219 Box::pin(async move {
220 if let Err(E) = RunTime.Environment.UpdateSourceControlGroup(ScmHandle, Payload).await {
221 dev_log!(
222 "grpc",
223 "warn: [VineHost] UpdateSourceControlGroup scm={} failed: {}",
224 ScmHandle,
225 E
226 );
227 }
228 })
229 }
230
231 fn RegisterLanguageProvider(&self, Handle:u32, TypeName:&str, Payload:&Value) -> bool {
232 use CommonLibrary::LanguageFeature::DTO::ProviderType::ProviderType as PT;
233 use serde_json::json;
234
235 use crate::ApplicationState::DTO::ProviderRegistrationDTO::ProviderRegistrationDTO;
236
237 let ProvType:Option<PT> = match TypeName {
238 "authentication" => Some(PT::Authentication),
239
240 "call_hierarchy" => Some(PT::CallHierarchy),
241
242 "code_actions" => Some(PT::CodeAction),
243
244 "code_lens" => Some(PT::CodeLens),
245
246 "color" => Some(PT::Color),
247
248 "completion_item" => Some(PT::Completion),
249
250 "debug_adapter" => Some(PT::DebugAdapter),
251
252 "debug_configuration" => Some(PT::DebugConfiguration),
253
254 "declaration" => Some(PT::Declaration),
255
256 "definition" => Some(PT::Definition),
257
258 "document_drop_edit" => Some(PT::DocumentDropEdit),
259
260 "document_formatting" => Some(PT::DocumentFormatting),
261
262 "document_highlight" => Some(PT::DocumentHighlight),
263
264 "document_link" => Some(PT::DocumentLink),
265
266 "document_paste_edit" => Some(PT::DocumentPasteEdit),
267
268 "document_range_formatting" => Some(PT::DocumentRangeFormatting),
269
270 "document_symbol" => Some(PT::DocumentSymbol),
271
272 "evaluatable_expression" => Some(PT::EvaluatableExpression),
273
274 "external_uri_opener" => Some(PT::ExternalUriOpener),
275
276 "file_decoration" => Some(PT::FileDecoration),
277
278 "file_system" => Some(PT::FileSystem),
279
280 "folding_range" => Some(PT::FoldingRange),
281
282 "hover" => Some(PT::Hover),
283
284 "implementation" => Some(PT::Implementation),
285
286 "inlay_hints" => Some(PT::InlayHint),
287
288 "inline_completion_item" => Some(PT::InlineCompletion),
289
290 "inline_edit" => Some(PT::InlineEdit),
291
292 "inline_values" => Some(PT::InlineValues),
293
294 "linked_editing_range" => Some(PT::LinkedEditingRange),
295
296 "mapped_edits" => Some(PT::MappedEdits),
297
298 "multi_document_highlight" => Some(PT::MultiDocumentHighlight),
299
300 "notebook_content" => Some(PT::NotebookContent),
301
302 "notebook_serializer" => Some(PT::NotebookSerializer),
303
304 "on_type_formatting" => Some(PT::OnTypeFormatting),
305
306 "reference" => Some(PT::References),
307
308 "remote_authority_resolver" => Some(PT::RemoteAuthorityResolver),
309
310 "rename" => Some(PT::Rename),
311
312 "resource_label_formatter" => Some(PT::ResourceLabelFormatter),
313
314 "scm" => Some(PT::SourceControl),
315
316 "scm_resource_group" => Some(PT::ScmResourceGroup),
317
318 "selection_range" => Some(PT::SelectionRange),
319
320 "semantic_tokens" => Some(PT::SemanticTokens),
321
322 "signature_help" => Some(PT::SignatureHelp),
323
324 "task" => Some(PT::Task),
325
326 "terminal_link" => Some(PT::TerminalLink),
327
328 "terminal_profile" => Some(PT::TerminalProfile),
329
330 "text_document_content" => Some(PT::TextDocumentContent),
331
332 "type_definition" => Some(PT::TypeDefinition),
333
334 "type_hierarchy" => Some(PT::TypeHierarchy),
335
336 "uri_handler" => Some(PT::UriHandler),
337
338 "workspace_symbol" => Some(PT::WorkspaceSymbol),
339
340 _ => None,
341 };
342
343 let Some(ProviderType) = ProvType else { return false };
344
345 let Selector = Payload
346 .get("languageSelector")
347 .or_else(|| Payload.get("language_selector"))
348 .and_then(Value::as_str)
349 .unwrap_or("*");
350
351 let ExtId = Payload
352 .get("extensionId")
353 .or_else(|| Payload.get("extension_id"))
354 .and_then(Value::as_str)
355 .unwrap_or("");
356
357 let Scheme = Payload.get("scheme").and_then(Value::as_str).unwrap_or("");
358
359 let SelectorValue = if !Scheme.is_empty() {
360 json!([{ "scheme": Scheme, "language": Selector }])
361 } else {
362 json!([{ "language": Selector }])
363 };
364
365 let Dto = ProviderRegistrationDTO {
366 Handle,
367
368 ProviderType,
369
370 Selector:SelectorValue,
371
372 SideCarIdentifier:"cocoon-main".to_string(),
373
374 ExtensionIdentifier:json!(ExtId),
375
376 Options:Payload.get("options").cloned(),
377 };
378
379 self.RunTime()
380 .Environment
381 .ApplicationState
382 .Extension
383 .ProviderRegistration
384 .RegisterProvider(Handle, Dto);
385
386 true
387 }
388
389 fn UpdateScmGroupMarkers(&self, ScmHandle:u32, GroupId:&str, ResourceStates:&Value) {
390 use std::collections::HashMap;
391
392 use CommonLibrary::SourceControlManagement::DTO::SourceControlManagementResourceDTO::SourceControlManagementResourceDTO;
393
394 if let Ok(mut Resources) = self
395 .RunTime()
396 .Environment
397 .ApplicationState
398 .Feature
399 .Markers
400 .SourceControlManagementResources
401 .lock()
402 {
403 let GroupsForProvider = Resources.entry(ScmHandle).or_insert_with(HashMap::new);
404
405 let mut DtoList:Vec<SourceControlManagementResourceDTO> = Vec::new();
406
407 if let Some(Array) = ResourceStates.as_array() {
408 for Raw in Array {
409 let ResourceUri = Raw
410 .get("resourceUri")
411 .or_else(|| Raw.get("sourceUri"))
412 .or_else(|| Raw.get("uri"))
413 .cloned()
414 .unwrap_or(Value::Null);
415
416 if ResourceUri.is_null() {
417 continue;
418 }
419
420 let Decorations = Raw
421 .get("decorations")
422 .cloned()
423 .unwrap_or_else(|| Value::Object(serde_json::Map::new()));
424
425 DtoList.push(SourceControlManagementResourceDTO {
426 ProviderHandle:ScmHandle,
427 GroupIdentifier:GroupId.to_string(),
428 ResourceURI:ResourceUri,
429 Decorations,
430 });
431 }
432 }
433
434 GroupsForProvider.insert(GroupId.to_string(), DtoList);
435 }
436 }
437}