diff --git a/lib/rust/Cargo.toml b/lib/rust/Cargo.toml index 8e2826766..9e3111290 100644 --- a/lib/rust/Cargo.toml +++ b/lib/rust/Cargo.toml @@ -40,4 +40,4 @@ listDirs = [] setTitle = [] execute = [] open = [] -answer = [] +emit = [] diff --git a/lib/rust/src/api.rs b/lib/rust/src/api.rs index e652d3e99..536054a78 100644 --- a/lib/rust/src/api.rs +++ b/lib/rust/src/api.rs @@ -85,18 +85,25 @@ pub fn handler(webview: &mut WebView<'_, T>, arg: &str) -> bool { webview .eval(&format!( " - if (window['{obj}'] === void 0) {{ - window['{obj}'] = {{}} + if (window['{listeners}'] === void 0) {{ + window['{listeners}'] = {{}} }} - if (window['{obj}']['{evt}'] === void 0) {{ - window['{obj}']['{evt}'] = [] + if (window['{listeners}']['{evt}'] === void 0) {{ + window['{listeners}']['{evt}'] = [] }} - window['{obj}']['{evt}'].push({{ + window['{listeners}']['{evt}'].push({{ handler: window['{handler}'], once: {once_flag} - }}) + }}); + + for (let i = 0; i < window['{queue}'].length; i++) {{ + const e = window['{queue}'][i]; + window['{emit}'](e.payload, e.salt, true) + }} ", - obj = crate::event::event_listeners_object_name(), + listeners = crate::event::event_listeners_object_name(), + queue = crate::event::event_queue_object_name(), + emit = crate::event::emit_function_name(), evt = event, handler = handler, once_flag = if once { "true" } else { "false" } @@ -104,12 +111,8 @@ pub fn handler(webview: &mut WebView<'_, T>, arg: &str) -> bool { .unwrap(); } #[cfg(any(feature = "all-api", feature = "answer"))] - Answer { - event_id, - payload, - salt, - } => { - crate::event::answer(event_id, payload, salt); + Emit { event, payload } => { + crate::event::on_event(event, payload); } } true diff --git a/lib/rust/src/api/cmd.rs b/lib/rust/src/api/cmd.rs index badebf07c..4257eca6d 100644 --- a/lib/rust/src/api/cmd.rs +++ b/lib/rust/src/api/cmd.rs @@ -53,10 +53,9 @@ pub enum Cmd { handler: String, once: bool, }, - #[cfg(any(feature = "all-api", feature = "answer"))] - Answer { - event_id: String, + #[cfg(any(feature = "all-api", feature = "emit"))] + Emit { + event: String, payload: String, - salt: String, }, } diff --git a/lib/rust/src/event.rs b/lib/rust/src/event.rs index ea82edc4d..84d3354c3 100644 --- a/lib/rust/src/event.rs +++ b/lib/rust/src/event.rs @@ -1,4 +1,4 @@ -use proton_ui::{Handle, WebView}; +use proton_ui::Handle; use std::boxed::Box; use std::collections::HashMap; use std::sync::{Arc, Mutex}; @@ -10,24 +10,24 @@ struct EventHandler { thread_local!(static LISTENERS: Arc>> = Arc::new(Mutex::new(HashMap::new()))); lazy_static! { - static ref PROMPT_FUNCTION_NAME: String = uuid::Uuid::new_v4().to_string(); + static ref EMIT_FUNCTION_NAME: String = uuid::Uuid::new_v4().to_string(); static ref EVENT_LISTENERS_OBJECT_NAME: String = uuid::Uuid::new_v4().to_string(); + static ref EVENT_QUEUE_OBJECT_NAME: String = uuid::Uuid::new_v4().to_string(); } -pub fn prompt_function_name() -> String { - PROMPT_FUNCTION_NAME.to_string() +pub fn emit_function_name() -> String { + EMIT_FUNCTION_NAME.to_string() } pub fn event_listeners_object_name() -> String { EVENT_LISTENERS_OBJECT_NAME.to_string() } -pub fn prompt( - webview: &mut WebView<'_, T>, - id: &'static str, - payload: String, - handler: F, -) { +pub fn event_queue_object_name() -> String { + EVENT_QUEUE_OBJECT_NAME.to_string() +} + +pub fn listen(id: &'static str, handler: F) { LISTENERS.with(|listeners| { let mut l = listeners.lock().unwrap(); l.insert( @@ -37,11 +37,9 @@ pub fn prompt( }, ); }); - - trigger(webview.handle(), id, payload); } -pub fn trigger(webview_handle: Handle, id: &'static str, mut payload: String) { +pub fn emit(webview_handle: Handle, event: &'static str, mut payload: String) { let salt = crate::salt::generate(); if payload == "" { payload = "void 0".to_string(); @@ -51,8 +49,8 @@ pub fn trigger(webview_handle: Handle, id: &'static str, mut payl .dispatch(move |_webview| { _webview.eval(&format!( "window['{}']({{type: '{}', payload: {}}}, '{}')", - prompt_function_name(), - id, + emit_function_name(), + event, payload, salt )) @@ -60,19 +58,17 @@ pub fn trigger(webview_handle: Handle, id: &'static str, mut payl .unwrap(); } -pub fn answer(id: String, data: String, salt: String) { - if crate::salt::is_valid(salt) { - LISTENERS.with(|l| { - let mut listeners = l.lock().unwrap(); +pub fn on_event(event: String, data: String) { + LISTENERS.with(|l| { + let mut listeners = l.lock().unwrap(); - let key = id.clone(); + let key = event.clone(); - if listeners.contains_key(&id) { - let handler = listeners.remove(&id).unwrap(); - (handler.on_event)(data); - } + if listeners.contains_key(&event) { + let handler = listeners.remove(&event).unwrap(); + (handler.on_event)(data); + } - listeners.remove(&key); - }); - } + listeners.remove(&key); + }); } diff --git a/templates/rust/src/main.rs b/templates/rust/src/main.rs index fbaf250df..5047d89d5 100755 --- a/templates/rust/src/main.rs +++ b/templates/rust/src/main.rs @@ -128,32 +128,32 @@ fn main() { .dispatch(move |_webview| { _webview .eval(&format!( - "window['{fn}'] = (payload, salt) => {{ + "window['{queue}'] = []; + window['{fn}'] = function (payload, salt, ignoreQueue) {{ window.proton.promisified({{ cmd: 'validateSalt', salt - }}).then(() => {{ - const listeners = (window['{obj}'] && window['{obj}'][payload.type]) || [] + }}).then(function () {{ + const listeners = (window['{listeners}'] && window['{listeners}'][payload.type]) || [] + + if (!ignoreQueue && listeners.length === 0) {{ + window['{queue}'].push({{ + payload: payload, + salt: salt + }}) + }} + for (let i = listeners.length - 1; i >= 0; i--) {{ const listener = listeners[i] if (listener.once) listeners.splice(i, 1) - const response = listener.handler(payload) - response && response - .then(result => {{ - window.proton.invoke({{ - cmd: 'answer', - event_id: payload.type, - payload: result, - salt: '{salt}' - }}) - }}) + listener.handler(payload) }} }}) }}", - fn = proton::event::prompt_function_name(), - obj = proton::event::event_listeners_object_name(), - salt = proton::salt::generate_static() + fn = proton::event::emit_function_name(), + listeners = proton::event::event_listeners_object_name(), + queue = proton::event::event_queue_object_name() )) .unwrap();