]> uap-core.de Git - note.git/commitdiff
add message broadcasting system
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 17 May 2026 10:38:17 +0000 (12:38 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 17 May 2026 10:38:17 +0000 (12:38 +0200)
application/src/backend.rs
application/src/main.rs
application/src/window.rs

index bf12ef3a30eb7a878edb98965465e273c01c51c9..7318c0585693ab00280c6368a4859595ade5cd16 100644 (file)
@@ -3,20 +3,20 @@ use std::pin::Pin;
 use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, DbErr, EntityTrait, QueryFilter, ColumnTrait, Set, QueryOrder};
 use tokio::runtime::Runtime;
 use std::sync::{Arc};
-use tokio::sync::mpsc;
-use tokio::sync::mpsc::UnboundedSender;
+use tokio::sync::{broadcast, mpsc};
 use migration::{Migrator, MigratorTrait};
 use ui_rs::ui;
 
 use entity::{collection, profile};
 use entity::profile::Entity as Profile;
-use entity::collection::{CollectionType, Entity as Collection};
+use entity::collection::{CollectionType, Entity as Collection, Node};
 
 pub struct Backend {
     rt: Arc<Runtime>,
     db: DatabaseConnection,
 
     pub current_profile: Option<profile::Model>,
+    pub broadcast: Option<tokio::sync::broadcast::Sender<BroadcastMessage>>
 }
 
 type CmdFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
@@ -27,9 +27,25 @@ pub trait Cmd: Send {
 pub type DynCmd = Box<dyn Cmd>;
 
 pub struct BackendHandle {
-    tx: UnboundedSender<DynCmd>,
+    pub tx: tokio::sync::mpsc::UnboundedSender<DynCmd>,
+    pub btx: tokio::sync::broadcast::Sender<BroadcastMessage>,
+    pub brx: tokio::sync::broadcast::Receiver<BroadcastMessage>
 }
 
+impl Clone for BackendHandle {
+    fn clone(&self) -> Self {
+        BackendHandle {
+            tx: self.tx.clone(),
+            btx: self.btx.clone(),
+            brx: self.btx.subscribe()
+        }
+    }
+}
+
+#[derive(Clone)]
+pub enum BroadcastMessage {
+    NotebookStructureUpdate(Vec<Node>)
+}
 
 
 impl Backend {
@@ -52,6 +68,7 @@ impl Backend {
             rt,
             db,
             current_profile: None,
+            broadcast: None
         })
     }
 
@@ -120,7 +137,7 @@ impl Backend {
 
                 ..Default::default()
             };
-            let notebooks = insert_notebooks.insert(&self.db).await?;
+            insert_notebooks.insert(&self.db).await?;
 
             let insert_notes = collection::ActiveModel {
                 profile_id: Set(inserted.id),
@@ -148,10 +165,12 @@ impl Backend {
         })
     }
 
-    pub fn start(self) -> BackendHandle {
-        let backend = Arc::new(self);
-
+    pub fn start(mut self) -> BackendHandle {
         let (tx, mut rx) = mpsc::unbounded_channel::<DynCmd>();
+        let (btx, brx) = broadcast::channel::<BroadcastMessage>(16);
+        self.broadcast = Some(btx.clone());
+
+        let backend = Arc::new(self);
 
         let rt = backend.rt.clone();
 
@@ -167,6 +186,10 @@ impl Backend {
             });
         });
 
-        BackendHandle { tx }
+        BackendHandle {
+            tx: tx,
+            btx: btx,
+            brx: brx,
+        }
     }
 }
index 82dfcda18fe35f78cf1ee8caea45f78fb258df4a..4683cee7aeba04f2fd683e51b3ce859b0a36d6b8 100644 (file)
@@ -127,8 +127,7 @@ impl Application<MainWindow> for App {
 
         create_toolbar(app);
 
-        let window = create_window(app);
-        window.window_data(|data| init_window_data(data, self));
+        create_window(self, app);
     }
 }
 
index 3e3fe1449b3dfc8cdef8c8dbacb44d65dd157d2c..507afa1cabca62246b7d556f1e55f5696062ddf7 100644 (file)
 use ui_rs::{action, ui_actions, UiModel};
 use ui_rs::ui::*;
 use crate::App;
-use entity::collection::Model as Collection;
+use entity::collection::{Model as Collection, Node};
+use crate::backend::{BackendHandle, BroadcastMessage};
 
-#[derive(UiModel, Default)]
+#[derive(UiModel)]
 pub struct MainWindow {
+    pub backend: BackendHandle,
+
     #[bind]
     notebooks: UiSourceList<Collection>
 }
 
 #[ui_actions]
 impl MainWindow {
+    pub fn new(app: &App) -> MainWindow {
+        MainWindow {
+            backend: app.backend.clone(),
+            notebooks: UiSourceList::default()
+        }
+    }
+
     #[action]
     pub fn new_notebook(&mut self, _event: &ActionEvent) {
         println!("new notebook");
@@ -58,12 +68,23 @@ impl MainWindow {
     pub fn go_forward(&mut self, _event: &ActionEvent) {
 
     }
+
+    #[action]
+    pub fn message(&mut self, _event: &ActionEvent) {
+        while let Ok(msg) = self.backend.brx.try_recv() {
+            match msg {
+                BroadcastMessage::NotebookStructureUpdate(nodes) => fill_sourcelist_from_nodes(&mut self.notebooks, &nodes),
+            }
+        }
+    }
 }
 
-pub fn create_window(app: &AppContext<MainWindow>) -> UiObject<MainWindow> {
-    let windowdata: MainWindow = Default::default();
+pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWindow> {
+    let windowdata: MainWindow = MainWindow::new(app);
+
+    let window = ctx.splitview_window("note", true, windowdata, |obj, data| {
+        init_window_data(data, app);
 
-    let window = app.splitview_window("note", true, windowdata, |obj, data| {
         obj.sidebar_builder().create(|obj|{
             obj.sourcelist(|b|{
                 b.fill(true);
@@ -108,8 +129,14 @@ pub fn create_window(app: &AppContext<MainWindow>) -> UiObject<MainWindow> {
     window
 }
 
-pub fn init_window_data(window: &mut MainWindow, data: &App) {
-    for elm in data.notebooks.iter() {
+fn init_window_data(window: &mut MainWindow, data: &App) {
+    fill_sourcelist_from_nodes(&mut window.notebooks, &data.notebooks);
+}
+
+fn fill_sourcelist_from_nodes(list: &mut UiSourceList<Collection>, nodes: &Vec<Node>) {
+    list.clear();
+
+    for elm in nodes.iter() {
         let mut notebook = SubList::new();
         notebook.set_header(elm.collection.name.as_str());
 
@@ -118,7 +145,7 @@ pub fn init_window_data(window: &mut MainWindow, data: &App) {
             sublist_data.push(child.collection.clone());
         }
 
-        window.notebooks.push(notebook);
+        list.push(notebook);
     }
-    window.notebooks.update();
+    list.update();
 }