From: Olaf Wintermann Date: Sun, 17 May 2026 10:38:17 +0000 (+0200) Subject: add message broadcasting system X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=b3c3343319b97e51c4a84c717e82ba54bed5724e;p=note.git add message broadcasting system --- diff --git a/application/src/backend.rs b/application/src/backend.rs index bf12ef3..7318c05 100644 --- a/application/src/backend.rs +++ b/application/src/backend.rs @@ -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, db: DatabaseConnection, pub current_profile: Option, + pub broadcast: Option> } type CmdFuture = Pin + Send>>; @@ -27,9 +27,25 @@ pub trait Cmd: Send { pub type DynCmd = Box; pub struct BackendHandle { - tx: UnboundedSender, + pub tx: tokio::sync::mpsc::UnboundedSender, + pub btx: tokio::sync::broadcast::Sender, + pub brx: tokio::sync::broadcast::Receiver } +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) +} 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::(); + let (btx, brx) = broadcast::channel::(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, + } } } diff --git a/application/src/main.rs b/application/src/main.rs index 82dfcda..4683cee 100644 --- a/application/src/main.rs +++ b/application/src/main.rs @@ -127,8 +127,7 @@ impl Application for App { create_toolbar(app); - let window = create_window(app); - window.window_data(|data| init_window_data(data, self)); + create_window(self, app); } } diff --git a/application/src/window.rs b/application/src/window.rs index 3e3fe14..507afa1 100644 --- a/application/src/window.rs +++ b/application/src/window.rs @@ -29,16 +29,26 @@ 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 } #[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) -> UiObject { - let windowdata: MainWindow = Default::default(); +pub fn create_window(app: &App, ctx: &AppContext) -> UiObject { + 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) -> UiObject { 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, nodes: &Vec) { + 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(); }