From 40580a6e7a0add33bb3878a670ede7a183a1dd9c Mon Sep 17 00:00:00 2001
From: Chris Cochrun <chris@cochrun.xyz>
Date: Wed, 15 Jan 2025 14:31:48 -0600
Subject: [PATCH] now there are items and a bit of style to the library

---
 src/core/content.rs       |  6 +++
 src/core/images.rs        | 12 ++++++
 src/core/mod.rs           |  1 +
 src/core/presentations.rs | 12 ++++++
 src/core/songs.rs         | 12 ++++++
 src/core/videos.rs        | 12 ++++++
 src/ui/library.rs         | 85 ++++++++++++++++++++++++++++++++++-----
 7 files changed, 131 insertions(+), 9 deletions(-)
 create mode 100644 src/core/content.rs

diff --git a/src/core/content.rs b/src/core/content.rs
new file mode 100644
index 0000000..ed617de
--- /dev/null
+++ b/src/core/content.rs
@@ -0,0 +1,6 @@
+use super::kinds::ServiceItemKind;
+
+pub trait Content {
+    fn title(&self) -> String;
+    fn kind(&self) -> ServiceItemKind;
+}
diff --git a/src/core/images.rs b/src/core/images.rs
index 0fa339c..1379650 100644
--- a/src/core/images.rs
+++ b/src/core/images.rs
@@ -1,6 +1,8 @@
 use crate::{Background, Slide, SlideBuilder, TextAlignment};
 
 use super::{
+    content::Content,
+    kinds::ServiceItemKind,
     model::{get_db, LibraryKind, Model},
     service_items::ServiceTrait,
 };
@@ -20,6 +22,16 @@ pub struct Image {
     pub path: PathBuf,
 }
 
