dnd works in library now too
Some checks failed
/ test (push) Has been cancelled

This commit is contained in:
Chris Cochrun 2025-10-02 15:15:33 -05:00
parent 894c68338d
commit 7f30b4395f
2 changed files with 190 additions and 89 deletions

View file

@ -1,4 +1,4 @@
use std::{error::Error, fmt::Display}; use std::{error::Error, fmt::Display, path::PathBuf};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -21,6 +21,29 @@ pub enum ServiceItemKind {
Content(Slide), Content(Slide),
} }
impl TryFrom<PathBuf> for ServiceItemKind {
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::Image(Image::from(path)))
}
"mp4" | "mkv" | "webm" => {
Ok(Self::Video(Video::from(path)))
}
_ => Err(miette::miette!("Unknown item")),
}
}
}
impl ServiceItemKind { impl ServiceItemKind {
pub fn title(&self) -> String { pub fn title(&self) -> String {
match self { match self {

View file

@ -31,7 +31,7 @@ use crate::core::{
self, Presentation, add_presentation_to_db, self, Presentation, add_presentation_to_db,
update_presentation_in_db, update_presentation_in_db,
}, },
service_items::{ServiceItem, ServiceTrait}, service_items::ServiceItem,
songs::{self, Song, update_song_in_db}, songs::{self, Song, update_song_in_db},
videos::{self, Video, update_video_in_db}, videos::{self, Video, update_video_in_db},
}; };
@ -100,6 +100,7 @@ pub enum Message {
Error(String), Error(String),
OpenContext(i32), OpenContext(i32),
None, None,
AddFiles(Vec<ServiceItemKind>),
AddImages(Option<Vec<Image>>), AddImages(Option<Vec<Image>>),
AddVideos(Option<Vec<Video>>), AddVideos(Option<Vec<Video>>),
AddPresentations(Option<Vec<Presentation>>), AddPresentations(Option<Vec<Presentation>>),
@ -210,35 +211,35 @@ impl<'a> Library {
error!(?e); error!(?e);
} }
let task = Task::future( let task = Task::future(
self.db.acquire(), self.db.acquire(),
) )
.and_then(move |db| { .and_then(move |db| {
Task::perform( Task::perform(
add_presentation_to_db( add_presentation_to_db(
presentation.to_owned(), presentation.to_owned(),
db, db,
index as i32, index as i32,
), ),
move |res| { move |res| {
debug!( debug!(
len, len,
index, "added to db" index, "added to db"
); );
if let Err(e) = res { if let Err(e) = res {
error!(?e); error!(?e);
} }
if len == index { if len == index {
debug!("open the pres"); debug!("open the pres");
Message::OpenItem(Some(( Message::OpenItem(Some((
LibraryKind::Presentation, LibraryKind::Presentation,
index as i32, index as i32,
))) )))
} else { } else {
Message::None Message::None
} }
}, },
) )
}); });
tasks.push(task); tasks.push(task);
index += 1; index += 1;
} }
@ -517,30 +518,30 @@ impl<'a> Library {
} }
match self match self
.presentation_library .presentation_library
.update_item(presentation.clone(), index) .update_item(presentation.clone(), index)
{ {
Ok(()) => return Action::Task( Ok(()) => return Action::Task(
Task::future(self.db.acquire()).and_then( Task::future(self.db.acquire()).and_then(
move |conn| { move |conn| {
Task::perform( Task::perform(
update_presentation_in_db( update_presentation_in_db(
presentation.clone(), presentation.clone(),
conn, conn,
), ),
|r| match r { |r| match r {
Ok(_) => Message::PresentationChanged, Ok(_) => Message::PresentationChanged,
Err(e) => { Err(e) => {
error!(?e); error!(?e);
Message::None Message::None
} }
},
)
}, },
) ),
}, ),
), Err(_) => todo!(),
), }
Err(_) => todo!(),
}
} }
Message::PresentationChanged => (), Message::PresentationChanged => (),
Message::Error(_) => (), Message::Error(_) => (),
@ -561,6 +562,55 @@ impl<'a> Library {
self.selected_items = Some(items.to_vec()); self.selected_items = Some(items.to_vec());
self.context_menu = Some(index); self.context_menu = Some(index);
} }
Message::AddFiles(items) => {
for item in items {
match item {
ServiceItemKind::Song(song) => {
let Some(e) = self
.song_library
.add_item(song)
.err()
else {
continue;
};
error!(?e);
}
ServiceItemKind::Video(video) => {
let Some(e) = self
.video_library
.add_item(video)
.err()
else {
continue;
};
error!(?e);
}
ServiceItemKind::Image(image) => {
let Some(e) = self
.image_library
.add_item(image)
.err()
else {
continue;
};
error!(?e);
}
ServiceItemKind::Presentation(
presentation,
) => {
let Some(e) = self
.presentation_library
.add_item(presentation)
.err()
else {
continue;
};
error!(?e);
}
ServiceItemKind::Content(slide) => todo!(),
}
}
}
} }
Action::None Action::None
} }
@ -572,7 +622,7 @@ impl<'a> Library {
let presentation_library = let presentation_library =
self.library_item(&self.presentation_library); self.library_item(&self.presentation_library);
column![ let library_column = column![
text::heading("Library").center().width(Length::Fill), text::heading("Library").center().width(Length::Fill),
cosmic::iced::widget::horizontal_rule(1), cosmic::iced::widget::horizontal_rule(1),
song_library, song_library,
@ -582,8 +632,67 @@ impl<'a> Library {
] ]
.height(Length::Fill) .height(Length::Fill)
.padding(10) .padding(10)
.spacing(10) .spacing(10);
.into() let library_dnd = dnd_destination(
library_column,
vec![
"image/png".into(),
"image/jpg".into(),
"image/heif".into(),
"image/gif".into(),
"video/mp4".into(),
"video/AV1".into(),
"video/H264".into(),
"video/H265".into(),
"video/mpeg".into(),
"video/mkv".into(),
"video/webm".into(),
"video/ogg".into(),
"video/vnd.youtube.yt".into(),
"video/x-matroska".into(),
"application/pdf".into(),
"text/html".into(),
"text/md".into(),
"text/org".into(),
"text/uri-list".into(),
],
)
.on_enter(|_, _, mimes| {
warn!(?mimes);
Message::None
})
.on_finish(|mime, data, action, _, _| {
// warn!(?mime, ?data, ?action);
match mime.as_str() {
"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 = ServiceItemKind::try_from(path);
match item {
Ok(item) => items.push(item),
Err(e) => error!(?e),
}
}
Message::AddFiles(items)
}
_ => Message::None,
}
});
container(library_dnd).padding(2).into()
} }
pub fn library_item<T>( pub fn library_item<T>(
@ -767,38 +876,7 @@ impl<'a> Library {
); );
let library_column = let library_column =
column![library_toolbar, items].spacing(3); column![library_toolbar, items].spacing(3);
let library_dnd = dnd_destination( Container::new(library_column).padding(5)
library_column,
vec![
"image/png".into(),
"image/jpg".into(),
"image/heif".into(),
"image/gif".into(),
"video/mp4".into(),
"video/AV1".into(),
"video/H264".into(),
"video/H265".into(),
"video/mpeg".into(),
"video/mkv".into(),
"video/webm".into(),
"video/ogg".into(),
"video/vnd.youtube.yt".into(),
"video/x-matroska".into(),
"application/pdf".into(),
"text/html".into(),
"text/md".into(),
"text/org".into(),
],
)
.on_enter(|_, _, mimes| {
warn!(?mimes);
Message::None
})
.on_finish(|mime, data, action, _, _| {
warn!(?mime, ?data, ?action);
Message::None
});
Container::new(library_dnd).padding(5)
} else { } else {
Container::new(Space::new(0, 0)) Container::new(Space::new(0, 0))
}; };