use std::sync::{Arc};
use std::thread::JoinHandle;
use tokio::sync::{broadcast, mpsc};
+use tokio::sync::broadcast::error::SendError;
use migration::{Migrator, MigratorTrait};
use ui_rs::ui;
#[derive(Clone)]
pub enum BroadcastMessage {
- NotebookStructureUpdate(Vec<Node>)
+ NotebookStructureUpdate(Vec<Node>),
+ NotesUpdate(NotesUpdate),
+}
+
+#[derive(Clone)]
+pub enum NoteId {
+ Id(i32),
+ TmpId(String),
+}
+
+impl Default for NoteId {
+ fn default() -> Self {
+ NoteId::Id(0)
+ }
+}
+
+#[derive(Clone, Default)]
+pub struct NoteUpdate {
+ pub note_id: NoteId,
+ pub title: Option<String>,
+ pub content: bool,
+}
+
+#[derive(Clone, Default)]
+pub struct NotesUpdate {
+ pub collection_id: i32,
+ pub note_updates: Vec<NoteUpdate>,
+}
+
+impl NotesUpdate {
+ pub fn new(collection_id: i32, note_updates: Vec<NoteUpdate>) -> Self {
+ NotesUpdate {
+ collection_id: collection_id,
+ note_updates: note_updates,
+ }
+ }
}
}
impl BackendHandle {
+ pub fn send_broadcast(&self, msg: BroadcastMessage) -> Result<usize, SendError<BroadcastMessage>> {
+ let result = self.btx.send(msg);
+ if let Some(notify) = &self.backend.broadcast_notify.as_ref() {
+ notify();
+ }
+ result
+ }
+
/// Reloads the notebook structure/collections. On success, it sends a NotebookStructureUpdate
/// to the broadcast channel.
pub fn reload_collections(&self) {
use entity::note::NoteType;
use ui_rs::{action, ui_actions, UiModel};
use ui_rs::ui::*;
-use crate::backend::BackendHandle;
+use crate::backend::{BackendHandle, BroadcastMessage, NoteId, NoteUpdate, NotesUpdate};
use crate::window::NoteTypeTabView;
#[derive(UiModel)]
pub fn init_content(&mut self, content: &entity::notecontent::Model) {
self.content_id = content.id;
self.text.set(content.content.as_str());
- self.update_title(content.content.as_str());
+ self.update_title(content.content.as_str(), false);
}
- pub fn update_title(&mut self, s: &str) {
+ pub fn update_title(&mut self, s: &str, notify: bool) {
match generate_title(s) {
Some(result) => {
let title = result.0;
self.title_start = result.1 as i32;
self.title_end = result.1 as i32 + title.len() as i32;
- // TODO: notify notebook that the title has changed
+ if notify {
+ let update = NoteUpdate {
+ note_id: NoteId::Id(self.note_id),
+ title: Some(title.to_string()),
+ ..Default::default()
+ };
+ let msg = NotesUpdate::new(self.collection_id, vec![update]);
+ _ = self.backend.as_ref().send_broadcast(BroadcastMessage::NotesUpdate(msg));
+ }
},
None => {
self.title_start = -1;
}
// TODO: we don't need the full text
- self.update_title(self.text.get().as_str());
+ self.update_title(self.text.get().as_str(), true);
}
}
use ui_rs::ui::*;
use entity::note::{Model as Note};
-use crate::backend::{BackendHandle, BroadcastMessage};
+use crate::backend::{BackendHandle, BroadcastMessage, NoteId};
#[derive(UiModel)]
pub struct Notebook {
pub fn message(&mut self, _event: &ActionEvent) {
while let Ok(msg) = self.broadcast_rx.try_recv() {
match msg {
+ BroadcastMessage::NotesUpdate(update) => {
+ let mut update_rows: Vec<usize> = Vec::new();
+ for u in &update.note_updates {
+ if let NoteId::Id(id) = u.note_id {
+ let note_data = self.notes.data_mut();
+ for (i, note) in note_data.iter_mut().enumerate() {
+ if note.note_id == id {
+ // update note
+ if let Some(title) = &u.title {
+ note.title = title.clone();
+ }
+ }
+ update_rows.push(i);
+ }
+ }
+ }
+
+ for i in update_rows {
+ self.notes.update_row(i);
+ }
+ },
_ => {
-
+
},
}
}
while let Ok(msg) = self.broadcast_rx.try_recv() {
match msg {
BroadcastMessage::NotebookStructureUpdate(nodes) => self.update_notebook_structure(&nodes),
+ _ => {}
}
}
}
}
}
- pub fn update(&mut self) {
+ pub fn update(&self) {
unsafe {
ui_list_update(self.ptr);
}
}
- pub fn update_row(&mut self, row: i32) {
+ pub fn update_row(&self, row: usize) {
unsafe {
- ui_list_update_row(self.ptr, row);
+ ui_list_update_row(self.ptr, row as i32);
}
}