]> uap-core.de Git - note.git/commitdiff
separate note_content from note
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 29 May 2026 09:47:33 +0000 (11:47 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 29 May 2026 09:47:33 +0000 (11:47 +0200)
application/src/backend.rs
application/src/note.rs
application/src/notebook.rs
application/src/window.rs
entity/src/lib.rs
entity/src/note.rs
entity/src/notecontent.rs [new file with mode: 0644]
migration/src/m20260502_184134_create_settings.rs
ui/common/context.c

index 8469c36fc27e2bdebe83925279d878c573bc9646..500dcd93254e91aa6120ed22291b307114302156 100644 (file)
@@ -8,10 +8,11 @@ use tokio::sync::{broadcast, mpsc};
 use migration::{Migrator, MigratorTrait};
 use ui_rs::ui;
 
-use entity::{collection, note, profile};
+use entity::{collection, note, notecontent, profile};
 use entity::profile::Entity as Profile;
 use entity::collection::{create_notebook_hierarchy, CollectionType, Entity as Collection, Node};
 use entity::note::{Entity as Note};
+use entity::notecontent::{Entity as NoteContent};
 
 pub struct Backend {
     rt: Arc<Runtime>,
@@ -296,13 +297,55 @@ impl BackendHandle {
         let _ = self.tx.send(cmd);
     }
     
-    pub fn save_note<F>(&self, note: entity::note::ActiveModel, callback: F)
-    where F: FnOnce(Result<note::ActiveModel, DbErr>) + Send + 'static {
+    pub fn get_note_content<F>(&self, note_id: i32, callback: F)
+    where F: FnOnce(Result<Option<notecontent::Model>, DbErr>) + Send + 'static {
         let backend = self.backend.clone();
         let cmd = Box::pin(async move {
-            let result = note.save(&backend.db).await;
+            let result = NoteContent::find()
+                .filter(notecontent::Column::NoteId.eq(note_id))
+                .order_by_id_asc().one(&backend.db).await;
             callback(result);
         });
         let _ = self.tx.send(cmd);
     }
+    
+    pub fn save_note<F>(&self, note: note::ActiveModel, content: Option<notecontent::ActiveModel>, callback: F)
+    where F: FnOnce(Result<(i32, i32), DbErr>) + Send + 'static {
+        let backend = self.backend.clone();
+        let cmd = Box::pin(async move {
+            let result = if note.note_id.is_set() {
+                note.update(&backend.db).await
+            } else {
+                note.insert(&backend.db).await
+            };
+
+            match result {
+                Ok(note) => {
+                    let note_id = note.note_id;
+                    if let Some(content) = content {
+                        let result2 = if content.id.is_set() {
+                            content.update(&backend.db).await
+                        } else {
+                            content.insert(&backend.db).await
+                        };
+
+                        match result2 {
+                            Ok(ctn) => {
+                                callback(Ok((note_id, ctn.id)));
+                            }
+                            Err(e) => {
+                                callback(Err(e));
+                            }
+                        }
+                    } else {
+                        callback(Ok((note_id, 0)));
+                    }
+                },
+                Err(e) => {
+                    callback(Err(e));
+                }
+            }
+        });
+        let _ = self.tx.send(cmd);
+    }
 }
index 4a9bd4247b1652c0f64de84f055df180dab86b29..e5298950ce05e807b88c129bb720712ecc3644ea 100644 (file)
@@ -10,6 +10,7 @@ use crate::window::NoteTypeTabView;
 #[derive(UiModel, Default)]
 pub struct Note {
     pub note_id: i32,
+    pub content_id: i32,
 
     pub kind: NoteType,
     pub created: DateTimeWithTimeZone,
@@ -25,7 +26,6 @@ pub struct Note {
 impl Note {
     pub fn init_from_model(&mut self, model: &entity::note::Model) {
         self.note_id = model.note_id;
-        self.text.set(model.content.as_str());
 
         let tab = match model.kind {
             NoteType::PlainTextNote => NoteTypeTabView::TextArea,
@@ -33,6 +33,11 @@ impl Note {
         };
         self.note_type.set(tab as i64);
     }
+    
+    pub fn init_content(&mut self, content: &entity::notecontent::Model) {
+        self.content_id = content.id;
+        self.text.set(content.content.as_str());
+    }
 
     pub fn save(&self, collection_id: i32, backend: &BackendHandle) {
         let content = self.text.get();
@@ -41,19 +46,26 @@ impl Note {
             None => "Note".to_string()
         };
 
+        let note_id = if self.note_id == 0 { NotSet } else { Set(self.note_id) };
+
         let note = entity::note::ActiveModel {
-            note_id: if self.note_id == 0 { NotSet } else { Set(self.note_id) },
+            note_id: note_id.clone(),
             collection_id: Set(collection_id),
             kind: Set(self.kind.clone()),
             title: Set(title),
-            content: Set(content),
             lastmodified: Set(Utc::now().into()),
             created: if self.note_id == 0 { Set(Utc::now().into()) } else { NotSet }
         };
 
-        backend.save_note(note, |result|{
+        let notecontent = entity::notecontent::ActiveModel {
+            id: if self.content_id == 0 { NotSet } else { Set(self.content_id) },
+            note_id: note_id,
+            content: Set(content),
+        };
+
+        backend.save_note(note, Some(notecontent), |result|{
             match result {
-                Ok(model) => {
+                Ok(_model) => {
                     println!("Note saved");
                 },
                 Err(error) => {
index eb1249df169684da6f4ce0ce62471b8e528d0381..366590be4c04b228786807525ef3dd14e73ca74a 100644 (file)
@@ -49,7 +49,7 @@ impl Notebook {
                         let note_proxy = current.doc_proxy();
                         let backend = self.backend.clone();
                         let collection_id = self.collection_id;
-                        note_proxy.call_mainthread(move |doc, note|{
+                        note_proxy.call_mainthread(move |_doc, note|{
                             note.save(collection_id, &backend);
                         });
                         
@@ -75,6 +75,24 @@ impl Notebook {
                     }
 
                     n.init_from_model(&note);
+
+                    let proxy = d.doc_proxy();
+                    self.backend.get_note_content(note.note_id, move|result|{
+                        proxy.call_mainthread(|doc, note|{
+                            match result {
+                                Ok(content) => {
+                                    if let Some(content) = content {
+                                        note.init_content(&content);
+                                    } else {
+                                        println!("note {}: no content", note.note_id);
+                                    }
+                                },
+                                Err(e) => {
+                                    println!("Cannot get note content: {}", e);
+                                }
+                            }
+                        });
+                    });
                 });
 
                 // Attach the new note
@@ -87,7 +105,7 @@ impl Notebook {
     }
 }
 
-pub fn note_getvalue<'a>(elm: &Note, col: i32, _row: i32) -> ListValue<'a> {
+pub fn notelist_getvalue<'a>(elm: &Note, col: i32, _row: i32) -> ListValue<'a> {
     match col {
         0 => ListValue::String(elm.title.clone()),
         1 => ListValue::String(elm.lastmodified.to_string()),
index a3629cab0cd6511806a8a3c22ad7cfef43e5379e..2a7436f7f32da3cbaa1688f35360490833010568 100644 (file)
@@ -33,7 +33,7 @@ use entity::collection::{Model as Collection, Node};
 use entity::note::Model as Note;
 use crate::backend::{BackendHandle, BroadcastMessage};
 use crate::newnotebook::new_notebook_dialog;
-use crate::notebook::{note_getvalue, Notebook};
+use crate::notebook::{notelist_getvalue, Notebook};
 
 #[derive(UiModel)]
 pub struct MainWindow {
@@ -49,11 +49,6 @@ pub struct MainWindow {
     notebooks: UiSourceList<Collection>
 }
 
-impl Drop for MainWindow {
-    fn drop(&mut self) {
-        println!("MainWindow dropped!");
-    }
-}
 
 #[ui_actions]
 impl MainWindow {
@@ -173,7 +168,7 @@ pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWi
                 .varname("notes")
                 .model(&model)
                 .fill(true)
-                .getvalue(note_getvalue)
+                .getvalue(notelist_getvalue)
                 .onselection_action("note_selected")
                 .create();
         });
index 96fecfd0baabd58330cfc19a2f60a5c9d8debf35..1b1ae7c098a2de6efa6c64176124c7e365d857eb 100644 (file)
@@ -1,4 +1,5 @@
 mod prelude;
 pub mod profile;
 pub mod collection;
-pub mod note;
\ No newline at end of file
+pub mod note;
+pub mod notecontent;
\ No newline at end of file
index 54bed383f565f870949a5e4a3cdf3ed0f75834f4..cd71986ec60d1b7151ee6802a0336c22dfd2f15d 100644 (file)
@@ -1,6 +1,7 @@
 use sea_orm::entity::prelude::*;
 
 
+#[sea_orm::model]
 #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 #[sea_orm(table_name = "note")]
 pub struct Model {
@@ -10,10 +11,12 @@ pub struct Model {
 
     pub kind: NoteType,
     pub title: String,
-    pub content: String,
 
     pub lastmodified: DateTimeWithTimeZone,
     pub created: DateTimeWithTimeZone,
+
+    #[sea_orm(has_one)]
+    pub content: HasOne<crate::notecontent::Entity>
 }
 
 #[derive(EnumIter, DeriveActiveEnum, Clone, Debug, PartialEq, Default)]
@@ -24,7 +27,4 @@ pub enum NoteType {
     MDTextNote = 1,
 }
 
-#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
-pub enum Relation {}
-
 impl ActiveModelBehavior for ActiveModel {}
diff --git a/entity/src/notecontent.rs b/entity/src/notecontent.rs
new file mode 100644 (file)
index 0000000..0396da1
--- /dev/null
@@ -0,0 +1,21 @@
+use sea_orm::entity::prelude::*;
+
+use sea_orm::{ActiveModelBehavior, DeriveEntityModel, DeriveRelation, EnumIter};
+
+#[sea_orm::model]
+#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
+#[sea_orm(table_name = "note_content")]
+pub struct Model {
+    #[sea_orm(primary_key)]
+    pub id: i32,
+
+    #[sea_orm(unique)]
+    pub note_id: i32,
+
+    pub content: String,
+
+    #[sea_orm(belongs_to, from = "note_id", to = "note_id")]
+    pub note: HasOne<crate::note::Entity>
+}
+
+impl ActiveModelBehavior for ActiveModel {}
index 1d997c1ef78f56d0595346eb438d00c0557803b6..1001304db6a935fefba0de14191dd1069a69b0f1 100644 (file)
@@ -50,14 +50,34 @@ impl MigrationTrait for Migration {
                     .col(integer("collection_id"))
                     .col(integer("kind"))
                     .col(string("title"))
-                    .col(string_null("content"))
                     .col(timestamp_with_time_zone("lastmodified"))
                     .col(timestamp_with_time_zone("created"))
                     .to_owned()
-            ).await
+            ).await?;
+
+        manager
+            .create_table(
+                Table::create()
+                    .table("note_content")
+                    .if_not_exists()
+                    .col(integer("id").primary_key())
+                    .col(integer("note_id").unique_key())
+                    .col(string("content"))
+                    .foreign_key(
+                        ForeignKey::create()
+                            .name("fk-note_content-note")
+                            .from("note_content", "note_id")
+                            .to("note", "note_id")
+                            .on_delete(ForeignKeyAction::Cascade),
+                    )
+                    .to_owned(),
+            )
+            .await
     }
 
     async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
+        manager
+            .drop_table(Table::drop().table("note_content").to_owned()).await?;
         manager
             .drop_table(Table::drop().table("note").to_owned()).await?;
         manager
index 22ecd55f860f239401e194b7f23e4f2db77d1261..b3695784a16beb996d652b6a2f7e7513fee9b6ac 100644 (file)
@@ -110,6 +110,7 @@ void uic_context_prepare_close(UiContext *ctx) {
     cxListClear(ctx->states);
     cxListClear(ctx->state_widgets);
     cxListClear(ctx->action_bindings);
+    uic_context_detach_all(ctx);
 }
 
 void uic_context_destroy(UiContext *ctx, void *document) {