From: Olaf Wintermann Date: Fri, 17 Jul 2026 16:30:14 +0000 (+0200) Subject: add support for database-stored file content in open_extern X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=HEAD;p=note.git add support for database-stored file content in open_extern --- diff --git a/application/backend/src/backend.rs b/application/backend/src/backend.rs index 3253a1e..14823ea 100644 --- a/application/backend/src/backend.rs +++ b/application/backend/src/backend.rs @@ -47,7 +47,7 @@ use entity::notecontent::{Entity as NoteContent}; use migration::prelude::Utc; use crate::lockmanager::LockManager; use crate::note::{create_nodename, randomize_nodename}; -use crate::storage::{get_collection_storage_path, get_note_storage_path, write_file}; +use crate::storage::{get_collection_storage_path, get_file_content, get_note_storage_path, write_file, write_tmp_file}; pub struct Backend { rt: Arc, @@ -431,7 +431,7 @@ impl BackendHandle { }); let _ = self.tx.send(cmd); } - + pub fn save_note(&self, initiator: u64, id: NoteId, mut note: note::ActiveModel, content: Option, callback: F) where F: FnOnce(SaveNoteResult) + Send + 'static { let Set(collection_id) = note.collection_id else { @@ -606,9 +606,31 @@ impl BackendHandle { if let Some(note_path) = note_path { // local storage - callback(OpenExternResult::Ok((note_path, false))); + callback(OpenExternResult::Ok((PathBuf::from(note_path), false))); } else { - // TODO: copy content from db to tmp file + // get file from database and write it to a tmp file + let content_result = get_file_content(&backend.db, note_id).await; + match content_result { + Ok(Some(content)) => { + let filename = format!("file_content_{}", content.id); + let path = write_tmp_file(filename.as_str(), content.content).await; + match path { + Ok(path) => { + callback(OpenExternResult::Ok((path, true))); + }, + Err(e) => { + callback(OpenExternResult::FsErr(e)); + } + } + + }, + Ok(None) => { + callback(OpenExternResult::DbErr(DbErr::Custom("Content not found".into()))); + } + Err(e) => { + callback(OpenExternResult::DbErr(e)); + } + } } }); let _ = self.tx.send(cmd); @@ -627,7 +649,7 @@ pub enum SaveNoteResult { } pub enum OpenExternResult { - Ok((String, bool)), // path, istmp + Ok((PathBuf, bool)), // path, istmp DbErr(DbErr), FsErr(Error) } diff --git a/application/backend/src/storage.rs b/application/backend/src/storage.rs index eb71445..57ff854 100644 --- a/application/backend/src/storage.rs +++ b/application/backend/src/storage.rs @@ -28,12 +28,14 @@ use std::io::ErrorKind; use std::path::Path; -use sea_orm::{DatabaseConnection, DbErr, EntityTrait, QuerySelect, RelationTrait}; +use sea_orm::entity::prelude::*; +use sea_orm::{ColumnTrait, DatabaseConnection, DbErr, EntityTrait, QuerySelect, RelationTrait}; use tokio::fs; use tokio::fs::File; use tokio::io::AsyncWriteExt; -use entity::{collection, note, repository}; +use entity::{collection, filecontent, note, repository}; use entity::collection::LocalStorageSetting; +use entity::filecontent::Model as FileContent; use migration::JoinType; /// Checks if a collection should use local storage @@ -92,6 +94,12 @@ pub async fn get_collection_storage_path(db: &DatabaseConnection, collection_id: } } +pub async fn get_file_content(db: &DatabaseConnection, note_id: i32) -> Result, DbErr> { + filecontent::Entity::find() + .filter(filecontent::Column::NoteId.eq(note_id)) + .one(db).await +} + pub async fn write_file(path: &Path, content: &str) -> std::io::Result<()> { let mut file = match File::create(path).await { Ok(f) => f, @@ -106,4 +114,14 @@ pub async fn write_file(path: &Path, content: &str) -> std::io::Result<()> { file.write_all(content.as_bytes()).await?; Ok(()) -} \ No newline at end of file +} + +pub async fn write_tmp_file(name: &str, data: Vec) -> std::io::Result { + let path = std::env::temp_dir().join(name); + + let mut file = File::create(&path).await?; + file.write_all(&data).await?; + file.flush().await?; + + Ok(path) +} diff --git a/application/note/src/file.rs b/application/note/src/file.rs index 3a9df0f..d2c1df9 100644 --- a/application/note/src/file.rs +++ b/application/note/src/file.rs @@ -25,7 +25,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - +use std::path::PathBuf; use std::rc::Rc; use backend::backend::{BackendHandle, NoteId, OpenExternResult}; use ui_rs::{action, doc_cast, ui_actions, UiModel}; @@ -44,7 +44,7 @@ pub struct FileNote { pub id: NoteId, pub nodename: String, - pub local_path: Option, + pub local_path: Option, pub is_tmp_file: bool, pub is_opening: bool, @@ -97,8 +97,8 @@ impl FileNote { }; if let Some(path) = &self.local_path { - println!("open file: {}", path); - open_file(path.as_str()); + println!("open file: {}", path.to_string_lossy()); + open_file(path.to_string_lossy().as_ref()); } else if let NoteId::Id(note_id) = self.id { self.is_opening = true; let proxy = doc.doc_proxy(); @@ -107,8 +107,8 @@ impl FileNote { note.is_opening = false; match result { OpenExternResult::Ok((path, istmp)) => { - println!("open file: {}", path); - open_file(path.as_str()); + println!("open file: {}", path.to_string_lossy()); + open_file(path.to_string_lossy().as_ref()); note.local_path = Some(path); note.is_tmp_file = istmp; } diff --git a/entity/src/collection.rs b/entity/src/collection.rs index 858ebd2..20fd647 100644 --- a/entity/src/collection.rs +++ b/entity/src/collection.rs @@ -1,3 +1,31 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + use std::collections::HashMap; use sea_orm::entity::prelude::*; diff --git a/entity/src/filecontent.rs b/entity/src/filecontent.rs new file mode 100644 index 0000000..4630431 --- /dev/null +++ b/entity/src/filecontent.rs @@ -0,0 +1,48 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +use sea_orm::entity::prelude::*; +use sea_orm::{ActiveModelBehavior, DeriveEntityModel, DeriveRelation, EnumIter}; + +#[sea_orm::model] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "file_content")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + + #[sea_orm(unique)] + pub note_id: i32, + + pub content: Vec, + + #[sea_orm(belongs_to, from = "note_id", to = "note_id")] + pub note: HasOne +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/entity/src/lib.rs b/entity/src/lib.rs index 1b9a694..0fc36c5 100644 --- a/entity/src/lib.rs +++ b/entity/src/lib.rs @@ -3,4 +3,5 @@ pub mod profile; pub mod collection; pub mod note; pub mod notecontent; -pub mod repository; \ No newline at end of file +pub mod repository; +pub mod filecontent; \ No newline at end of file diff --git a/entity/src/note.rs b/entity/src/note.rs index 9cf3278..8df1f1a 100644 --- a/entity/src/note.rs +++ b/entity/src/note.rs @@ -1,5 +1,32 @@ use sea_orm::entity::prelude::*; +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #[sea_orm::model] #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] @@ -19,9 +46,6 @@ pub struct Model { #[sea_orm(belongs_to, from = "collection_id", to = "collection_id")] pub repository: HasOne, - #[sea_orm(has_one)] - pub content: HasOne, - pub version: i64 } diff --git a/entity/src/notecontent.rs b/entity/src/notecontent.rs index 0396da1..8bf7841 100644 --- a/entity/src/notecontent.rs +++ b/entity/src/notecontent.rs @@ -1,3 +1,31 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + use sea_orm::entity::prelude::*; use sea_orm::{ActiveModelBehavior, DeriveEntityModel, DeriveRelation, EnumIter}; diff --git a/entity/src/profile.rs b/entity/src/profile.rs index 660ebc2..ec70965 100644 --- a/entity/src/profile.rs +++ b/entity/src/profile.rs @@ -1,3 +1,31 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] diff --git a/entity/src/repository.rs b/entity/src/repository.rs index 17ed22b..b7df46e 100644 --- a/entity/src/repository.rs +++ b/entity/src/repository.rs @@ -1,3 +1,31 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + use sea_orm::entity::prelude::*; diff --git a/ui-rs/src/ui/toolkit.rs b/ui-rs/src/ui/toolkit.rs index 5012b57..001dd9b 100644 --- a/ui-rs/src/ui/toolkit.rs +++ b/ui-rs/src/ui/toolkit.rs @@ -296,7 +296,7 @@ impl UiDoc { pub fn new_from_box2(data: Box, init: F) -> UiDoc where F: FnOnce(&mut T, &UiDoc) { unsafe { - let doc = ui_document_new(10000 + mem::size_of::<*mut Box>()); + let doc = ui_document_new(mem::size_of::<*mut Box>()); let ctx = UiContext::from_ptr(ui_document_context(doc)); ui_app_ref(); ui_reg_destructor(ctx.ptr, std::ptr::null_mut(), doc_app_unref);