chore(merge) feature/event-system-cleanup (#13)

* feat(event-system) better communication interface

* feat(proton) update main.rs

* test

* Revert "test"

This reverts commit 68daf6eeb7.
This commit is contained in:
Lucas Fernandes Nogueira 2019-07-31 19:04:24 -03:00 committed by GitHub
parent b40bc281d0
commit aa4fef37b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 61 deletions

View File

@ -40,4 +40,4 @@ listDirs = []
setTitle = []
execute = []
open = []
answer = []
emit = []

View File

@ -85,18 +85,25 @@ pub fn handler<T: 'static>(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<T: 'static>(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

View File

@ -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,
},
}

View File

@ -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<Mutex<HashMap<String, EventHandler>>> = 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<T: 'static, F: FnOnce(String) + 'static>(
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<F: FnOnce(String) + 'static>(id: &'static str, handler: F) {
LISTENERS.with(|listeners| {
let mut l = listeners.lock().unwrap();
l.insert(
@ -37,11 +37,9 @@ pub fn prompt<T: 'static, F: FnOnce(String) + 'static>(
},
);
});
trigger(webview.handle(), id, payload);
}
pub fn trigger<T: 'static>(webview_handle: Handle<T>, id: &'static str, mut payload: String) {
pub fn emit<T: 'static>(webview_handle: Handle<T>, 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<T: 'static>(webview_handle: Handle<T>, 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<T: 'static>(webview_handle: Handle<T>, 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);
});
}

View File

@ -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();