+impl Content for Image {
+    fn title(&self) -> String {
+        self.title.clone()
+    }
+
+    fn kind(&self) -> ServiceItemKind {
+        ServiceItemKind::Image(self.clone())
+    }
+}
+
 impl From<Value> for Image {
     fn from(value: Value) -> Self {
         Self::from(&value)
diff --git a/src/core/mod.rs b/src/core/mod.rs
index 0d33cc5..e23192e 100644
--- a/src/core/mod.rs
+++ b/src/core/mod.rs
@@ -1,3 +1,4 @@
+pub mod content;
 pub mod images;
 pub mod kinds;
 pub mod lisp;
diff --git a/src/core/presentations.rs b/src/core/presentations.rs
index a9ce0bc..21c5df8 100644
--- a/src/core/presentations.rs
+++ b/src/core/presentations.rs
@@ -10,6 +10,8 @@ use tracing::error;
 use crate::{Background, Slide, SlideBuilder, TextAlignment};
 
 use super::{
+    content::Content,
+    kinds::ServiceItemKind,
     model::{get_db, LibraryKind, Model},
     service_items::ServiceTrait,
 };
@@ -34,6 +36,16 @@ pub struct Presentation {
     pub kind: PresKind,
 }
 
+impl Content for Presentation {
+    fn title(&self) -> String {
+        self.title.clone()
+    }
+
+    fn kind(&self) -> ServiceItemKind {
+        ServiceItemKind::Presentation(self.clone())
+    }
+}
+
 impl From<Value> for Presentation {
     fn from(value: Value) -> Self {
         Self::from(&value)
diff --git a/src/core/songs.rs b/src/core/songs.rs
index 98c7ce2..6ee5a89 100644
--- a/src/core/songs.rs
+++ b/src/core/songs.rs
@@ -12,6 +12,8 @@ use tracing::{debug, error};
 use crate::{core::slide, Slide, SlideBuilder};
 
 use super::{
+    content::Content,
+    kinds::ServiceItemKind,
     model::{get_db, LibraryKind, Model},
     service_items::ServiceTrait,
     slide::{Background, TextAlignment},
@@ -34,6 +36,16 @@ pub struct Song {
     pub font_size: Option<i32>,
 }
 
+impl Content for Song {
+    fn title(&self) -> String {
+        self.title.clone()
+    }
+
+    fn kind(&self) -> ServiceItemKind {
+        ServiceItemKind::Song(self.clone())
+    }
+}
+
 impl ServiceTrait for Song {
     fn title(&self) -> String {
         self.title.clone()
diff --git a/src/core/videos.rs b/src/core/videos.rs
index c75b99d..0bbaa57 100644
--- a/src/core/videos.rs
+++ b/src/core/videos.rs
@@ -1,6 +1,8 @@
 use crate::{Background, SlideBuilder, TextAlignment};
 
 use super::{
+    content::Content,
+    kinds::ServiceItemKind,
     model::{get_db, LibraryKind, Model},
     service_items::ServiceTrait,
     slide::Slide,
@@ -25,6 +27,16 @@ pub struct Video {
     pub looping: bool,
 }
 
+impl Content for Video {
+    fn title(&self) -> String {
+        self.title.clone()
+    }
+
+    fn kind(&self) -> ServiceItemKind {
+        ServiceItemKind::Video(self.clone())
+    }
+}
+
 impl From<Value> for Video {
     fn from(value: Value) -> Self {
         Self::from(&value)
diff --git a/src/ui/library.rs b/src/ui/library.rs
index 4ca70ff..738caa9 100644
--- a/src/ui/library.rs
+++ b/src/ui/library.rs
@@ -1,18 +1,20 @@
 use cosmic::{
+    font::default,
     iced::{
         alignment::{Horizontal, Vertical},
         Background, Border, Color, Length,
     },
-    iced_widget::{column, text},
+    iced_widget::{column, row as rowm, text as textm},
     theme,
     widget::{
         button, container, horizontal_space, icon, mouse_area, row,
-        Container, Space,
+        text, Column, Container, Space,
     },
     Element, Task,
 };
 
 use crate::core::{
+    content::Content,
     images::Image,
     model::{get_db, LibraryKind, Model},
     presentations::Presentation,
@@ -86,31 +88,34 @@ impl Library {
     pub fn library_item<'a, T>(
         &'a self,
         model: &'a Model<T>,
-    ) -> Element<'a, Message> {
+    ) -> Element<'a, Message>
+    where
+        T: Content,
+    {
         let mut row = row::<Message>().spacing(5);
         match &model.kind {
             LibraryKind::Song => {
                 row = row
-                    .push(text!("Songs").align_y(Vertical::Center));
+                    .push(textm!("Songs").align_y(Vertical::Center));
             }
             LibraryKind::Video => {
                 row = row
-                    .push(text!("Videos").align_y(Vertical::Center));
+                    .push(textm!("Videos").align_y(Vertical::Center));
             }
             LibraryKind::Image => {
                 row = row
-                    .push(text!("Images").align_y(Vertical::Center));
+                    .push(textm!("Images").align_y(Vertical::Center));
             }
             LibraryKind::Presentation => {
                 row = row.push(
-                    text!("Presentations").align_y(Vertical::Center),
+                    textm!("Presentations").align_y(Vertical::Center),
                 );
             }
         };
         let item_count = model.items.len();
         row = row.push(horizontal_space());
         row = row
-            .push(text!("{}", item_count).align_y(Vertical::Center));
+            .push(textm!("{}", item_count).align_y(Vertical::Center));
         row = row.push(
             icon::from_name({
                 if self.library_open == Some(model.kind) {
@@ -156,6 +161,68 @@ impl Library {
             })
             .on_enter(Message::HoverLibrary(Some(model.kind)))
             .on_exit(Message::HoverLibrary(None));
-        button.into()
+        let lib_container = if self.library_open == Some(model.kind) {
+            let items: Column<Message> = column({
+                model.items.iter().map(|item| {
+                    let text =
+                        text::heading(elide_text(item.title(), 18))
+                            .center()
+                            .wrapping(textm::Wrapping::None);
+                    let icon = icon::from_name({
+                        match model.kind {
+                            LibraryKind::Song => {
+                                "folder-music-symbolic"
+                            }
+                            LibraryKind::Video => {
+                                "folder-videos-symbolic"
+                            }
+                            LibraryKind::Image => {
+                                "folder-pictures-symbolic"
+                            }
+                            LibraryKind::Presentation => {
+                                "x-office-presentation-symbolic"
+                            }
+                        }
+                    });
+                    Container::new(rowm![icon, text].spacing(10))
+                        .padding(5)
+                        .width(Length::Fill)
+                        .style(|t| {
+                            container::Style::default()
+                                .background(Background::Color(
+                                    t.cosmic().button.base.into(),
+                                ))
+                                .border(Border::default().rounded(
+                                    t.cosmic().corner_radii.radius_l,
+                                ))
+                        })
+                        .into()
+                })
+            })
+            .spacing(2)
+            .width(Length::Fill);
+            Container::new(items).padding(5).style(|t| {
+                container::Style::default()
+                    .background(Background::Color(
+                        t.cosmic().primary.base.into(),
+                    ))
+                    .border(
+                        Border::default().rounded(
+                            t.cosmic().corner_radii.radius_m,
+                        ),
+                    )
+            })
+        } else {
+            Container::new(Space::new(0, 0))
+        };
+        column![button, lib_container].into()
+    }
+}
+
+fn elide_text(text: String, amount: usize) -> String {
+    if text.len() > amount {
+        format!("{}...", text.split_at(amount).0)
+    } else {
+        text
     }
 }