From 4cd3515a787049a671d69de960ceb9e22d4f700f Mon Sep 17 00:00:00 2001 From: kernelkind Date: Thu, 5 Dec 2024 20:43:39 -0500 Subject: [PATCH] add decks UI to side panel Signed-off-by: kernelkind --- assets/icons/new_deck_icon_4x_dark.png | Bin 0 -> 4837 bytes src/app_style.rs | 2 +- src/ui/side_panel.rs | 103 ++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 assets/icons/new_deck_icon_4x_dark.png diff --git a/assets/icons/new_deck_icon_4x_dark.png b/assets/icons/new_deck_icon_4x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..38c628a2d998960c742e199352eae532cc63cfc2 GIT binary patch literal 4837 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 LNkvXXu0mjfWD;Tj literal 0 HcmV?d00001 diff --git a/src/app_style.rs b/src/app_style.rs index 86fc85d..b80c12a 100644 --- a/src/app_style.rs +++ b/src/app_style.rs @@ -229,7 +229,7 @@ pub fn create_themed_visuals(theme: ColorTheme, default: Visuals) -> Visuals { } } -//pub static DECK_ICON_SIZE: f32 = 24.0; +pub static DECK_ICON_SIZE: f32 = 24.0; pub fn deck_icon_font_sized(size: f32) -> FontId { egui::FontId::new(size, emoji_font_family()) diff --git a/src/ui/side_panel.rs b/src/ui/side_panel.rs index 1c5a3eb..451db2a 100644 --- a/src/ui/side_panel.rs +++ b/src/ui/side_panel.rs @@ -1,12 +1,15 @@ use egui::{ - vec2, Color32, InnerResponse, Label, Layout, Margin, RichText, Separator, Stroke, Widget, + vec2, Color32, InnerResponse, Label, Layout, Margin, RichText, ScrollArea, Separator, Stroke, + Widget, }; use tracing::info; use crate::{ accounts::{Accounts, AccountsRoute}, app::get_active_columns_mut, - app_style, colors, + app_style, + app_style::DECK_ICON_SIZE, + colors, column::Column, decks::DecksAction, decks::DecksCache, @@ -20,6 +23,7 @@ use crate::{ use super::{ anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE}, + configure_deck::deck_icon, profile::preview::get_account_url, ProfilePic, View, }; @@ -122,6 +126,21 @@ impl<'a> DesktopSidePanel<'a> { ui.add(Separator::default().horizontal().spacing(8.0).shrink(4.0)); + ui.add_space(8.0); + ui.add(egui::Label::new( + RichText::new("DECKS") + .size(11.0) + .color(ui.visuals().noninteractive().fg_stroke.color), + )); + ui.add_space(8.0); + let add_deck_resp = ui.add(add_deck_button()); + + let decks_inner = ScrollArea::vertical() + .max_height(ui.available_height() - (3.0 * (ICON_WIDTH + 12.0))) + .show(ui, |ui| { + show_decks(ui, self.decks_cache, self.selected_account) + }) + .inner; if expand_resp.clicked() { Some(InnerResponse::new( SidePanelAction::ExpandSidePanel, @@ -136,12 +155,34 @@ impl<'a> DesktopSidePanel<'a> { // Some(InnerResponse::new(SidePanelAction::Search, search_resp)) } else if column_resp.clicked() { Some(InnerResponse::new(SidePanelAction::Columns, column_resp)) + } else if add_deck_resp.clicked() { + Some(InnerResponse::new(SidePanelAction::NewDeck, add_deck_resp)) + } else if decks_inner.response.secondary_clicked() { + info!("decks inner secondary click"); + if let Some(clicked_index) = decks_inner.inner { + Some(InnerResponse::new( + SidePanelAction::EditDeck(clicked_index), + decks_inner.response, + )) + } else { + None + } + } else if decks_inner.response.clicked() { + if let Some(clicked_index) = decks_inner.inner { + Some(InnerResponse::new( + SidePanelAction::SwitchDeck(clicked_index), + decks_inner.response, + )) + } else { + None + } } else { None } }) .inner; + ui.add(Separator::default().horizontal().spacing(8.0).shrink(4.0)); let (pfp_resp, bottom_resp) = ui .with_layout(Layout::bottom_up(egui::Align::Center), |ui| { let pfp_resp = self.pfp_button(ui); @@ -481,6 +522,64 @@ fn support_button() -> impl Widget { } } +fn add_deck_button() -> impl Widget { + |ui: &mut egui::Ui| -> egui::Response { + let img_size = 40.0; + + let max_size = ICON_WIDTH * ICON_EXPANSION_MULTIPLE; // max size of the widget + let img_data = egui::include_image!("../../assets/icons/new_deck_icon_4x_dark.png"); + let img = egui::Image::new(img_data).max_width(img_size); + + let helper = AnimationHelper::new(ui, "new-deck-icon", vec2(max_size, max_size)); + + let cur_img_size = helper.scale_1d_pos(img_size); + img.paint_at( + ui, + helper + .get_animation_rect() + .shrink((max_size - cur_img_size) / 2.0), + ); + + helper.take_animation_response() + } +} + +fn show_decks<'a>( + ui: &mut egui::Ui, + decks_cache: &'a DecksCache, + selected_account: Option<&'a UserAccount>, +) -> InnerResponse> { + let show_decks_id = ui.id().with("show-decks"); + let account_id = if let Some(acc) = selected_account { + acc.pubkey + } else { + *decks_cache.get_fallback_pubkey() + }; + let (cur_decks, account_id) = ( + decks_cache.decks(&account_id), + show_decks_id.with(account_id), + ); + let active_index = cur_decks.active_index(); + + let (_, mut resp) = ui.allocate_exact_size(vec2(0.0, 0.0), egui::Sense::click()); + let mut clicked_index = None; + for (index, deck) in cur_decks.decks().iter().enumerate() { + let highlight = index == active_index; + let deck_icon_resp = ui.add(deck_icon( + account_id.with(index), + Some(deck.icon), + DECK_ICON_SIZE, + 40.0, + highlight, + )); + if deck_icon_resp.clicked() || deck_icon_resp.secondary_clicked() { + clicked_index = Some(index); + } + resp = resp.union(deck_icon_resp); + } + InnerResponse::new(clicked_index, resp) +} + fn milestone_name() -> impl Widget { |ui: &mut egui::Ui| -> egui::Response { ui.vertical_centered(|ui| {