notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit c2ceac16054602fd29eeb9945d130432eac1000d
parent d0e4e4b5709cd734495cfa48ac88de6213cb4ffc
Author: Martti Malmi <sirius@iki.fi>
Date:   Wed,  5 Nov 2025 15:21:22 +0200

fix fwd nav to profile, profile avatar at sidebar bottom

Diffstat:
Mcrates/notedeck_columns/src/app.rs | 2++
Mcrates/notedeck_columns/src/nav.rs | 30++++++++++++++++++++++++++++--
Mcrates/notedeck_columns/src/ui/side_panel.rs | 53++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 80 insertions(+), 5 deletions(-)

diff --git a/crates/notedeck_columns/src/app.rs b/crates/notedeck_columns/src/app.rs @@ -870,6 +870,8 @@ fn timelines_view( ctx.accounts.get_selected_account(), &app.decks_cache, ctx.i18n, + ctx.ndb, + ctx.img_cache, ) .show(ui); diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs @@ -36,10 +36,10 @@ use egui::scroll_area::ScrollAreaOutput; use egui_nav::{ Nav, NavAction, NavResponse, NavUiType, PopupResponse, PopupSheet, RouteResponse, Split, }; -use enostr::ProfileState; +use enostr::{ProfileState, RelayPool}; use nostrdb::{Filter, Ndb, Transaction}; use notedeck::{ - get_current_default_msats, tr, ui::is_narrow, Accounts, AppContext, NoteAction, NoteContext, + get_current_default_msats, tr, ui::is_narrow, Accounts, AppContext, NoteAction, NoteCache, NoteContext, RelayAction, }; use notedeck_ui::NoteOptions; @@ -317,6 +317,8 @@ fn process_nav_resp( NavAction::Navigating => { // explicitly update the edit profile state when navigating handle_navigating_edit_profile(ctx.ndb, ctx.accounts, app, col); + // open timeline in cache when navigating to timeline routes + handle_navigating_timeline(ctx.ndb, ctx.note_cache, ctx.pool, ctx.accounts, app, col); } } } @@ -362,6 +364,30 @@ fn handle_navigating_edit_profile(ndb: &Ndb, accounts: &Accounts, app: &mut Damu }); } +fn handle_navigating_timeline( + ndb: &Ndb, + note_cache: &mut NoteCache, + pool: &mut RelayPool, + accounts: &Accounts, + app: &mut Damus, + col: usize, +) { + let kind = { + let Route::Timeline(kind) = app.columns(accounts).column(col).router().top() else { + return; + }; + + if app.timeline_cache.get(kind).is_some() { + return; + } + + kind.to_owned() + }; + + let txn = Transaction::new(ndb).expect("txn"); + app.timeline_cache.open(ndb, note_cache, &txn, pool, &kind); +} + pub enum RouterAction { GoBack, /// We clicked on a pfp in a route. We currently don't carry any diff --git a/crates/notedeck_columns/src/ui/side_panel.rs b/crates/notedeck_columns/src/ui/side_panel.rs @@ -15,7 +15,7 @@ use crate::{ use notedeck::{tr, Accounts, Localization, UserAccount}; use notedeck_ui::{ anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE}, - app_images, colors, View, + app_images, colors, ProfilePic, View, }; use super::configure_deck::deck_icon; @@ -27,6 +27,8 @@ pub struct DesktopSidePanel<'a> { selected_account: &'a UserAccount, decks_cache: &'a DecksCache, i18n: &'a mut Localization, + ndb: &'a nostrdb::Ndb, + img_cache: &'a mut notedeck::Images, } impl View for DesktopSidePanel<'_> { @@ -45,6 +47,7 @@ pub enum SidePanelAction { SwitchDeck(usize), EditDeck(usize), Wallet, + ProfileAvatar, } pub struct SidePanelResponse { @@ -63,11 +66,15 @@ impl<'a> DesktopSidePanel<'a> { selected_account: &'a UserAccount, decks_cache: &'a DecksCache, i18n: &'a mut Localization, + ndb: &'a nostrdb::Ndb, + img_cache: &'a mut notedeck::Images, ) -> Self { Self { selected_account, decks_cache, i18n, + ndb, + img_cache, } } @@ -122,13 +129,40 @@ impl<'a> DesktopSidePanel<'a> { ui.add_space(8.0); let add_deck_resp = ui.add(add_deck_button(self.i18n)); + let avatar_size = 40.0; + let bottom_padding = 8.0; + let avatar_section_height = avatar_size + bottom_padding; + + let available_for_decks = ui.available_height() - avatar_section_height; + let decks_inner = ScrollArea::vertical() - .max_height(ui.available_height() - (3.0 * (ICON_WIDTH + 12.0))) + .max_height(available_for_decks) .show(ui, |ui| { show_decks(ui, self.decks_cache, self.selected_account) }) .inner; + let remaining = ui.available_height(); + if remaining > avatar_section_height { + ui.add_space(remaining - avatar_section_height); + } + + let txn = nostrdb::Transaction::new(self.ndb).ok(); + let profile_url = if let Some(ref txn) = txn { + if let Ok(profile) = self.ndb.get_profile_by_pubkey(txn, self.selected_account.key.pubkey.bytes()) { + notedeck::profile::get_profile_url(Some(&profile)) + } else { + notedeck::profile::no_pfp_url() + } + } else { + notedeck::profile::no_pfp_url() + }; + + let pfp_resp = ui.add(&mut ProfilePic::new(self.img_cache, profile_url) + .size(avatar_size) + .sense(egui::Sense::click())) + .on_hover_cursor(egui::CursorIcon::PointingHand); + /* if expand_resp.clicked() { Some(InnerResponse::new( @@ -136,7 +170,12 @@ impl<'a> DesktopSidePanel<'a> { expand_resp, )) */ - if compose_resp.clicked() { + if pfp_resp.clicked() { + Some(InnerResponse::new( + SidePanelAction::ProfileAvatar, + pfp_resp, + )) + } else if compose_resp.clicked() { Some(InnerResponse::new( SidePanelAction::ComposeNote, compose_resp, @@ -299,6 +338,14 @@ impl<'a> DesktopSidePanel<'a> { router.route_to(Route::Wallet(notedeck::WalletType::Auto)); } + SidePanelAction::ProfileAvatar => { + let pubkey = accounts.get_selected_account().key.pubkey; + if router.routes().iter().any(|r| r == &Route::profile(pubkey)) { + router.go_back(); + } else { + router.route_to(Route::profile(pubkey)); + } + } } switching_response }