]> uap-core.de Git - note.git/commitdiff
add file extension to nodename
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 13 Jul 2026 17:47:56 +0000 (19:47 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 13 Jul 2026 17:47:56 +0000 (19:47 +0200)
application/backend/src/backend.rs
application/backend/src/lib.rs
application/backend/src/lockmanager.rs
application/backend/src/note.rs [new file with mode: 0644]
application/backend/src/storage.rs

index 89d3699389f223f9b02260b42cd3844b9262e69d..0550be814dc14b2643f17e40d9ec6d05fb99b11c 100644 (file)
@@ -48,6 +48,7 @@ use entity::note::{Column, Entity as Note};
 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};
 
 pub struct Backend {
@@ -447,12 +448,18 @@ impl BackendHandle {
             callback(SaveNoteResult::ValidationError("title not set"));
             return;
         };
+        let Set(kind) = &note.kind else {
+            callback(SaveNoteResult::ValidationError("note type not set"));
+            return;
+        };
 
         let mut nodename = if let Set(nn) = &note.nodename {
             nn.clone()
         } else {
             // generate nodename from title
-            title.clone()
+            let nodename = create_nodename(title, kind);
+            note.nodename = Set(nodename.clone());
+            nodename
         };
 
         let bhandle = self.clone();
@@ -512,12 +519,7 @@ impl BackendHandle {
                         // collection+name unique constraint.
                         // Generate a random suffix and try it again
 
-                        let suffix: String = rand::rng()
-                            .sample_iter(Alphanumeric)
-                            .take(6)
-                            .map(char::from)
-                            .collect();
-                        let new_nodename = nodename + "-" + suffix.as_str();
+                        let new_nodename = randomize_nodename(nodename.as_str());
                         note.nodename = Set(new_nodename.clone());
                         nodename = new_nodename;
                         let result = note.clone().insert(&bhandle.backend.db).await;
index c781e3665d8a00a8d26d1d563b2902429dc16756..4eed8cd63908bc154dbfcb2fbfc3856bdedaebc7 100644 (file)
@@ -1,3 +1,4 @@
 pub mod backend;
 pub mod lockmanager;
-pub mod storage;
\ No newline at end of file
+pub mod storage;
+mod note;
\ No newline at end of file
index 77466644e9a7b707386fd8f602006995e54c7db0..bc7f6a4837ce8c108bd34f46658dab9bb91aab33 100644 (file)
@@ -25,6 +25,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+
 use std::collections::{HashSet};
 use std::sync::Arc;
 
diff --git a/application/backend/src/note.rs b/application/backend/src/note.rs
new file mode 100644 (file)
index 0000000..bd2e32d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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::path::Path;
+use rand::distr::Alphanumeric;
+use rand::RngExt;
+use entity::note::NoteType;
+
+pub fn notetype2ext(t: &NoteType) -> &'static str {
+    match t {
+        NoteType::PlainTextNote => { ".txt" }
+        NoteType::MDTextNote => { ".md" }
+    }
+}
+
+pub fn create_nodename(title: &str, kind: &NoteType) -> String {
+    format!("{}{}", title, notetype2ext(kind))
+}
+
+pub fn randomize_nodename(nodename: &str) -> String {
+    let suffix: String = rand::rng()
+        .sample_iter(Alphanumeric)
+        .take(6)
+        .map(char::from)
+        .collect();
+
+    let path = Path::new(nodename);
+    let stem = path
+        .file_stem()
+        .and_then(|s| s.to_str())
+        .unwrap_or(nodename);
+
+    match path.extension().and_then(|e| e.to_str()) {
+        Some(ext) => format!("{stem}-{suffix}.{ext}"),
+        None => format!("{stem}_{suffix}"),
+    }
+}
index df6a1879a88e9e4b5c7db0d128aaffd80bd09fac..eb714451bb9f53a368d34e282e14d154907ca3ea 100644 (file)
@@ -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::io::ErrorKind;
 use std::path::Path;
 use sea_orm::{DatabaseConnection, DbErr, EntityTrait, QuerySelect, RelationTrait};