a fledgling visible library system
Why do I write these weird commit messages....
This commit is contained in:
parent
201e9dc925
commit
89294061b7
|
@ -1,6 +1,9 @@
|
||||||
use crate::{Background, Slide, SlideBuilder, TextAlignment};
|
use crate::{Background, Slide, SlideBuilder, TextAlignment};
|
||||||
|
|
||||||
use super::{model::Model, service_items::ServiceTrait};
|
use super::{
|
||||||
|
model::{get_db, LibraryKind, Model},
|
||||||
|
service_items::ServiceTrait,
|
||||||
|
};
|
||||||
use crisp::types::{Keyword, Value};
|
use crisp::types::{Keyword, Value};
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -90,12 +93,22 @@ impl ServiceTrait for Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model<Image> {
|
impl Model<Image> {
|
||||||
pub async fn load_from_db(&mut self) {
|
pub async fn new_image_model(db: &mut SqliteConnection) -> Self {
|
||||||
|
let mut model = Self {
|
||||||
|
items: vec![],
|
||||||
|
kind: LibraryKind::Image,
|
||||||
|
};
|
||||||
|
|
||||||
|
model.load_from_db(db).await;
|
||||||
|
model
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_from_db(&mut self, db: &mut SqliteConnection) {
|
||||||
let result = query_as!(
|
let result = query_as!(
|
||||||
Image,
|
Image,
|
||||||
r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images"#
|
r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images"#
|
||||||
)
|
)
|
||||||
.fetch_all(&mut self.db)
|
.fetch_all(db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
|
|
|
@ -6,12 +6,20 @@ use sqlx::{Connection, SqliteConnection};
|
||||||
|
|
||||||
use super::kinds::ServiceItemKind;
|
use super::kinds::ServiceItemKind;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Model<T> {
|
pub struct Model<T> {
|
||||||
pub items: Vec<T>,
|
pub items: Vec<T>,
|
||||||
pub db: SqliteConnection,
|
pub kind: LibraryKind,
|
||||||
pub kind: ServiceItemKind,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum LibraryKind {
|
||||||
|
Song,
|
||||||
|
Video,
|
||||||
|
Image,
|
||||||
|
Presentation,
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Model<T> {
|
impl<T> Model<T> {
|
||||||
pub fn add_item(&mut self, item: T) -> Result<()> {
|
pub fn add_item(&mut self, item: T) -> Result<()> {
|
||||||
self.items.push(item);
|
self.items.push(item);
|
||||||
|
|
|
@ -9,7 +9,10 @@ use tracing::error;
|
||||||
|
|
||||||
use crate::{Background, Slide, SlideBuilder, TextAlignment};
|
use crate::{Background, Slide, SlideBuilder, TextAlignment};
|
||||||
|
|
||||||
use super::{model::Model, service_items::ServiceTrait};
|
use super::{
|
||||||
|
model::{get_db, LibraryKind, Model},
|
||||||
|
service_items::ServiceTrait,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
@ -131,11 +134,23 @@ impl FromRow<'_, SqliteRow> for Presentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model<Presentation> {
|
impl Model<Presentation> {
|
||||||
pub async fn load_from_db(&mut self) {
|
pub async fn new_presentation_model(
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Self {
|
||||||
|
let mut model = Self {
|
||||||
|
items: vec![],
|
||||||
|
kind: LibraryKind::Presentation,
|
||||||
|
};
|
||||||
|
|
||||||
|
model.load_from_db(db).await;
|
||||||
|
model
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_from_db(&mut self, db: &mut SqliteConnection) {
|
||||||
let result = query!(
|
let result = query!(
|
||||||
r#"SELECT id as "id: i32", title, file_path as "path", html from presentations"#
|
r#"SELECT id as "id: i32", title, file_path as "path", html from presentations"#
|
||||||
)
|
)
|
||||||
.fetch_all(&mut self.db)
|
.fetch_all(db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use tracing::{debug, error};
|
||||||
use crate::{core::slide, Slide, SlideBuilder};
|
use crate::{core::slide, Slide, SlideBuilder};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
model::Model,
|
model::{get_db, LibraryKind, Model},
|
||||||
service_items::ServiceTrait,
|
service_items::ServiceTrait,
|
||||||
slide::{Background, TextAlignment},
|
slide::{Background, TextAlignment},
|
||||||
};
|
};
|
||||||
|
@ -348,9 +348,19 @@ pub async fn get_song_from_db(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model<Song> {
|
impl Model<Song> {
|
||||||
pub async fn load_from_db(&mut self) {
|
pub async fn new_song_model(db: &mut SqliteConnection) -> Self {
|
||||||
|
let mut model = Self {
|
||||||
|
items: vec![],
|
||||||
|
kind: LibraryKind::Song,
|
||||||
|
};
|
||||||
|
|
||||||
|
model.load_from_db(db).await;
|
||||||
|
model
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_from_db(&mut self, db: &mut SqliteConnection) {
|
||||||
// static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
// static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
||||||
let result = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await;
|
let result = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
for song in s.into_iter() {
|
for song in s.into_iter() {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::{Background, SlideBuilder, TextAlignment};
|
use crate::{Background, SlideBuilder, TextAlignment};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
model::Model, service_items::ServiceTrait, slide::Slide,
|
model::{get_db, LibraryKind, Model},
|
||||||
|
service_items::ServiceTrait,
|
||||||
|
slide::Slide,
|
||||||
};
|
};
|
||||||
use cosmic::iced::Executor;
|
use cosmic::iced::Executor;
|
||||||
use crisp::types::{Keyword, Value};
|
use crisp::types::{Keyword, Value};
|
||||||
|
@ -136,8 +138,18 @@ impl ServiceTrait for Video {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model<Video> {
|
impl Model<Video> {
|
||||||
pub async fn load_from_db(&mut self) {
|
pub async fn new_video_model(db: &mut SqliteConnection) -> Self {
|
||||||
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&mut self.db).await;
|
let mut model = Self {
|
||||||
|
items: vec![],
|
||||||
|
kind: LibraryKind::Video,
|
||||||
|
};
|
||||||
|
|
||||||
|
model.load_from_db(db).await;
|
||||||
|
model
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load_from_db(&mut self, db: &mut SqliteConnection) {
|
||||||
|
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
for video in v.into_iter() {
|
for video in v.into_iter() {
|
||||||
|
|
53
src/main.rs
53
src/main.rs
|
@ -23,7 +23,7 @@ use std::path::PathBuf;
|
||||||
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::library::Library;
|
use ui::library::{self, Library};
|
||||||
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod lisp;
|
pub mod lisp;
|
||||||
|
@ -88,7 +88,7 @@ struct App {
|
||||||
current_slide: Slide,
|
current_slide: Slide,
|
||||||
presentation_open: bool,
|
presentation_open: bool,
|
||||||
cli_mode: bool,
|
cli_mode: bool,
|
||||||
// library: Library,
|
library: Option<Library>,
|
||||||
library_open: bool,
|
library_open: bool,
|
||||||
library_width: f32,
|
library_width: f32,
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,7 @@ struct App {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message {
|
enum Message {
|
||||||
Present(presenter::Message),
|
Present(presenter::Message),
|
||||||
|
Library(library::Message),
|
||||||
File(PathBuf),
|
File(PathBuf),
|
||||||
DndEnter(ServiceItem),
|
DndEnter(ServiceItem),
|
||||||
DndDrop(ServiceItem),
|
DndDrop(ServiceItem),
|
||||||
|
@ -103,6 +104,7 @@ enum Message {
|
||||||
CloseWindow(Option<window::Id>),
|
CloseWindow(Option<window::Id>),
|
||||||
WindowOpened(window::Id, Option<Point>),
|
WindowOpened(window::Id, Option<Point>),
|
||||||
WindowClosed(window::Id),
|
WindowClosed(window::Id),
|
||||||
|
AddLibrary(Library),
|
||||||
Quit,
|
Quit,
|
||||||
Key(Key, Modifiers),
|
Key(Key, Modifiers),
|
||||||
None,
|
None,
|
||||||
|
@ -174,21 +176,24 @@ impl cosmic::Application for App {
|
||||||
current_slide,
|
current_slide,
|
||||||
presentation_open: false,
|
presentation_open: false,
|
||||||
cli_mode: !input.ui,
|
cli_mode: !input.ui,
|
||||||
// library: Library::new(&items),
|
library: None,
|
||||||
library_open: true,
|
library_open: true,
|
||||||
library_width: 60.0,
|
library_width: 60.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let command;
|
let mut batch = vec![];
|
||||||
|
|
||||||
if input.ui {
|
if input.ui {
|
||||||
debug!("main view");
|
debug!("main view");
|
||||||
command = app.update_title()
|
batch.push(app.update_title())
|
||||||
} else {
|
} else {
|
||||||
debug!("window view");
|
debug!("window view");
|
||||||
command = app.show_window()
|
batch.push(app.show_window())
|
||||||
};
|
};
|
||||||
|
|
||||||
(app, command)
|
batch.push(app.add_library());
|
||||||
|
let batch = Task::batch(batch);
|
||||||
|
(app, batch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows COSMIC to integrate with your application's [`nav_bar::Model`].
|
/// Allows COSMIC to integrate with your application's [`nav_bar::Model`].
|
||||||
|
@ -412,6 +417,18 @@ impl cosmic::Application for App {
|
||||||
cosmic::app::Message::App(Message::None)
|
cosmic::app::Message::App(Message::None)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::Library(message) => {
|
||||||
|
// debug!(?message);
|
||||||
|
if let Some(library) = &mut self.library {
|
||||||
|
library.update(message).map(|x| {
|
||||||
|
debug!(?x);
|
||||||
|
cosmic::app::Message::App(Message::None)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::File(file) => {
|
Message::File(file) => {
|
||||||
self.file = file;
|
self.file = file;
|
||||||
Task::none()
|
Task::none()
|
||||||
|
@ -483,6 +500,10 @@ impl cosmic::Application for App {
|
||||||
Message::Quit => cosmic::iced::exit(),
|
Message::Quit => cosmic::iced::exit(),
|
||||||
Message::DndEnter(service_item) => todo!(),
|
Message::DndEnter(service_item) => todo!(),
|
||||||
Message::DndDrop(service_item) => todo!(),
|
Message::DndDrop(service_item) => todo!(),
|
||||||
|
Message::AddLibrary(library) => {
|
||||||
|
self.library = Some(library);
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
Message::None => Task::none(),
|
Message::None => Task::none(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,9 +571,14 @@ impl cosmic::Application for App {
|
||||||
]
|
]
|
||||||
.spacing(3);
|
.spacing(3);
|
||||||
|
|
||||||
// let library = Container::new(self.library.view())
|
let library =
|
||||||
// .center(Length::Fill)
|
Container::new(if let Some(library) = &self.library {
|
||||||
// .width(self.library_width);
|
library.view().map(|m| Message::Library(m))
|
||||||
|
} else {
|
||||||
|
Space::new(0, 0).into()
|
||||||
|
})
|
||||||
|
.style(nav_bar_style)
|
||||||
|
.center(Length::Fill);
|
||||||
// let drag_handle = Container::new(Space::new(1, Length::Fill))
|
// let drag_handle = Container::new(Space::new(1, Length::Fill))
|
||||||
// .style(|t| nav_bar_style(t));
|
// .style(|t| nav_bar_style(t));
|
||||||
// let dragger = MouseArea::new(drag_handle)
|
// let dragger = MouseArea::new(drag_handle)
|
||||||
|
@ -586,6 +612,7 @@ impl cosmic::Application for App {
|
||||||
.center_y(Length::Fill)
|
.center_y(Length::Fill)
|
||||||
.align_left(Length::Fill)
|
.align_left(Length::Fill)
|
||||||
.width(Length::FillPortion(2)),
|
.width(Length::FillPortion(2)),
|
||||||
|
library
|
||||||
]
|
]
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
|
@ -645,6 +672,12 @@ where
|
||||||
cosmic::app::Message::App(Message::WindowOpened(id, None))
|
cosmic::app::Message::App(Message::WindowOpened(id, None))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_library(&mut self) -> Task<Message> {
|
||||||
|
Task::perform(async { Library::new().await }, |x| {
|
||||||
|
cosmic::app::Message::App(Message::AddLibrary(x))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,25 +1,36 @@
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
iced::Length,
|
iced::{
|
||||||
|
alignment::{Horizontal, Vertical},
|
||||||
|
Background, Border, Color, Length,
|
||||||
|
},
|
||||||
iced_widget::{column, text},
|
iced_widget::{column, text},
|
||||||
widget::{button, horizontal_space, icon, row},
|
widget::{
|
||||||
|
button, container, horizontal_space, icon, mouse_area, row,
|
||||||
|
Container, Space,
|
||||||
|
},
|
||||||
Element, Task,
|
Element, Task,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
images::Image, kinds::ServiceItemKind, model::Model,
|
images::Image,
|
||||||
presentations::Presentation, service_items::ServiceItemModel,
|
kinds::ServiceItemKind,
|
||||||
songs::Song, videos::Video,
|
model::{get_db, LibraryKind, Model},
|
||||||
|
presentations::Presentation,
|
||||||
|
service_items::ServiceItemModel,
|
||||||
|
songs::Song,
|
||||||
|
videos::Video,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Library {
|
pub(crate) struct Library {
|
||||||
song_library: Model<Song>,
|
song_library: Model<Song>,
|
||||||
image_library: Model<Image>,
|
image_library: Model<Image>,
|
||||||
video_library: Model<Video>,
|
video_library: Model<Video>,
|
||||||
presentation_library: Model<Presentation>,
|
presentation_library: Model<Presentation>,
|
||||||
library_open: Option<ServiceItemKind>,
|
library_open: Option<LibraryKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum Message {
|
pub(crate) enum Message {
|
||||||
AddItem,
|
AddItem,
|
||||||
RemoveItem,
|
RemoveItem,
|
||||||
|
@ -28,15 +39,26 @@ pub(crate) enum Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Library {
|
impl Library {
|
||||||
pub fn new(service_items: &ServiceItemModel) -> Library {
|
pub async fn new() -> Self {
|
||||||
todo!()
|
let mut db = get_db().await;
|
||||||
|
Self {
|
||||||
|
song_library: Model::new_song_model(&mut db).await,
|
||||||
|
image_library: Model::new_image_model(&mut db).await,
|
||||||
|
video_library: Model::new_video_model(&mut db).await,
|
||||||
|
presentation_library: Model::new_presentation_model(
|
||||||
|
&mut db,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
library_open: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, message: Message) -> Task<Message> {
|
pub fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::AddItem => todo!(),
|
Message::AddItem => Task::none(),
|
||||||
Message::None => todo!(),
|
Message::None => Task::none(),
|
||||||
Message::RemoveItem => todo!(),
|
Message::RemoveItem => Task::none(),
|
||||||
Message::OpenItem => todo!(),
|
Message::OpenItem => Task::none(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,36 +69,56 @@ impl Library {
|
||||||
self.library_item(&self.video_library),
|
self.library_item(&self.video_library),
|
||||||
self.library_item(&self.presentation_library),
|
self.library_item(&self.presentation_library),
|
||||||
];
|
];
|
||||||
todo!()
|
column.height(Length::Fill).spacing(5).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn library_item<T>(
|
pub fn library_item<T>(
|
||||||
&self,
|
&self,
|
||||||
model: &Model<T>,
|
model: &Model<T>,
|
||||||
) -> Element<Message> {
|
) -> Element<Message> {
|
||||||
let mut row = row::<Message>();
|
let mut row = row::<Message>().spacing(5);
|
||||||
let title = match &model.kind {
|
match &model.kind {
|
||||||
ServiceItemKind::Song(song) => {
|
LibraryKind::Song => {
|
||||||
row = row.push(text!("Songs"));
|
row = row
|
||||||
|
.push(text!("Songs").align_y(Vertical::Center));
|
||||||
}
|
}
|
||||||
ServiceItemKind::Video(video) => {
|
LibraryKind::Video => {
|
||||||
row = row.push(text!("Videos"));
|
row = row
|
||||||
|
.push(text!("Videos").align_y(Vertical::Center));
|
||||||
}
|
}
|
||||||
ServiceItemKind::Image(image) => {
|
LibraryKind::Image => {
|
||||||
row = row.push(text!("Images"));
|
row = row
|
||||||
|
.push(text!("Images").align_y(Vertical::Center));
|
||||||
}
|
}
|
||||||
ServiceItemKind::Presentation(presentation) => {
|
LibraryKind::Presentation => {
|
||||||
row = row.push(text!("Presentations"));
|
row = row.push(
|
||||||
|
text!("Presentations").align_y(Vertical::Center),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ServiceItemKind::Content(slide) => todo!(),
|
|
||||||
};
|
};
|
||||||
let item_count = model.items.len();
|
let item_count = model.items.len();
|
||||||
row = row.push(text!("{}", item_count));
|
row = row.push(horizontal_space());
|
||||||
row = row.push(horizontal_space().width(Length::Fill));
|
|
||||||
row = row.push(
|
row = row.push(
|
||||||
button::icon(icon::from_name("arrow-down"))
|
text!("{}", item_count)
|
||||||
.on_press(Message::None),
|
.align_y(Vertical::Center)
|
||||||
|
.size(18),
|
||||||
);
|
);
|
||||||
row.into()
|
row = row.push(icon::from_name("arrow-down").size(20));
|
||||||
|
let row_container =
|
||||||
|
Container::new(row)
|
||||||
|
.padding(5)
|
||||||
|
.style(|t| {
|
||||||
|
container::Style::default()
|
||||||
|
.background(Background::Color(
|
||||||
|
t.cosmic().secondary.base.into(),
|
||||||
|
))
|
||||||
|
.border(Border::default().rounded(
|
||||||
|
t.cosmic().corner_radii.radius_s,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.center_x(Length::Fill)
|
||||||
|
.center_y(Length::Shrink);
|
||||||
|
let button = mouse_area(row_container);
|
||||||
|
button.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue