use std::io::{Error, ErrorKind};
use std::path::{Path, PathBuf};
use std::pin::Pin;
-use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, EntityTrait, QueryFilter, ColumnTrait, Set, QueryOrder, DbErr, ExprTrait, QuerySelect};
+use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, EntityTrait, QueryFilter, ColumnTrait, Set, QueryOrder, DbErr, ExprTrait, QuerySelect, NotSet};
use tokio::runtime::Runtime;
use std::sync::{Arc};
use std::thread::JoinHandle;
use std::time::SystemTime;
use notify::Event;
+use sea_orm::prelude::DateTimeWithTimeZone;
use tokio::fs;
use tokio::sync::{broadcast, mpsc};
use tokio::sync::broadcast::error::SendError;
use migration::{Expr, Migrator, MigratorTrait};
-use entity::{attachment, collection, filecontent, note, notecontent, profile, repository};
+use entity::{attachment, attachmentcontent, collection, filecontent, note, notecontent, profile, repository};
use entity::profile::Entity as Profile;
use entity::collection::{create_notebook_hierarchy, CollectionType, Entity as Collection, Node};
use entity::note::{Column, Entity as Note, NoteType};
let _ = self.tx.send(cmd);
}
+ pub fn add_note_attachment<F>(&self, note_id: i32, path: &Path, callback: F)
+ where F: FnOnce(Result<(attachment::Model, attachmentcontent::Model), DbErr>) + Send + 'static {
+ let backend = self.backend.clone();
+ let pathbuf = path.to_path_buf();
+ let name = pathbuf.file_name();
+ let Some(name) = pathbuf.file_name() else {
+ callback(Err(DbErr::Custom("invalid path".to_string())));
+ return;
+ };
+ let file_name = name.to_string_lossy().to_string();
+ let cmd = Box::pin(async move {
+ let result = async {
+ let collection_id = note::Entity::find_by_id(note_id)
+ .select_only()
+ .column(note::Column::CollectionId)
+ .into_tuple::<i32>()
+ .one(&backend.db).await?.ok_or(DbErr::Custom("note not found".to_string()))?;
+
+ let now: DateTimeWithTimeZone = Utc::now().into();
+ let new_attachment = attachment::ActiveModel {
+ attachment_id: Default::default(),
+ note_id: Set(note_id),
+ collection_id: Set(collection_id),
+ nodename: Set(file_name.clone()),
+ title: Set(file_name.clone()),
+ content_type: Set(nodename_to_contenttype(file_name.as_str()).to_string()),
+ lastmodified: Set(now.clone()),
+ created: Set(now),
+ };
+ let attachment = new_attachment.insert(&backend.db).await?;
+
+ let content = fs::read(pathbuf).await.map_err(|e| DbErr::Custom(e.to_string()))?;
+ let new_attachment_content = attachmentcontent::ActiveModel {
+ id: Default::default(),
+ attachment_id: Set(attachment.attachment_id),
+ content: Set(content)
+ };
+ let attachment_content = new_attachment_content.insert(&backend.db).await?;
+
+ Ok((attachment, attachment_content))
+ }.await;
+ callback(result);
+ });
+ let _ = self.tx.send(cmd);
+ }
+
pub fn open_extern<F>(&self, note_id: i32, callback: F)
where F: FnOnce(OpenExternResult) + Send + 'static {
let backend = self.backend.clone();