Add ability to listen to node events from the frontend

This commit is contained in:
Sebastian Martinez
2024-09-18 12:25:28 +02:00
parent 797a64b8d7
commit ff6b7aa5dc
7 changed files with 95 additions and 1 deletions
+1
View File
@@ -3672,6 +3672,7 @@ name = "radicle-desktop"
version = "0.0.0"
dependencies = [
"anyhow",
"log",
"radicle",
"radicle-surf",
"serde",
+1
View File
@@ -20,6 +20,7 @@ tauri-build = { version = "2.0.0-rc.0", features = ["isolation"] }
[dependencies]
anyhow = { version = "1.0.86" }
log = { version = "0.4" }
radicle = { version = "0.13.0" }
radicle-surf = { version = "0.22.0" }
serde = { version = "1.0", features = ["derive"] }
+4
View File
@@ -73,6 +73,10 @@ pub enum Error {
hint: &'static str,
},
/// Tauri error.
#[error(transparent)]
Tauri(#[from] tauri::Error),
/// Storage error.
#[error(transparent)]
Storage(#[from] radicle::storage::Error),
+42
View File
@@ -0,0 +1,42 @@
use std::sync::{atomic::AtomicBool, Arc};
use radicle::{node::Handle, Node, Profile};
use tauri::{AppHandle, Emitter};
use crate::error::Error;
pub async fn subscribe_events(
handle: &AppHandle,
profile: Profile,
existing_events_thread: Arc<AtomicBool>,
) -> Result<(), Error> {
let event_handler = handle.clone();
let node = Node::new(profile.socket());
if !node.is_running() {
event_handler.emit("node_status", "stopped")?;
log::debug!("node: not subscribing to events due to stopped node.");
return Ok(());
};
event_handler.emit("node_status", "running")?;
if existing_events_thread.load(std::sync::atomic::Ordering::SeqCst) {
log::debug!("node: not subscribing to events due to a running subscription.");
return Ok(());
} else {
let join_handle = tauri::async_runtime::spawn(async move {
log::debug!("node: spawned node event subscription.");
while let Ok(events) = node.subscribe(std::time::Duration::MAX) {
existing_events_thread.store(true, std::sync::atomic::Ordering::SeqCst);
for event in events.into_iter().flatten() {
let _ = event_handler.emit("event", event);
}
}
existing_events_thread.store(false, std::sync::atomic::Ordering::SeqCst);
log::debug!("node: event subscription loop has exited.");
});
join_handle.await?;
}
Ok(())
}
+23 -1
View File
@@ -1,8 +1,13 @@
mod commands;
mod error;
mod events;
mod types;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use serde_json::json;
use tauri::Listener;
use tauri::Manager;
use radicle::identity::doc::PayloadId;
@@ -15,6 +20,7 @@ use radicle::storage::git::Repository;
use radicle::storage::{ReadRepository, ReadStorage};
use commands::{auth, cobs, profile, repos};
use events::subscribe_events;
use types::repo::SupportedPayloads;
struct AppState {
@@ -97,7 +103,23 @@ pub fn run() {
}),
}?;
app.manage(AppState { profile });
app.manage(AppState {
profile: profile.clone(),
});
let existing_events_thread: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
let events_handler = app.handle().clone();
app.listen("subscribe_events", move |_| {
let profile = profile.clone();
let existing_events_thread = existing_events_thread.clone();
let events_handler = events_handler.to_owned();
tauri::async_runtime::spawn(async move {
let _result =
subscribe_events(&events_handler, profile, existing_events_thread).await;
});
});
Ok(())
})
+12
View File
@@ -2,9 +2,11 @@
import { onMount } from "svelte";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
import * as router from "@app/lib/router";
import { theme } from "@app/components/ThemeSwitch.svelte";
import { subscribeToNodeEvents } from "@app/lib/events";
import { unreachable } from "@app/lib/utils";
import AuthenticationError from "@app/views/AuthenticationError.svelte";
@@ -12,6 +14,16 @@
import Issues from "@app/views/repo/Issues.svelte";
import Patches from "@app/views/repo/Patches.svelte";
subscribeToNodeEvents();
void listen("event", event => {
console.log(event.payload);
});
void listen("node_status", event => {
console.log(`Node: ${event.payload}`);
});
const activeRouteStore = router.activeRouteStore;
onMount(async () => {
+12
View File
@@ -0,0 +1,12 @@
import { emit } from "@tauri-apps/api/event";
let interval: ReturnType<typeof setInterval> | undefined = undefined;
export function subscribeToNodeEvents() {
if (interval === undefined) {
interval = setInterval(() => {
// In case there is a running subscription this won't launch a new one.
void emit("subscribe_events");
}, 10_000);
}
}