dnd now works for files in service items
Some checks are pending
/ test (push) Waiting to run

This commit is contained in:
Chris Cochrun 2025-10-02 13:10:55 -05:00
parent f9f3f7f95f
commit 20843f1b2c
3 changed files with 86 additions and 21 deletions

View file

@ -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<PathBuf> for LibraryKind {
fn from(value: PathBuf) -> Self {
todo!()
}
}
impl TryFrom<(Vec<u8>, String)> for KindWrapper {
type Error = miette::Error;
fn try_from(
value: (Vec<u8>, String),
) -> std::result::Result<Self, Self::Error> {
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}"))
}
}
}

View file

@ -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<u8>, String)> for ServiceItem {
value: (Vec<u8>, String),
) -> std::result::Result<Self, Self::Error> {
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<PathBuf> for ServiceItem {
type Error = miette::Error;
fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
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 {

View file

@ -167,6 +167,7 @@ enum Message {
AddSelectServiceItem(usize),
HoveredServiceItem(Option<usize>),
AddServiceItem(usize, KindWrapper),
AddServiceItemsFiles(usize, Vec<ServiceItem>),
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,9 +1794,11 @@ 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, _, _, _| {
match mime.as_str() {
"application/service-item" => {
let Ok(item) =
KindWrapper::try_from((data, mime))
else {
@ -1797,6 +1807,31 @@ where
};
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()
});