Mountain/Track/Effect/CreateEffectForRequest/
WindowUI.rs1#![allow(unused_variables, dead_code, unused_imports)]
2
3use std::{future::Future, pin::Pin, sync::Arc};
9
10use serde_json::{Value, json};
11use tauri::Runtime;
12
13use crate::{
14 ApplicationState::State::ApplicationState::ApplicationState,
15 RunTime::ApplicationRunTime::ApplicationRunTime,
16 Track::Effect::MappedEffectType::MappedEffect,
17 dev_log,
18};
19
20pub fn CreateEffect<R:Runtime>(MethodName:&str, Parameters:Value) -> Option<Result<MappedEffect, String>> {
21 match MethodName {
22 "Window.ShowMessage" => {
23 let effect =
24 move |run_time:Arc<ApplicationRunTime>| -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> {
25 Box::pin(async move {
26 use tauri::Emitter;
27 let AppHandle = run_time.Environment.ApplicationHandle.clone();
28 let Payload = if Parameters.is_array() {
29 Parameters.get(0).cloned().unwrap_or_default()
30 } else {
31 Parameters
32 };
33 let Id = format!(
34 "notification-{}",
35 std::time::SystemTime::now()
36 .duration_since(std::time::UNIX_EPOCH)
37 .map(|D| D.as_millis())
38 .unwrap_or(0)
39 );
40 let Message = Payload.get("message").and_then(Value::as_str).unwrap_or("").to_string();
41 let Level = Payload.get("level").and_then(Value::as_str).unwrap_or("info").to_string();
42 let Items = Payload.get("items").cloned().unwrap_or(json!([]));
43 let Options = Payload.get("options").cloned().unwrap_or(json!({}));
44 if let Err(Error) = AppHandle.emit(
45 "sky://notification/show",
46 json!({
47 "id": Id,
48 "message": Message,
49 "severity": Level,
50 "actions": Items,
51 "options": Options,
52 }),
53 ) {
54 dev_log!(
55 "notification",
56 "warn: [Window.ShowMessage] sky://notification/show emit failed: {}",
57 Error
58 );
59 }
60 Ok(Value::Null)
61 })
62 };
63
64 Some(Ok(Box::new(effect)))
65 },
66
67 "Window.ShowQuickPick" | "Window.ShowInputBox" | "Window.ShowOpenDialog" | "Window.ShowSaveDialog" => {
68 let MethodNameOwned = MethodName.to_string();
69
70 let effect =
71 move |run_time:Arc<ApplicationRunTime>| -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> {
72 Box::pin(async move {
73 use tauri::Emitter;
74
75 let Args = if Parameters.is_array() { Parameters } else { json!([Parameters]) };
76
77 let Channel = match MethodNameOwned.as_str() {
78 "Window.ShowQuickPick" => "sky://quickpick/show",
79 "Window.ShowInputBox" => "sky://input-box/show",
80 "Window.ShowOpenDialog" => "sky://dialog/open",
81 "Window.ShowSaveDialog" => "sky://dialog/save",
82 _ => "sky://quickpick/show",
83 };
84
85 use std::sync::atomic::{AtomicU64, Ordering as AO};
86
87 static UI_SEQ:AtomicU64 = AtomicU64::new(1);
88
89 let Nonce = format!("ui-{}", UI_SEQ.fetch_add(1, AO::Relaxed));
90
91 let (tx, rx) = tokio::sync::oneshot::channel();
94 run_time.Environment.ApplicationState.UI.AddPendingRequest(Nonce.clone(), tx);
95
96 let AppHandle = run_time.Environment.ApplicationHandle.clone();
97 if let Err(Error) = AppHandle.emit(Channel, json!({ "nonce": Nonce, "args": Args })) {
98 run_time.Environment.ApplicationState.UI.RemovePendingRequest(&Nonce.clone());
101 dev_log!("ipc", "warn: [{}] {} emit failed: {}", MethodNameOwned, Channel, Error);
102 return Err(format!("[{}] emit failed: {}", MethodNameOwned, Error));
103 }
104
105 match rx.await {
109 Ok(Ok(Value)) => Ok(Value),
110 Ok(Err(CommonError)) => Err(CommonError.to_string()),
111 Err(_RecvError) => {
112 dev_log!("ipc", "[{}] dialog dismissed (nonce dropped)", MethodNameOwned);
117 Ok(Value::Null)
118 },
119 }
120 })
121 };
122
123 Some(Ok(Box::new(effect)))
124 },
125
126 _ => None,
127 }
128}