euv_ui/component/bridge/hook/
impl.rs1use crate::*;
2
3impl UseEuvNativeBridge {
5 pub fn use_bridge_state() -> UseEuvNativeBridge {
14 UseEuvNativeBridge::new(
15 App::use_signal(|| false),
16 App::use_signal(|| true),
17 App::use_signal(String::new),
18 )
19 }
20
21 pub fn load_data(self, config: Option<BridgeConfig>) {
33 if !BridgeConfig::is_available(config.as_ref()) {
34 self.get_available().set(false);
35 self.get_loading().set(false);
36 return;
37 }
38 let permissions_state: UseEuvNativeBridge = self;
39 let cfg: Option<BridgeConfig> = config;
40 spawn_local(async move {
41 let args_obj: Object = Object::new();
42 Reflect::set(
43 &args_obj,
44 &JsValue::from_str(BRIDGE_GROUP_KEY),
45 &JsValue::from_str(BRIDGE_GROUP_ALL),
46 )
47 .unwrap_or(false);
48 let permissions_result: Result<JsValue, String> = match BridgeConfig::invoke(
49 INVOKE_RESOLVE_BRIDGE_GROUP_PERMISSIONS,
50 Some(&args_obj),
51 cfg.as_ref(),
52 ) {
53 Ok(promise) => {
54 let future: JsFuture = JsFuture::from(promise);
55 match future.await {
56 Ok(value) => Ok(value),
57 Err(error) => Err(format!("{error:?}")),
58 }
59 }
60 Err(error) => Err(error),
61 };
62 match permissions_result {
63 Ok(value) => {
64 let permissions_array: Vec<String> = value
65 .dyn_into::<Array>()
66 .map(|array: Array| {
67 array
68 .iter()
69 .filter_map(|item: JsValue| item.as_string())
70 .collect::<Vec<String>>()
71 })
72 .unwrap_or_default();
73 permissions_state
74 .get_permissions()
75 .set(permissions_array.join(", "));
76 permissions_state.get_available().set(true);
77 }
78 Err(_) => {
79 permissions_state.get_available().set(false);
80 }
81 }
82 permissions_state.get_loading().set(false);
83 });
84 }
85}
86
87impl UseCacheUpdate {
89 pub fn use_cache_state() -> UseCacheUpdate {
99 UseCacheUpdate::new(
100 App::use_signal(|| false),
101 App::use_signal(String::new),
102 App::use_signal(|| false),
103 )
104 }
105
106 pub fn load(self, current_version: &str, config: Option<BridgeConfig>) {
121 let doc_status_signal: Signal<bool> = self.get_doc_status();
122 let version_signal: Signal<String> = self.get_version();
123 let updating_signal: Signal<bool> = self.get_updating();
124 let version_to_compare: String = current_version.to_string();
125 let cfg: Option<BridgeConfig> = config;
126 spawn_local(async move {
127 let window_value: Window = window().expect("no global window exists");
128 let promise: Promise = window_value.fetch_with_str(DOCS_STATUS_URL);
129 let future: JsFuture = JsFuture::from(promise);
130 let response: JsValue = match future.await {
131 Ok(value) => value,
132 Err(error) => {
133 Console::error(&format!(
134 "Failed to fetch version status: {}",
135 error.as_string().unwrap_or_default()
136 ));
137 return;
138 }
139 };
140 let response_value: Response = match response.dyn_into() {
141 Ok(value) => value,
142 Err(error) => {
143 Console::error(&format!(
144 "Failed to convert fetch response: {}",
145 error.as_string().unwrap_or_default()
146 ));
147 return;
148 }
149 };
150 let text_promise: Promise = match response_value.text() {
151 Ok(promise) => promise,
152 Err(error) => {
153 Console::error(&format!(
154 "Failed to get response text promise: {}",
155 error.as_string().unwrap_or_default()
156 ));
157 return;
158 }
159 };
160 let text_future: JsFuture = JsFuture::from(text_promise);
161 let text: JsValue = match text_future.await {
162 Ok(value) => value,
163 Err(error) => {
164 Console::error(&format!(
165 "Failed to read response text: {}",
166 error.as_string().unwrap_or_default()
167 ));
168 return;
169 }
170 };
171 let text_string: String = text.as_string().unwrap_or_default();
172 Console::log(&text_string);
173 let parsed: DocsStatus =
174 serde_json::from_str::<DocsStatus>(&text_string).unwrap_or_default();
175 doc_status_signal.set(parsed.get_doc_status());
176 version_signal.set(parsed.get_version().clone());
177 if !matches!(
178 CompareVersion::compare_version(parsed.get_version(), &version_to_compare),
179 Ok(VersionLevel::Greater)
180 ) {
181 Console::log(&format!(
182 "Current version v{version_to_compare} is already the latest version"
183 ));
184 return;
185 }
186 if !BridgeConfig::is_available(cfg.as_ref()) {
187 return;
188 }
189 updating_signal.set(true);
190 if let Ok(promise) = BridgeConfig::invoke(INVOKE_UPDATE_CACHE, None, cfg.as_ref()) {
191 let future: JsFuture = JsFuture::from(promise);
192 match future.await {
193 Ok(result) => Console::log(&result.as_string().unwrap_or_default()),
194 Err(error) => Console::error(&error.as_string().unwrap_or_default()),
195 }
196 }
197 updating_signal.set(false);
198 });
199 }
200}
201
202impl BridgeConfig {
204 pub(crate) fn is_available(config: Option<&BridgeConfig>) -> bool {
218 let cfg: BridgeConfig =
219 config.map_or_else(BridgeConfig::default, |c: &BridgeConfig| c.clone());
220 let window_value: Window = window().expect("no global window exists");
221 let bridge_key: JsValue = JsValue::from_str(cfg.global_key);
222 let bridge_obj: JsValue = match Reflect::get(&window_value, &bridge_key) {
223 Ok(value) => value,
224 Err(_) => return false,
225 };
226 if bridge_obj.is_undefined() || bridge_obj.is_null() {
227 return false;
228 }
229 let core_key: JsValue = JsValue::from_str(cfg.core_key);
230 let core_obj: JsValue = match Reflect::get(&bridge_obj, &core_key) {
231 Ok(value) => value,
232 Err(_) => return false,
233 };
234 !core_obj.is_undefined() && !core_obj.is_null()
235 }
236
237 pub(crate) fn invoke(
254 command: &str,
255 args: Option<&JsValue>,
256 config: Option<&BridgeConfig>,
257 ) -> Result<Promise, String> {
258 let cfg: BridgeConfig =
259 config.map_or_else(BridgeConfig::default, |c: &BridgeConfig| c.clone());
260 let window_value: Window = window().expect("no global window exists");
261 let bridge_key: JsValue = JsValue::from_str(cfg.global_key);
262 let bridge_obj: JsValue = Reflect::get(&window_value, &bridge_key)
263 .map_err(|error: JsValue| format!("{error:?}"))?;
264 let core_key: JsValue = JsValue::from_str(cfg.core_key);
265 let core_obj: JsValue =
266 Reflect::get(&bridge_obj, &core_key).map_err(|error: JsValue| format!("{error:?}"))?;
267 let invoke_key: JsValue = JsValue::from_str(cfg.invoke_key);
268 let invoke_fn: JsValue =
269 Reflect::get(&core_obj, &invoke_key).map_err(|error: JsValue| format!("{error:?}"))?;
270 let invoke_function: Function = invoke_fn
271 .dyn_into::<Function>()
272 .map_err(|error: JsValue| format!("{error:?}"))?;
273 let command_value: JsValue = JsValue::from_str(command);
274 let result: JsValue = match args {
275 Some(arguments) => invoke_function
276 .call2(&core_obj, &command_value, arguments)
277 .map_err(|error: JsValue| format!("{error:?}"))?,
278 None => invoke_function
279 .call1(&core_obj, &command_value)
280 .map_err(|error: JsValue| format!("{error:?}"))?,
281 };
282 result
283 .dyn_into::<Promise>()
284 .map_err(|error: JsValue| format!("{error:?}"))
285 }
286}