feat: Update typegen enums and the UI
This commit is contained in:
23
src/main.rs
23
src/main.rs
@@ -1,12 +1,8 @@
|
||||
mod errors;
|
||||
mod ui;
|
||||
use api::{JellyfinClient, JellyfinConfig};
|
||||
use errors::*;
|
||||
|
||||
use gpui::{
|
||||
App, Application, Bounds, Context, SharedString, Window, WindowBounds, WindowOptions, div,
|
||||
prelude::*, px, rgb, size,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> Result<()> {
|
||||
dotenvy::dotenv()
|
||||
@@ -22,17 +18,12 @@ pub async fn main() -> Result<()> {
|
||||
"jello".to_string(),
|
||||
);
|
||||
let mut jellyfin = api::JellyfinClient::new(config);
|
||||
authenticate(&mut jellyfin).await?;
|
||||
jellyfin
|
||||
.authenticate_with_cached_token(".session")
|
||||
.await
|
||||
.change_context(Error)?;
|
||||
|
||||
ui::ui(jellyfin);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn authenticate(client: &mut JellyfinClient) -> Result<()> {
|
||||
if std::path::PathBuf::from(".session").exists() {
|
||||
client.load_token(".session").change_context(Error)?;
|
||||
} else {
|
||||
client.authenticate().await.change_context(Error)?;
|
||||
client.save_token(".session").change_context(Error)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
165
src/ui.rs
165
src/ui.rs
@@ -0,0 +1,165 @@
|
||||
mod movies;
|
||||
mod player;
|
||||
mod series;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use gpui::{
|
||||
App, Application, Bounds, Context, 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 current_item: Option<SharedString>,
|
||||
pub errors: Vec<String>,
|
||||
pub jellyfin_client: api::JellyfinClient,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Item {
|
||||
pub id: SharedString,
|
||||
pub name: SharedString,
|
||||
pub item_type: SharedString,
|
||||
pub media_type: SharedString,
|
||||
}
|
||||
|
||||
impl Render for AppState {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.size_full()
|
||||
.justify_center()
|
||||
.text_color(rgb(0xffffff))
|
||||
.child(Self::header())
|
||||
.child(Self::body(self, window, cx))
|
||||
.child(Self::footer())
|
||||
}
|
||||
}
|
||||
|
||||
actions!(jello_actions, [OpenItem, OnLoadItem,]);
|
||||
|
||||
impl AppState {
|
||||
fn new(title: impl AsRef<str>, jellyfin_client: api::JellyfinClient) -> Self {
|
||||
AppState {
|
||||
title: SharedString::new(title.as_ref()),
|
||||
items: BTreeMap::new(),
|
||||
current_item: None,
|
||||
errors: Vec::new(),
|
||||
jellyfin_client,
|
||||
}
|
||||
}
|
||||
|
||||
// fn on_open_item(&mut self, _: &OpenItem, _: &mut Window, cx: &mut Context<Self>) {
|
||||
// self.current_item = Some(item.0.clone());
|
||||
// }
|
||||
|
||||
fn header() -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.w_full()
|
||||
.justify_end()
|
||||
.h_20()
|
||||
.border_10()
|
||||
.bg(rgb(0x333333))
|
||||
.child(Self::button("Refresh"))
|
||||
}
|
||||
|
||||
fn footer() -> impl IntoElement {
|
||||
div().flex().flex_row().w_full().h_20().bg(rgb(0x333333))
|
||||
}
|
||||
|
||||
fn body(&mut self, window: &mut Window, cx: &mut Context<AppState>) -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.size_full()
|
||||
.child(Self::content(self, window, cx))
|
||||
.child(Self::sidebar(self, window, cx))
|
||||
}
|
||||
|
||||
fn button(label: &str) -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.justify_center()
|
||||
.items_center()
|
||||
.bg(rgb(0xff00ff))
|
||||
.text_color(rgb(0xffffff))
|
||||
.border_5()
|
||||
.rounded_lg()
|
||||
.child(label.to_string())
|
||||
}
|
||||
|
||||
fn content(&mut self, window: &mut Window, cx: &mut Context<AppState>) -> impl IntoElement {
|
||||
div()
|
||||
.debug_below()
|
||||
.w_3_4()
|
||||
// .flex()
|
||||
// .flex_wrap()
|
||||
.bg(rgb(0x111111))
|
||||
.justify_start()
|
||||
.items_start()
|
||||
.overflow_hidden()
|
||||
.child(
|
||||
div()
|
||||
.size_full()
|
||||
.flex()
|
||||
.flex_wrap()
|
||||
.justify_start()
|
||||
.items_start()
|
||||
.content_start()
|
||||
.gap_y_10()
|
||||
.gap_x_10()
|
||||
.border_t_10()
|
||||
.p_5()
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card())
|
||||
.child(Self::card()),
|
||||
)
|
||||
}
|
||||
|
||||
fn sidebar(&mut self, window: &mut Window, cx: &mut Context<AppState>) -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.w_1_4()
|
||||
.min_w_1_6()
|
||||
.bg(rgb(0x222222))
|
||||
.child(div().size_full().bg(gpui::yellow()))
|
||||
}
|
||||
|
||||
fn card() -> impl IntoElement {
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.w_48()
|
||||
.h_64()
|
||||
.p_10()
|
||||
.bg(rgb(0xff00ff))
|
||||
.rounded_lg()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(jellyfin_client: api::JellyfinClient) {
|
||||
Application::new().run(|cx: &mut App| {
|
||||
let bounds = Bounds::centered(None, size(px(500.0), px(500.0)), cx);
|
||||
cx.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(bounds)),
|
||||
..Default::default()
|
||||
},
|
||||
|_, cx| cx.new(|_| AppState::new("Jello Media Browser", jellyfin_client)),
|
||||
)
|
||||
.expect("Failed to open window");
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user