diff --git a/src/core/model.rs b/src/core/model.rs index 62c6d84..2ebf1b4 100644 --- a/src/core/model.rs +++ b/src/core/model.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, mem::replace}; +use std::{borrow::Cow, mem::replace, path::{Path, PathBuf}}; use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes}; use miette::{IntoDiagnostic, Result, miette}; @@ -23,18 +23,29 @@ pub enum LibraryKind { } #[derive( - Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize, + Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, )] pub struct KindWrapper(pub (LibraryKind, i32)); +impl From for LibraryKind { + fn from(value: PathBuf) -> Self { + todo!() + } +} + impl TryFrom<(Vec, String)> for KindWrapper { type Error = miette::Error; fn try_from( value: (Vec, String), ) -> std::result::Result { - debug!(?value); - ron::de::from_bytes(&value.0).into_diagnostic() + let (data, mime) = value; + match mime.as_str() { + "application/service-item" => { + ron::de::from_bytes(&data).into_diagnostic() + } + _ => Err(miette!("Wrong mime type: {mime}")) + } } } diff --git a/src/core/service_items.rs b/src/core/service_items.rs index dba027c..250d16d 100644 --- a/src/core/service_items.rs +++ b/src/core/service_items.rs @@ -1,10 +1,11 @@ use std::borrow::Cow; use std::cmp::Ordering; use std::ops::Deref; +use std::path::PathBuf; use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes}; use crisp::types::{Keyword, Symbol, Value}; -use miette::{IntoDiagnostic, Result}; +use miette::{IntoDiagnostic, Result, miette}; use serde::{Deserialize, Serialize}; use tracing::{debug, error}; @@ -48,13 +49,8 @@ impl TryFrom<(Vec, String)> for ServiceItem { value: (Vec, String), ) -> std::result::Result { let (data, mime) = value; - match mime.as_str() { - "application/service_item" => {} - "text/uri-list" => {} - "x-special/gnome-copied-files" => {} - } - debug!(?value); - ron::de::from_bytes(&value.0).into_diagnostic() + debug!(?mime); + ron::de::from_bytes(&data).into_diagnostic() } } @@ -86,6 +82,29 @@ impl AsMimeTypes for ServiceItem { } } +impl TryFrom for ServiceItem { + type Error = miette::Error; + + fn try_from(path: PathBuf) -> Result { + let ext = path + .extension() + .map(|ext| ext.to_str()) + .flatten() + .ok_or(miette::miette!( + "There isn't an extension on this file" + ))?; + match ext { + "png" | "jpg" | "jpeg" => { + Ok(Self::from(&Image::from(path))) + } + "mp4" | "mkv" | "webm" => { + Ok(Self::from(&Video::from(path))) + } + _ => Err(miette!("Unkown service item")), + } + } +} + impl From<&ServiceItem> for Value { fn from(value: &ServiceItem) -> Self { match &value.kind { diff --git a/src/main.rs b/src/main.rs index 5192bf3..82cad1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -167,6 +167,7 @@ enum Message { AddSelectServiceItem(usize), HoveredServiceItem(Option), AddServiceItem(usize, KindWrapper), + AddServiceItemsFiles(usize, Vec), RemoveServiceItem(usize), AddServiceItemDrop(usize), AppendServiceItem(ServiceItem), @@ -1231,6 +1232,13 @@ impl cosmic::Application for App { self.presenter.update_items(self.service.clone()); Task::none() } + Message::AddServiceItemsFiles(index, items) => { + for item in items { + self.service.insert(index, item); + } + self.presenter.update_items(self.service.clone()); + Task::none() + } Message::RemoveServiceItem(index) => { self.service.remove(index); self.presenter.update_items(self.service.clone()); @@ -1786,17 +1794,44 @@ where .gap(cosmic::theme::spacing().space_xs); dnd_destination( tooltip, - vec!["application/service-item".into()], + vec!["application/service-item".into(), "text/uri-list".into(), "x-special/gnome-copied-files".into()], ) .on_finish(move |mime, data, _, _, _| { - let Ok(item) = - KindWrapper::try_from((data, mime)) - else { - error!("couldn't drag in Service item"); - return Message::None; - }; - debug!(?item, index, "adding Service item"); - Message::AddServiceItem(index, item) + match mime.as_str() { + "application/service-item" => { + let Ok(item) = + KindWrapper::try_from((data, mime)) + else { + error!("couldn't drag in Service item"); + return Message::None; + }; + debug!(?item, index, "adding Service item"); + Message::AddServiceItem(index, item) + } + "text/uri-list" => { + let Ok(text) = str::from_utf8(&data) else { + return Message::None; + }; + let mut items = Vec::new(); + for line in text.lines() { + let Ok(url) = url::Url::parse(line) else { + error!(?line, "problem parsing this file url"); + continue; + }; + let Ok(path) = url.to_file_path() else { + error!(?url, "invalid file URL"); + continue; + }; + let item = ServiceItem::try_from(path); + match item { + Ok(item) => items.push(item), + Err(e) => error!(?e), + } + } + Message::AddServiceItemsFiles(index, items) + } + _ => Message::None + } }) .into() });