Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding some communication between UI and backend to ensure sync at connection start #164

Merged
merged 12 commits into from
Aug 24, 2022
55 changes: 48 additions & 7 deletions ui/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

extern crate alloc;

use core::time::Duration;
use manta_signer::{
config::{Config, Setup},
secret::{
Expand All @@ -36,13 +35,45 @@ use manta_signer::{
serde::Serialize,
service::Server,
storage::Store,
tokio::time::sleep,
};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, Instant};
use tauri::{
async_runtime::spawn, CustomMenuItem, Manager, RunEvent, Runtime, State, SystemTray,
SystemTrayEvent, SystemTrayMenu, Window, WindowEvent,
};

/// UI_CONNECTED keeps track if we are yet connected to the UI
/// This is a workaround as normally Tauri apps do not care to be synced from the start, but we do
/// Atomic so we can modify without unsafe blocks and in closures from Tauri listen
static UI_CONNECTED: AtomicBool = AtomicBool::new(false);

/// Called from the UI after it recieves a 'connect' event
/// To ensure proper connection you should emit 'connect' continuously
/// untill UI_CONNECTED is true then stop, this is the only way for now to ensure
/// they are synced. Tauri is working on a better way
#[tauri::command]
fn ui_connected() {
UI_CONNECTED.store(true, Ordering::Relaxed);
}

/// while with a timeout
/// '$body' while body
/// '$timeout' timeout
/// '$falure' body after if while times out
macro_rules! while_w_timeout{
($body:block, $timeout_d:expr, $failure:block) => {{
let time_start = Instant::now();
let timeout = Duration::from_millis($timeout_d);
loop {
$body
if time_start.elapsed() >= timeout {
$failure
}
}
}};
}

/// User
pub struct User {
/// Main Window
Expand Down Expand Up @@ -107,11 +138,20 @@ impl Authorizer for User {
fn setup<'s>(&'s mut self, setup: &'s Setup) -> UnitFuture<'s> {
let window = self.window.clone();
Box::pin(async move {
// NOTE: We have to wait here until the UI listener is registered.
sleep(Duration::from_millis(500)).await;
window
.emit("connect", setup)
.expect("The `connect` command failed to be emitted to the window.");
while_w_timeout!(
{
if UI_CONNECTED.load(Ordering::Relaxed) {
break;
}
window
.emit("connect", setup)
.expect("The `connect` command failed to be emitted to the window.");
},
5000,
{
panic!("Connection attempt timedout!");
}
);
})
}

Expand Down Expand Up @@ -220,6 +260,7 @@ fn main() {
.invoke_handler(tauri::generate_handler![
send_password,
stop_password_prompt,
ui_connected,
])
.build(tauri::generate_context!())
.expect("Error while building UI.");
Expand Down
1 change: 1 addition & 0 deletions ui/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function App() {
if (isConnected) return;
const beginInitialConnectionPhase = async () => {
await once('connect', (event) => {
invoke('ui_connected');
console.log("[INFO]: Connect Event: ", event);
let payload = event.payload;
switch (payload.type) {
Expand Down