feat(ui): add support for blurhash rendering in card component
This commit is contained in:
94
src/ui.rs
94
src/ui.rs
@@ -1,18 +1,20 @@
|
||||
mod movies;
|
||||
mod player;
|
||||
mod series;
|
||||
// mod movies;
|
||||
// mod player;
|
||||
// mod series;
|
||||
use ::tap::*;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
use gpui::{
|
||||
App, Application, Bounds, ClickEvent, Context, SharedString, Window, WindowBounds,
|
||||
WindowOptions, actions, div, prelude::*, px, rgb, size,
|
||||
App, Application, Bounds, ClickEvent, Context, ImageId, ImageSource, RenderImage, Resource,
|
||||
SharedString, Window, WindowBounds, WindowOptions, actions, div, prelude::*, px, rgb, size,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AppState {
|
||||
pub title: SharedString,
|
||||
pub items: BTreeMap<SharedString, Item>,
|
||||
pub item_ids: BTreeMap<usize, SharedString>,
|
||||
pub current_item: Option<SharedString>,
|
||||
pub errors: Vec<String>,
|
||||
pub jellyfin_client: api::JellyfinClient,
|
||||
@@ -47,6 +49,7 @@ impl AppState {
|
||||
AppState {
|
||||
title: SharedString::new(title.as_ref()),
|
||||
items: BTreeMap::new(),
|
||||
item_ids: BTreeMap::new(),
|
||||
current_item: None,
|
||||
errors: Vec::new(),
|
||||
jellyfin_client,
|
||||
@@ -64,7 +67,10 @@ impl AppState {
|
||||
|
||||
fn load_item(id: usize) -> impl Fn(&mut Self, &ClickEvent, &mut Window, &mut Context<Self>) {
|
||||
move |state: &mut Self, event: &ClickEvent, window: &mut Window, cx: &mut Context<Self>| {
|
||||
dbg!("Loading item with ID: {}", id);
|
||||
let item_id = id;
|
||||
cx.spawn(async move |entity, app| {
|
||||
tracing::info!("Loading item with id: {}", item_id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,3 +189,77 @@ pub fn ui(jellyfin_client: api::JellyfinClient) {
|
||||
.expect("Failed to open window");
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Card {
|
||||
pub id: usize,
|
||||
pub title: SharedString,
|
||||
pub description: SharedString,
|
||||
pub image: SharedString,
|
||||
pub image_blurhash: BlurHash,
|
||||
pub media_type: SharedString,
|
||||
pub loading: bool,
|
||||
}
|
||||
|
||||
impl Render for Card {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.id(self.id)
|
||||
.flex()
|
||||
.flex_col()
|
||||
.w_48()
|
||||
.h_64()
|
||||
.p_10()
|
||||
.bg(rgb(0xff00ff))
|
||||
.rounded_lg()
|
||||
.pipe(|card| {
|
||||
if self.loading {
|
||||
card.child(self.image_blurhash.clone())
|
||||
} else {
|
||||
card.child(gpui::img(self.image.clone()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BlurHash {
|
||||
pub id: ImageId,
|
||||
pub data: Arc<RenderImage>,
|
||||
}
|
||||
|
||||
impl BlurHash {
|
||||
pub fn new(
|
||||
data: impl AsRef<str>,
|
||||
width: u32,
|
||||
height: u32,
|
||||
punch: f32,
|
||||
) -> Result<Self, error_stack::Report<crate::Error>> {
|
||||
use error_stack::ResultExt;
|
||||
let decoded =
|
||||
blurhash::decode(data.as_ref(), width, height, punch).change_context(crate::Error)?;
|
||||
let buffer = image::RgbaImage::from_raw(width, height, decoded)
|
||||
.ok_or(crate::Error)
|
||||
.attach("Failed to convert")?;
|
||||
let frame = image::Frame::new(buffer);
|
||||
let render_image = RenderImage::new([frame]);
|
||||
Ok(Self {
|
||||
id: render_image.id,
|
||||
data: Arc::from(render_image),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for BlurHash {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
gpui::img(ImageSource::Render(self.data.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoElement for BlurHash {
|
||||
type Element = gpui::Img;
|
||||
|
||||
fn into_element(self) -> Self::Element {
|
||||
gpui::img(ImageSource::Render(self.data.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user