Compare commits
2 commits
3b1a0c4207
...
761006f516
| Author | SHA1 | Date | |
|---|---|---|---|
| 761006f516 | |||
| 46abd9dd7a |
20 changed files with 228 additions and 265 deletions
|
|
@ -10,8 +10,8 @@ use crisp::types::{Keyword, Symbol, Value};
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
pool::PoolConnection, query, query_as, Sqlite, SqliteConnection,
|
Sqlite, SqliteConnection, SqlitePool, pool::PoolConnection,
|
||||||
SqlitePool,
|
query, query_as,
|
||||||
};
|
};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
@ -211,7 +211,7 @@ pub async fn update_image_in_db(
|
||||||
.map(std::string::ToString::to_string)
|
.map(std::string::ToString::to_string)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let mut db = db.detach();
|
let mut db = db.detach();
|
||||||
let id = image.id.clone();
|
let id = image.id;
|
||||||
if let Err(e) = query!("SELECT id FROM images where id = $1", id)
|
if let Err(e) = query!("SELECT id FROM images where id = $1", id)
|
||||||
.fetch_one(&mut db)
|
.fetch_one(&mut db)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
|
||||||
use miette::{miette, Result};
|
use miette::{Result, miette};
|
||||||
use sqlx::{Connection, SqliteConnection};
|
use sqlx::{Connection, SqliteConnection};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ use miette::{IntoDiagnostic, Result};
|
||||||
use mupdf::{Colorspace, Document, Matrix};
|
use mupdf::{Colorspace, Document, Matrix};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
pool::PoolConnection, prelude::FromRow, query, sqlite::SqliteRow,
|
Row, Sqlite, SqliteConnection, SqlitePool, pool::PoolConnection,
|
||||||
Row, Sqlite, SqliteConnection, SqlitePool,
|
prelude::FromRow, query, sqlite::SqliteRow,
|
||||||
};
|
};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
@ -318,7 +318,7 @@ pub async fn update_presentation_in_db(
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let html = presentation.kind == PresKind::Html;
|
let html = presentation.kind == PresKind::Html;
|
||||||
let mut db = db.detach();
|
let mut db = db.detach();
|
||||||
let id = presentation.id.clone();
|
let id = presentation.id;
|
||||||
if let Err(e) =
|
if let Err(e) =
|
||||||
query!("SELECT id FROM presentations where id = $1", id)
|
query!("SELECT id FROM presentations where id = $1", id)
|
||||||
.fetch_one(&mut db)
|
.fetch_one(&mut db)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::Slide;
|
||||||
|
|
||||||
use super::images::Image;
|
use super::images::Image;
|
||||||
use super::presentations::Presentation;
|
use super::presentations::Presentation;
|
||||||
use super::songs::{lisp_to_song, Song};
|
use super::songs::{Song, lisp_to_song};
|
||||||
use super::videos::Video;
|
use super::videos::Video;
|
||||||
|
|
||||||
use super::kinds::ServiceItemKind;
|
use super::kinds::ServiceItemKind;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use cosmic::widget::image::Handle;
|
||||||
// use cosmic::dialog::ashpd::url::Url;
|
// use cosmic::dialog::ashpd::url::Url;
|
||||||
use crisp::types::{Keyword, Symbol, Value};
|
use crisp::types::{Keyword, Symbol, Value};
|
||||||
use iced_video_player::Video;
|
use iced_video_player::Video;
|
||||||
use miette::{miette, Result};
|
use miette::{Result, miette};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
use std::{collections::HashMap, option::Option, path::PathBuf};
|
use std::{collections::HashMap, option::Option, path::PathBuf};
|
||||||
|
|
||||||
use crisp::types::{Keyword, Symbol, Value};
|
use crisp::types::{Keyword, Symbol, Value};
|
||||||
use miette::{miette, IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result, miette};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
pool::PoolConnection, query, sqlite::SqliteRow, Acquire, FromRow,
|
Acquire, FromRow, Row, Sqlite, SqliteConnection, SqlitePool,
|
||||||
Row, Sqlite, SqliteConnection, SqlitePool,
|
pool::PoolConnection, query, sqlite::SqliteRow,
|
||||||
};
|
};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::{core::slide, Slide, SlideBuilder};
|
use crate::{Slide, SlideBuilder, core::slide};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
content::Content,
|
content::Content,
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use crisp::types::{Keyword, Symbol, Value};
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
pool::PoolConnection, query, query_as, Sqlite, SqliteConnection,
|
Sqlite, SqliteConnection, SqlitePool, pool::PoolConnection,
|
||||||
SqlitePool,
|
query, query_as,
|
||||||
};
|
};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
@ -246,7 +246,7 @@ pub async fn update_video_in_db(
|
||||||
.map(std::string::ToString::to_string)
|
.map(std::string::ToString::to_string)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let mut db = db.detach();
|
let mut db = db.detach();
|
||||||
let id = video.id.clone();
|
let id = video.id;
|
||||||
if let Err(e) = query!("SELECT id FROM videos where id = $1", id)
|
if let Err(e) = query!("SELECT id FROM videos where id = $1", id)
|
||||||
.fetch_one(&mut db)
|
.fetch_one(&mut db)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,11 @@ mod test {
|
||||||
use std::{fs::read_to_string, path::PathBuf};
|
use std::{fs::read_to_string, path::PathBuf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
Background, TextAlignment,
|
||||||
core::{
|
core::{
|
||||||
images::Image, kinds::ServiceItemKind,
|
images::Image, kinds::ServiceItemKind,
|
||||||
service_items::ServiceTrait, songs::Song, videos::Video,
|
service_items::ServiceTrait, songs::Song, videos::Video,
|
||||||
},
|
},
|
||||||
Background, TextAlignment,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
29
src/main.rs
29
src/main.rs
|
|
@ -1,4 +1,4 @@
|
||||||
use clap::{command, Parser};
|
use clap::{Parser, command};
|
||||||
use core::service_items::ServiceItem;
|
use core::service_items::ServiceItem;
|
||||||
use core::slide::{
|
use core::slide::{
|
||||||
Background, BackgroundKind, Slide, SlideBuilder, TextAlignment,
|
Background, BackgroundKind, Slide, SlideBuilder, TextAlignment,
|
||||||
|
|
@ -9,8 +9,8 @@ use cosmic::iced::alignment::Vertical;
|
||||||
use cosmic::iced::keyboard::{Key, Modifiers};
|
use cosmic::iced::keyboard::{Key, Modifiers};
|
||||||
use cosmic::iced::window::{Mode, Position};
|
use cosmic::iced::window::{Mode, Position};
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
self, event, window, Background as IcedBackground, Border, Color,
|
self, Background as IcedBackground, Border, Color, Length, event,
|
||||||
Length,
|
window,
|
||||||
};
|
};
|
||||||
use cosmic::iced_core::text::Wrapping;
|
use cosmic::iced_core::text::Wrapping;
|
||||||
use cosmic::iced_futures::Subscription;
|
use cosmic::iced_futures::Subscription;
|
||||||
|
|
@ -21,18 +21,18 @@ use cosmic::widget::menu::key_bind::Modifier;
|
||||||
use cosmic::widget::menu::{ItemWidth, KeyBind};
|
use cosmic::widget::menu::{ItemWidth, KeyBind};
|
||||||
use cosmic::widget::nav_bar::nav_bar_style;
|
use cosmic::widget::nav_bar::nav_bar_style;
|
||||||
use cosmic::widget::tooltip::Position as TPosition;
|
use cosmic::widget::tooltip::Position as TPosition;
|
||||||
|
use cosmic::widget::{Container, menu};
|
||||||
use cosmic::widget::{
|
use cosmic::widget::{
|
||||||
button, context_menu, horizontal_space, mouse_area, nav_bar,
|
Space, button, context_menu, horizontal_space, mouse_area,
|
||||||
nav_bar_toggle, responsive, scrollable, search_input, tooltip,
|
nav_bar, nav_bar_toggle, responsive, scrollable, search_input,
|
||||||
vertical_space, Space,
|
tooltip, vertical_space,
|
||||||
};
|
};
|
||||||
use cosmic::widget::{container, text};
|
use cosmic::widget::{container, text};
|
||||||
use cosmic::widget::{icon, slider};
|
use cosmic::widget::{icon, slider};
|
||||||
use cosmic::widget::{menu, Container};
|
use cosmic::{Application, ApplicationExt, Element, executor};
|
||||||
use cosmic::{executor, Application, ApplicationExt, Element};
|
|
||||||
use crisp::types::Value;
|
use crisp::types::Value;
|
||||||
use lisp::parse_lisp;
|
use lisp::parse_lisp;
|
||||||
use miette::{miette, Result};
|
use miette::{Result, miette};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use resvg::usvg::fontdb;
|
use resvg::usvg::fontdb;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -42,10 +42,10 @@ use std::sync::Arc;
|
||||||
use tracing::{debug, level_filters::LevelFilter};
|
use tracing::{debug, level_filters::LevelFilter};
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
use ui::EditorMode;
|
||||||
use ui::library::{self, Library};
|
use ui::library::{self, Library};
|
||||||
use ui::presenter::{self, Presenter};
|
use ui::presenter::{self, Presenter};
|
||||||
use ui::song_editor::{self, SongEditor};
|
use ui::song_editor::{self, SongEditor};
|
||||||
use ui::EditorMode;
|
|
||||||
|
|
||||||
use crate::core::kinds::ServiceItemKind;
|
use crate::core::kinds::ServiceItemKind;
|
||||||
use crate::ui::image_editor::{self, ImageEditor};
|
use crate::ui::image_editor::{self, ImageEditor};
|
||||||
|
|
@ -765,7 +765,7 @@ impl cosmic::Application for App {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
song_editor::Action::UpdateSong(song) => {
|
song_editor::Action::UpdateSong(song) => {
|
||||||
if let Some(_) = &mut self.library {
|
if self.library.is_some() {
|
||||||
self.update(Message::Library(
|
self.update(Message::Library(
|
||||||
library::Message::UpdateSong(song),
|
library::Message::UpdateSong(song),
|
||||||
))
|
))
|
||||||
|
|
@ -786,7 +786,7 @@ impl cosmic::Application for App {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
image_editor::Action::UpdateImage(image) => {
|
image_editor::Action::UpdateImage(image) => {
|
||||||
if let Some(_) = &mut self.library {
|
if self.library.is_some() {
|
||||||
self.update(Message::Library(
|
self.update(Message::Library(
|
||||||
library::Message::UpdateImage(image),
|
library::Message::UpdateImage(image),
|
||||||
))
|
))
|
||||||
|
|
@ -807,7 +807,7 @@ impl cosmic::Application for App {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
video_editor::Action::UpdateVideo(video) => {
|
video_editor::Action::UpdateVideo(video) => {
|
||||||
if let Some(_) = &mut self.library {
|
if self.library.is_some() {
|
||||||
self.update(Message::Library(
|
self.update(Message::Library(
|
||||||
library::Message::UpdateVideo(video),
|
library::Message::UpdateVideo(video),
|
||||||
))
|
))
|
||||||
|
|
@ -1732,8 +1732,7 @@ where
|
||||||
moved_item_overlay: Color::from(
|
moved_item_overlay: Color::from(
|
||||||
t.cosmic().primary.base,
|
t.cosmic().primary.base,
|
||||||
)
|
)
|
||||||
.scale_alpha(0.2)
|
.scale_alpha(0.2),
|
||||||
.into(),
|
|
||||||
ghost_border: Border {
|
ghost_border: Border {
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
color: t.cosmic().secondary.base.into(),
|
color: t.cosmic().secondary.base.into(),
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@ use std::{io, path::PathBuf};
|
||||||
|
|
||||||
use crate::core::images::Image;
|
use crate::core::images::Image;
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
dialog::file_chooser::{open::Dialog, FileFilter},
|
Element, Task,
|
||||||
iced::{alignment::Vertical, Length},
|
dialog::file_chooser::{FileFilter, open::Dialog},
|
||||||
|
iced::{Length, alignment::Vertical},
|
||||||
iced_widget::{column, row},
|
iced_widget::{column, row},
|
||||||
theme,
|
theme,
|
||||||
widget::{
|
widget::{
|
||||||
self, button, container, horizontal_space, icon, text,
|
self, Space, button, container, horizontal_space, icon, text,
|
||||||
text_input, Space,
|
text_input,
|
||||||
},
|
},
|
||||||
Element, Task,
|
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
|
|
@ -73,8 +73,7 @@ impl ImageEditor {
|
||||||
.image
|
.image
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.id)
|
.map(|v| v.id)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default();
|
||||||
.clone();
|
|
||||||
let task = Task::perform(
|
let task = Task::perform(
|
||||||
pick_image(),
|
pick_image(),
|
||||||
move |image_result| {
|
move |image_result| {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ use cosmic::{
|
||||||
dialog::file_chooser::open::Dialog,
|
dialog::file_chooser::open::Dialog,
|
||||||
iced::{
|
iced::{
|
||||||
alignment::Vertical, clipboard::dnd::DndAction,
|
alignment::Vertical, clipboard::dnd::DndAction,
|
||||||
futures::FutureExt, keyboard::Modifiers, Background, Border,
|
keyboard::Modifiers, Background, Border, Color, Length,
|
||||||
Color, Length,
|
|
||||||
},
|
},
|
||||||
iced_core::widget::tree::State,
|
iced_core::widget::tree::State,
|
||||||
iced_widget::{column, row as rowm, text as textm},
|
iced_widget::{column, row as rowm, text as textm},
|
||||||
|
|
@ -19,7 +18,7 @@ use cosmic::{
|
||||||
},
|
},
|
||||||
Element, Task,
|
Element, Task,
|
||||||
};
|
};
|
||||||
use miette::{miette, IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use rapidfuzz::distance::levenshtein;
|
use rapidfuzz::distance::levenshtein;
|
||||||
use sqlx::{migrate, SqlitePool};
|
use sqlx::{migrate, SqlitePool};
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
@ -53,8 +52,8 @@ pub struct Library {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Copy)]
|
#[derive(Debug, Clone, Eq, PartialEq, Copy)]
|
||||||
enum MenuMessage {
|
enum MenuMessage {
|
||||||
Delete((LibraryKind, i32)),
|
Delete,
|
||||||
Open,
|
Open((LibraryKind, i32)),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MenuAction for MenuMessage {
|
impl MenuAction for MenuMessage {
|
||||||
|
|
@ -62,10 +61,10 @@ impl MenuAction for MenuMessage {
|
||||||
|
|
||||||
fn message(&self) -> Self::Message {
|
fn message(&self) -> Self::Message {
|
||||||
match self {
|
match self {
|
||||||
MenuMessage::Delete((kind, index)) => {
|
MenuMessage::Delete => Message::DeleteItem,
|
||||||
Message::DeleteItem((*kind, *index))
|
MenuMessage::Open((kind, index)) => {
|
||||||
|
Message::OpenItem(Some((*kind, *index)))
|
||||||
}
|
}
|
||||||
MenuMessage::Open => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +79,7 @@ pub enum Action {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
AddItem,
|
AddItem,
|
||||||
DeleteItem((LibraryKind, i32)),
|
DeleteItem,
|
||||||
OpenItem(Option<(LibraryKind, i32)>),
|
OpenItem(Option<(LibraryKind, i32)>),
|
||||||
HoverLibrary(Option<LibraryKind>),
|
HoverLibrary(Option<LibraryKind>),
|
||||||
OpenLibrary(Option<LibraryKind>),
|
OpenLibrary(Option<LibraryKind>),
|
||||||
|
|
@ -135,7 +134,7 @@ impl<'a> Library {
|
||||||
pub fn update(&'a mut self, message: Message) -> Action {
|
pub fn update(&'a mut self, message: Message) -> Action {
|
||||||
match message {
|
match message {
|
||||||
Message::None => (),
|
Message::None => (),
|
||||||
Message::DeleteItem((kind, index)) => {
|
Message::DeleteItem => {
|
||||||
return self.delete_items();
|
return self.delete_items();
|
||||||
}
|
}
|
||||||
Message::AddItem => {
|
Message::AddItem => {
|
||||||
|
|
@ -156,13 +155,13 @@ impl<'a> Library {
|
||||||
LibraryKind::Video => {
|
LibraryKind::Video => {
|
||||||
return Action::Task(Task::perform(
|
return Action::Task(Task::perform(
|
||||||
add_videos(),
|
add_videos(),
|
||||||
|videos| Message::AddVideos(videos),
|
Message::AddVideos,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LibraryKind::Image => {
|
LibraryKind::Image => {
|
||||||
return Action::Task(Task::perform(
|
return Action::Task(Task::perform(
|
||||||
add_images(),
|
add_images(),
|
||||||
|images| Message::AddImages(images),
|
Message::AddImages,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LibraryKind::Presentation => {
|
LibraryKind::Presentation => {
|
||||||
|
|
@ -185,6 +184,7 @@ impl<'a> Library {
|
||||||
return self.update(Message::OpenItem(item));
|
return self.update(Message::OpenItem(item));
|
||||||
}
|
}
|
||||||
Message::AddVideos(videos) => {
|
Message::AddVideos(videos) => {
|
||||||
|
debug!(?videos);
|
||||||
if let Some(videos) = videos {
|
if let Some(videos) = videos {
|
||||||
for video in videos {
|
for video in videos {
|
||||||
if let Err(e) =
|
if let Err(e) =
|
||||||
|
|
@ -248,13 +248,12 @@ impl<'a> Library {
|
||||||
let Some(first_item) = self
|
let Some(first_item) = self
|
||||||
.selected_items
|
.selected_items
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|items| {
|
.and_then(|items| {
|
||||||
items
|
items
|
||||||
.iter()
|
.iter()
|
||||||
.next()
|
.next()
|
||||||
.map(|(_, index)| index)
|
.map(|(_, index)| index)
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
else {
|
else {
|
||||||
let Some(item) = item else {
|
let Some(item) = item else {
|
||||||
return Action::None;
|
return Action::None;
|
||||||
|
|
@ -270,9 +269,9 @@ impl<'a> Library {
|
||||||
self.selected_items = self
|
self.selected_items = self
|
||||||
.selected_items
|
.selected_items
|
||||||
.clone()
|
.clone()
|
||||||
.and_then(|mut items| {
|
.map(|mut items| {
|
||||||
items.push((kind, id));
|
items.push((kind, id));
|
||||||
Some(items)
|
items
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if first_item > &index {
|
} else if first_item > &index {
|
||||||
|
|
@ -280,9 +279,9 @@ impl<'a> Library {
|
||||||
self.selected_items = self
|
self.selected_items = self
|
||||||
.selected_items
|
.selected_items
|
||||||
.clone()
|
.clone()
|
||||||
.and_then(|mut items| {
|
.map(|mut items| {
|
||||||
items.push((kind, id));
|
items.push((kind, id));
|
||||||
Some(items)
|
items
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -605,7 +604,10 @@ impl<'a> Library {
|
||||||
|
|
||||||
if let Some(context_id) = self.context_menu {
|
if let Some(context_id) = self.context_menu {
|
||||||
if index == context_id as usize {
|
if index == context_id as usize {
|
||||||
let menu_items = vec![menu::Item::Button("Delete", None, MenuMessage::Delete((model.kind, index as i32)))];
|
let menu_items = vec![
|
||||||
|
menu::Item::Button("Open", None, MenuMessage::Open((model.kind, index as i32))),
|
||||||
|
menu::Item::Button("Delete", None, MenuMessage::Delete)
|
||||||
|
];
|
||||||
let context_menu = context_menu(
|
let context_menu = context_menu(
|
||||||
mouse_area,
|
mouse_area,
|
||||||
self.context_menu.map_or_else(|| None, |_| {
|
self.context_menu.map_or_else(|| None, |_| {
|
||||||
|
|
@ -685,11 +687,11 @@ impl<'a> Library {
|
||||||
"text/org".into(),
|
"text/org".into(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.on_enter(|x, y, mimes| {
|
.on_enter(|_, _, mimes| {
|
||||||
warn!(?mimes);
|
warn!(?mimes);
|
||||||
Message::None
|
Message::None
|
||||||
})
|
})
|
||||||
.on_finish(|mime, data, action, x, y| {
|
.on_finish(|mime, data, action, _, _| {
|
||||||
warn!(?mime, ?data, ?action);
|
warn!(?mime, ?data, ?action);
|
||||||
Message::None
|
Message::None
|
||||||
});
|
});
|
||||||
|
|
@ -893,22 +895,22 @@ impl<'a> Library {
|
||||||
return Action::None;
|
return Action::None;
|
||||||
};
|
};
|
||||||
items.sort_by(|(_, index), (_, other)| index.cmp(other));
|
items.sort_by(|(_, index), (_, other)| index.cmp(other));
|
||||||
let tasks: Vec<Task<Message>> = items
|
let tasks: Vec<Task<Message>> =
|
||||||
.iter()
|
items
|
||||||
.rev()
|
.iter()
|
||||||
.map(|(kind, index)| match kind {
|
.rev()
|
||||||
LibraryKind::Song => {
|
.map(|(kind, index)| match kind {
|
||||||
if let Some(song) =
|
LibraryKind::Song => {
|
||||||
self.song_library.get_item(*index)
|
if let Some(song) =
|
||||||
{
|
self.song_library.get_item(*index)
|
||||||
let song = song.clone();
|
|
||||||
if let Err(e) =
|
|
||||||
self.song_library.remove_item(*index)
|
|
||||||
{
|
{
|
||||||
error!(?e);
|
let song = song.clone();
|
||||||
Task::none()
|
if let Err(e) =
|
||||||
} else {
|
self.song_library.remove_item(*index)
|
||||||
let task =
|
{
|
||||||
|
error!(?e);
|
||||||
|
Task::none()
|
||||||
|
} else {
|
||||||
Task::future(self.db.acquire())
|
Task::future(self.db.acquire())
|
||||||
.and_then(move |db| {
|
.and_then(move |db| {
|
||||||
Task::perform(
|
Task::perform(
|
||||||
|
|
@ -916,34 +918,29 @@ impl<'a> Library {
|
||||||
db, song.id,
|
db, song.id,
|
||||||
),
|
),
|
||||||
|r| {
|
|r| {
|
||||||
match r {
|
if let Err(e) = r {
|
||||||
Err(e) => {
|
error!(?e)
|
||||||
error!(?e)
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
Message::None
|
Message::None
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
})
|
||||||
task
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LibraryKind::Video => {
|
|
||||||
if let Some(video) =
|
|
||||||
self.video_library.get_item(*index)
|
|
||||||
{
|
|
||||||
let video = video.clone();
|
|
||||||
if let Err(e) =
|
|
||||||
self.video_library.remove_item(*index)
|
|
||||||
{
|
|
||||||
error!(?e);
|
|
||||||
Task::none()
|
|
||||||
} else {
|
} else {
|
||||||
let task =
|
Task::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LibraryKind::Video => {
|
||||||
|
if let Some(video) =
|
||||||
|
self.video_library.get_item(*index)
|
||||||
|
{
|
||||||
|
let video = video.clone();
|
||||||
|
if let Err(e) =
|
||||||
|
self.video_library.remove_item(*index)
|
||||||
|
{
|
||||||
|
error!(?e);
|
||||||
|
Task::none()
|
||||||
|
} else {
|
||||||
Task::future(self.db.acquire())
|
Task::future(self.db.acquire())
|
||||||
.and_then(move |db| {
|
.and_then(move |db| {
|
||||||
Task::perform(
|
Task::perform(
|
||||||
|
|
@ -951,34 +948,29 @@ impl<'a> Library {
|
||||||
db, video.id,
|
db, video.id,
|
||||||
),
|
),
|
||||||
|r| {
|
|r| {
|
||||||
match r {
|
if let Err(e) = r {
|
||||||
Err(e) => {
|
error!(?e)
|
||||||
error!(?e)
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
Message::None
|
Message::None
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
})
|
||||||
task
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LibraryKind::Image => {
|
|
||||||
if let Some(image) =
|
|
||||||
self.image_library.get_item(*index)
|
|
||||||
{
|
|
||||||
let image = image.clone();
|
|
||||||
if let Err(e) =
|
|
||||||
self.image_library.remove_item(*index)
|
|
||||||
{
|
|
||||||
error!(?e);
|
|
||||||
Task::none()
|
|
||||||
} else {
|
} else {
|
||||||
let task =
|
Task::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LibraryKind::Image => {
|
||||||
|
if let Some(image) =
|
||||||
|
self.image_library.get_item(*index)
|
||||||
|
{
|
||||||
|
let image = image.clone();
|
||||||
|
if let Err(e) =
|
||||||
|
self.image_library.remove_item(*index)
|
||||||
|
{
|
||||||
|
error!(?e);
|
||||||
|
Task::none()
|
||||||
|
} else {
|
||||||
Task::future(self.db.acquire())
|
Task::future(self.db.acquire())
|
||||||
.and_then(move |db| {
|
.and_then(move |db| {
|
||||||
Task::perform(
|
Task::perform(
|
||||||
|
|
@ -986,35 +978,30 @@ impl<'a> Library {
|
||||||
db, image.id,
|
db, image.id,
|
||||||
),
|
),
|
||||||
|r| {
|
|r| {
|
||||||
match r {
|
if let Err(e) = r {
|
||||||
Err(e) => {
|
error!(?e)
|
||||||
error!(?e)
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
Message::None
|
Message::None
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
})
|
||||||
task
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LibraryKind::Presentation => {
|
|
||||||
if let Some(presentation) =
|
|
||||||
self.presentation_library.get_item(*index)
|
|
||||||
{
|
|
||||||
let presentation = presentation.clone();
|
|
||||||
if let Err(e) = self
|
|
||||||
.presentation_library
|
|
||||||
.remove_item(*index)
|
|
||||||
{
|
|
||||||
error!(?e);
|
|
||||||
Task::none()
|
|
||||||
} else {
|
} else {
|
||||||
let task =
|
Task::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LibraryKind::Presentation => {
|
||||||
|
if let Some(presentation) =
|
||||||
|
self.presentation_library.get_item(*index)
|
||||||
|
{
|
||||||
|
let presentation = presentation.clone();
|
||||||
|
if let Err(e) = self
|
||||||
|
.presentation_library
|
||||||
|
.remove_item(*index)
|
||||||
|
{
|
||||||
|
error!(?e);
|
||||||
|
Task::none()
|
||||||
|
} else {
|
||||||
Task::future(self.db.acquire())
|
Task::future(self.db.acquire())
|
||||||
.and_then(move |db| {
|
.and_then(move |db| {
|
||||||
Task::perform(
|
Task::perform(
|
||||||
|
|
@ -1023,25 +1010,21 @@ impl<'a> Library {
|
||||||
presentation.id,
|
presentation.id,
|
||||||
),
|
),
|
||||||
|r| {
|
|r| {
|
||||||
match r {
|
if let Err(e) = r {
|
||||||
Err(e) => {
|
error!(?e)
|
||||||
error!(?e)
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
Message::None
|
Message::None
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
})
|
||||||
task
|
}
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Task::none()
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
.collect();
|
||||||
.collect();
|
if !tasks.is_empty() {
|
||||||
if tasks.len() > 0 {
|
|
||||||
self.selected_items = None;
|
self.selected_items = None;
|
||||||
}
|
}
|
||||||
Action::Task(Task::batch(tasks))
|
Action::Task(Task::batch(tasks))
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,15 @@ use crate::core::{
|
||||||
slide::Slide,
|
slide::Slide,
|
||||||
};
|
};
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
dialog::file_chooser::{open::Dialog, FileFilter},
|
Element, Task,
|
||||||
iced::{alignment::Vertical, Length},
|
dialog::file_chooser::{FileFilter, open::Dialog},
|
||||||
|
iced::{Length, alignment::Vertical},
|
||||||
iced_widget::{column, row},
|
iced_widget::{column, row},
|
||||||
theme,
|
theme,
|
||||||
widget::{
|
widget::{
|
||||||
self, button, container, horizontal_space, icon, text,
|
Space, button, container, horizontal_space, icon, text,
|
||||||
text_input, Space,
|
text_input,
|
||||||
},
|
},
|
||||||
Element, Task,
|
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
|
|
@ -83,8 +83,7 @@ impl PresentationEditor {
|
||||||
.presentation
|
.presentation
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.id)
|
.map(|v| v.id)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default();
|
||||||
.clone();
|
|
||||||
let task = Task::perform(
|
let task = Task::perform(
|
||||||
pick_presentation(),
|
pick_presentation(),
|
||||||
move |presentation_result| {
|
move |presentation_result| {
|
||||||
|
|
|
||||||
|
|
@ -7,37 +7,36 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
|
Task,
|
||||||
iced::{
|
iced::{
|
||||||
font::{Family, Stretch, Style, Weight},
|
|
||||||
Background, Border, Color, ContentFit, Font, Length, Shadow,
|
Background, Border, Color, ContentFit, Font, Length, Shadow,
|
||||||
Vector,
|
Vector,
|
||||||
|
font::{Family, Stretch, Style, Weight},
|
||||||
},
|
},
|
||||||
iced_widget::{
|
iced_widget::{
|
||||||
scrollable::{
|
scrollable::{
|
||||||
scroll_to, AbsoluteOffset, Direction, Scrollbar,
|
AbsoluteOffset, Direction, Scrollbar, scroll_to,
|
||||||
},
|
},
|
||||||
stack, vertical_rule,
|
stack, vertical_rule,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
widget::{
|
widget::{
|
||||||
container, image, mouse_area, responsive, scrollable, text,
|
Container, Id, Row, Space, container, image, mouse_area,
|
||||||
Container, Id, Row, Space,
|
responsive, scrollable, text,
|
||||||
},
|
},
|
||||||
Task,
|
|
||||||
};
|
};
|
||||||
use iced_video_player::{gst_pbutils, Position, Video, VideoPlayer};
|
use iced_video_player::{Position, Video, VideoPlayer, gst_pbutils};
|
||||||
use rodio::{Decoder, OutputStream, OutputStreamBuilder, Sink};
|
use rodio::{Decoder, OutputStream, OutputStreamBuilder, Sink};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{service_items::ServiceItem, slide::Slide},
|
|
||||||
BackgroundKind,
|
BackgroundKind,
|
||||||
|
core::{service_items::ServiceItem, slide::Slide},
|
||||||
};
|
};
|
||||||
|
|
||||||
const REFERENCE_WIDTH: f32 = 1920.0;
|
const REFERENCE_WIDTH: f32 = 1920.0;
|
||||||
static DEFAULT_SLIDE: LazyLock<Slide> =
|
static DEFAULT_SLIDE: LazyLock<Slide> = LazyLock::new(Slide::default);
|
||||||
LazyLock::new(|| Slide::default());
|
|
||||||
|
|
||||||
// #[derive(Default, Clone, Debug)]
|
// #[derive(Default, Clone, Debug)]
|
||||||
pub(crate) struct Presenter {
|
pub(crate) struct Presenter {
|
||||||
|
|
@ -155,11 +154,12 @@ impl Presenter {
|
||||||
items.iter().fold(0, |a, item| a + item.slides.len());
|
items.iter().fold(0, |a, item| a + item.slides.len());
|
||||||
|
|
||||||
let slide =
|
let slide =
|
||||||
items.get(0).map(|item| item.slides.get(0)).flatten();
|
items.first().and_then(|item| item.slides.first());
|
||||||
let audio = items
|
let audio = items
|
||||||
.get(0)
|
.first()
|
||||||
.map(|item| item.slides.get(0).map(|slide| slide.audio()))
|
.and_then(|item| {
|
||||||
.flatten()
|
item.slides.first().map(|slide| slide.audio())
|
||||||
|
})
|
||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -179,7 +179,7 @@ impl Presenter {
|
||||||
.expect("Can't open default rodio stream");
|
.expect("Can't open default rodio stream");
|
||||||
(
|
(
|
||||||
Arc::new(Sink::connect_new(
|
Arc::new(Sink::connect_new(
|
||||||
&stream_handle.mixer(),
|
stream_handle.mixer(),
|
||||||
)),
|
)),
|
||||||
stream_handle,
|
stream_handle,
|
||||||
)
|
)
|
||||||
|
|
@ -219,8 +219,7 @@ impl Presenter {
|
||||||
if let Some(slide) = self
|
if let Some(slide) = self
|
||||||
.service
|
.service
|
||||||
.get(item_index)
|
.get(item_index)
|
||||||
.map(|item| item.slides.get(slide_index))
|
.and_then(|item| item.slides.get(slide_index))
|
||||||
.flatten()
|
|
||||||
{
|
{
|
||||||
self.current_item = item_index;
|
self.current_item = item_index;
|
||||||
self.current_slide_index = slide_index;
|
self.current_slide_index = slide_index;
|
||||||
|
|
@ -473,7 +472,7 @@ impl Presenter {
|
||||||
);
|
);
|
||||||
|
|
||||||
let container = slide_view(
|
let container = slide_view(
|
||||||
&slide,
|
slide,
|
||||||
&self.video,
|
&self.video,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ use cosmic::iced::Size;
|
||||||
|
|
||||||
use cosmic::iced_core::widget::tree;
|
use cosmic::iced_core::widget::tree;
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
|
Element,
|
||||||
iced::{
|
iced::{
|
||||||
|
Event, Length, Point, Rectangle, Vector,
|
||||||
clipboard::dnd::{DndEvent, SourceEvent},
|
clipboard::dnd::{DndEvent, SourceEvent},
|
||||||
event, mouse, Event, Length, Point, Rectangle, Vector,
|
event, mouse,
|
||||||
},
|
},
|
||||||
iced_core::{
|
iced_core::{
|
||||||
self, image::Renderer, layout, renderer, widget::Tree,
|
self, Clipboard, Shell, layout, renderer, widget::Tree,
|
||||||
Clipboard, Shell,
|
|
||||||
},
|
},
|
||||||
widget::Widget,
|
widget::Widget,
|
||||||
Element,
|
|
||||||
};
|
};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
|
@ -196,27 +196,23 @@ impl<Message: Clone + 'static>
|
||||||
// We ignore motion if we do not possess drag content by now.
|
// We ignore motion if we do not possess drag content by now.
|
||||||
if let Some(left_pressed_position) =
|
if let Some(left_pressed_position) =
|
||||||
state.left_pressed_position
|
state.left_pressed_position
|
||||||
{
|
&& position
|
||||||
if position
|
|
||||||
.distance(left_pressed_position)
|
.distance(left_pressed_position)
|
||||||
> self.drag_threshold
|
> self.drag_threshold
|
||||||
|
{
|
||||||
|
if let Some(on_start) =
|
||||||
|
self.on_start.as_ref()
|
||||||
{
|
{
|
||||||
if let Some(on_start) =
|
shell.publish(on_start.clone())
|
||||||
self.on_start.as_ref()
|
|
||||||
{
|
|
||||||
shell
|
|
||||||
.publish(on_start.clone())
|
|
||||||
}
|
|
||||||
let offset = Vector::new(
|
|
||||||
left_pressed_position.x
|
|
||||||
- layout.bounds().x,
|
|
||||||
left_pressed_position.y
|
|
||||||
- layout.bounds().y,
|
|
||||||
);
|
|
||||||
state.is_dragging = true;
|
|
||||||
state.left_pressed_position =
|
|
||||||
None;
|
|
||||||
}
|
}
|
||||||
|
let offset = Vector::new(
|
||||||
|
left_pressed_position.x
|
||||||
|
- layout.bounds().x,
|
||||||
|
left_pressed_position.y
|
||||||
|
- layout.bounds().y,
|
||||||
|
);
|
||||||
|
state.is_dragging = true;
|
||||||
|
state.left_pressed_position = None;
|
||||||
}
|
}
|
||||||
if !cursor.is_over(layout.bounds()) {
|
if !cursor.is_over(layout.bounds()) {
|
||||||
state.hovered = false;
|
state.hovered = false;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use std::{io, path::PathBuf};
|
use std::{io, path::PathBuf};
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
|
Renderer,
|
||||||
iced::{Color, Font, Length, Size},
|
iced::{Color, Font, Length, Size},
|
||||||
widget::{
|
widget::{
|
||||||
self,
|
self,
|
||||||
canvas::{self, Program, Stroke},
|
canvas::{self, Program, Stroke},
|
||||||
container,
|
container,
|
||||||
},
|
},
|
||||||
Renderer,
|
|
||||||
};
|
};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use std::{io, path::PathBuf, sync::Arc};
|
use std::{io, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
dialog::file_chooser::{open::Dialog, FileFilter},
|
Element, Task,
|
||||||
iced::{alignment::Vertical, Length},
|
dialog::file_chooser::{FileFilter, open::Dialog},
|
||||||
|
iced::{Length, alignment::Vertical},
|
||||||
iced_wgpu::graphics::text::cosmic_text::fontdb,
|
iced_wgpu::graphics::text::cosmic_text::fontdb,
|
||||||
iced_widget::{column, row},
|
iced_widget::{column, row},
|
||||||
theme,
|
theme,
|
||||||
|
|
@ -10,7 +11,6 @@ use cosmic::{
|
||||||
button, combo_box, container, horizontal_space, icon,
|
button, combo_box, container, horizontal_space, icon,
|
||||||
progress_bar, scrollable, text, text_editor, text_input,
|
progress_bar, scrollable, text, text_editor, text_input,
|
||||||
},
|
},
|
||||||
Element, Task,
|
|
||||||
};
|
};
|
||||||
use dirs::font_dir;
|
use dirs::font_dir;
|
||||||
use iced_video_player::Video;
|
use iced_video_player::Video;
|
||||||
|
|
@ -18,11 +18,11 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
Background, BackgroundKind,
|
||||||
core::{service_items::ServiceTrait, slide::Slide, songs::Song},
|
core::{service_items::ServiceTrait, slide::Slide, songs::Song},
|
||||||
ui::{
|
ui::{
|
||||||
presenter::slide_view, slide_editor::SlideEditor, text_svg,
|
presenter::slide_view, slide_editor::SlideEditor, text_svg,
|
||||||
},
|
},
|
||||||
Background, BackgroundKind,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -308,12 +308,12 @@ impl SongEditor {
|
||||||
fn slide_preview(&self) -> Element<Message> {
|
fn slide_preview(&self) -> Element<Message> {
|
||||||
if let Some(slides) = &self.song_slides {
|
if let Some(slides) = &self.song_slides {
|
||||||
let slides: Vec<Element<Message>> = slides
|
let slides: Vec<Element<Message>> = slides
|
||||||
.into_iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, slide)| {
|
.map(|(index, slide)| {
|
||||||
container(
|
container(
|
||||||
slide_view(
|
slide_view(
|
||||||
&slide,
|
slide,
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
&self.video
|
&self.video
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,16 @@ use std::{
|
||||||
use colors_transform::Rgb;
|
use colors_transform::Rgb;
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
iced::{
|
iced::{
|
||||||
font::{Style, Weight},
|
|
||||||
ContentFit, Length, Size,
|
ContentFit, Length, Size,
|
||||||
|
font::{Style, Weight},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
widget::{image::Handle, Image},
|
widget::{Image, image::Handle},
|
||||||
};
|
};
|
||||||
use rapidhash::v3::rapidhash_v3;
|
use rapidhash::v3::rapidhash_v3;
|
||||||
use resvg::{
|
use resvg::{
|
||||||
tiny_skia::{self, Pixmap},
|
tiny_skia::{self, Pixmap},
|
||||||
usvg::{fontdb, Tree},
|
usvg::{Tree, fontdb},
|
||||||
};
|
};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
use std::{io, path::PathBuf};
|
use std::{io, path::PathBuf};
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
dialog::file_chooser::{open::Dialog, FileFilter},
|
Element, Task,
|
||||||
iced::{alignment::Vertical, Length},
|
dialog::file_chooser::{FileFilter, open::Dialog},
|
||||||
|
iced::{Length, alignment::Vertical},
|
||||||
iced_widget::{column, row},
|
iced_widget::{column, row},
|
||||||
theme,
|
theme,
|
||||||
widget::{
|
widget::{
|
||||||
button, container, horizontal_space, icon, progress_bar,
|
Space, button, container, horizontal_space, icon,
|
||||||
text, text_input, Space,
|
progress_bar, text, text_input,
|
||||||
},
|
},
|
||||||
Element, Task,
|
|
||||||
};
|
};
|
||||||
use iced_video_player::{Video, VideoPlayer};
|
use iced_video_player::{Video, VideoPlayer};
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
@ -94,8 +94,7 @@ impl VideoEditor {
|
||||||
.core_video
|
.core_video
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.id)
|
.map(|v| v.id)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default();
|
||||||
.clone();
|
|
||||||
let task = Task::perform(
|
let task = Task::perform(
|
||||||
pick_video(),
|
pick_video(),
|
||||||
move |video_result| {
|
move |video_result| {
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,17 @@
|
||||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
use cosmic::Theme;
|
||||||
use cosmic::iced::advanced::layout::{self, Layout};
|
use cosmic::iced::advanced::layout::{self, Layout};
|
||||||
use cosmic::iced::advanced::widget::{tree, Operation, Tree, Widget};
|
use cosmic::iced::advanced::widget::{Operation, Tree, Widget, tree};
|
||||||
use cosmic::iced::advanced::{overlay, renderer, Clipboard, Shell};
|
use cosmic::iced::advanced::{Clipboard, Shell, overlay, renderer};
|
||||||
use cosmic::iced::alignment::{self, Alignment};
|
use cosmic::iced::alignment::{self, Alignment};
|
||||||
use cosmic::iced::event::{self, Event};
|
use cosmic::iced::event::{self, Event};
|
||||||
use cosmic::iced::{self, mouse, Transformation};
|
use cosmic::iced::{self, Transformation, mouse};
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
Background, Border, Color, Element, Length, Padding, Pixels,
|
Background, Border, Color, Element, Length, Padding, Pixels,
|
||||||
Point, Rectangle, Size, Vector,
|
Point, Rectangle, Size, Vector,
|
||||||
};
|
};
|
||||||
use cosmic::Theme;
|
|
||||||
|
|
||||||
use super::{Action, DragEvent, DropPosition};
|
use super::{Action, DragEvent, DropPosition};
|
||||||
|
|
||||||
|
|
@ -468,26 +468,21 @@ where
|
||||||
Action::Picking { index, origin } => {
|
Action::Picking { index, origin } => {
|
||||||
if let Some(cursor_position) =
|
if let Some(cursor_position) =
|
||||||
cursor.position()
|
cursor.position()
|
||||||
{
|
&& cursor_position.distance(origin)
|
||||||
if cursor_position.distance(origin)
|
|
||||||
> self.deadband_zone
|
> self.deadband_zone
|
||||||
{
|
{
|
||||||
// Start dragging
|
// Start dragging
|
||||||
*action = Action::Dragging {
|
*action = Action::Dragging {
|
||||||
index,
|
index,
|
||||||
origin,
|
origin,
|
||||||
last_cursor: cursor_position,
|
last_cursor: cursor_position,
|
||||||
};
|
};
|
||||||
if let Some(on_reorder) =
|
if let Some(on_reorder) = &self.on_drag {
|
||||||
&self.on_drag
|
shell.publish(on_reorder(
|
||||||
{
|
DragEvent::Picked { index },
|
||||||
shell.publish(on_reorder(
|
));
|
||||||
DragEvent::Picked { index },
|
|
||||||
));
|
|
||||||
}
|
|
||||||
event_status =
|
|
||||||
event::Status::Captured;
|
|
||||||
}
|
}
|
||||||
|
event_status = event::Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::Dragging { origin, index, .. } => {
|
Action::Dragging { origin, index, .. } => {
|
||||||
|
|
@ -903,8 +898,7 @@ pub fn default(theme: &Theme) -> Style {
|
||||||
Style {
|
Style {
|
||||||
scale: 1.05,
|
scale: 1.05,
|
||||||
moved_item_overlay: Color::from(theme.cosmic().primary.base)
|
moved_item_overlay: Color::from(theme.cosmic().primary.base)
|
||||||
.scale_alpha(0.2)
|
.scale_alpha(0.2),
|
||||||
.into(),
|
|
||||||
ghost_border: Border {
|
ghost_border: Border {
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
color: theme.cosmic().secondary.base.into(),
|
color: theme.cosmic().secondary.base.into(),
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,11 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use cosmic::iced::advanced::layout::{self, Layout};
|
use cosmic::iced::advanced::layout::{self, Layout};
|
||||||
use cosmic::iced::advanced::widget::{tree, Operation, Tree, Widget};
|
use cosmic::iced::advanced::widget::{Operation, Tree, Widget, tree};
|
||||||
use cosmic::iced::advanced::{overlay, renderer, Clipboard, Shell};
|
use cosmic::iced::advanced::{Clipboard, Shell, overlay, renderer};
|
||||||
use cosmic::iced::alignment::{self, Alignment};
|
use cosmic::iced::alignment::{self, Alignment};
|
||||||
use cosmic::iced::event::{self, Event};
|
use cosmic::iced::event::{self, Event};
|
||||||
use cosmic::iced::{self, mouse, Transformation};
|
use cosmic::iced::{self, Transformation, mouse};
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
Background, Border, Color, Element, Length, Padding, Pixels,
|
Background, Border, Color, Element, Length, Padding, Pixels,
|
||||||
Point, Rectangle, Size, Theme, Vector,
|
Point, Rectangle, Size, Theme, Vector,
|
||||||
|
|
@ -454,26 +454,21 @@ where
|
||||||
Action::Picking { index, origin } => {
|
Action::Picking { index, origin } => {
|
||||||
if let Some(cursor_position) =
|
if let Some(cursor_position) =
|
||||||
cursor.position()
|
cursor.position()
|
||||||
{
|
&& cursor_position.distance(origin)
|
||||||
if cursor_position.distance(origin)
|
|
||||||
> self.deadband_zone
|
> self.deadband_zone
|
||||||
{
|
{
|
||||||
// Start dragging
|
// Start dragging
|
||||||
*action = Action::Dragging {
|
*action = Action::Dragging {
|
||||||
index,
|
index,
|
||||||
origin,
|
origin,
|
||||||
last_cursor: cursor_position,
|
last_cursor: cursor_position,
|
||||||
};
|
};
|
||||||
if let Some(on_reorder) =
|
if let Some(on_reorder) = &self.on_drag {
|
||||||
&self.on_drag
|
shell.publish(on_reorder(
|
||||||
{
|
DragEvent::Picked { index },
|
||||||
shell.publish(on_reorder(
|
));
|
||||||
DragEvent::Picked { index },
|
|
||||||
));
|
|
||||||
}
|
|
||||||
event_status =
|
|
||||||
event::Status::Captured;
|
|
||||||
}
|
}
|
||||||
|
event_status = event::Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::Dragging { origin, index, .. } => {
|
Action::Dragging { origin, index, .. } => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue