notedeck

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

commit 3cb2dd88b654ad0f064c7828897f4cf1394eab03
parent c36a22828d917b62eb8abed9ff0cdfe619eb7673
Author: kernelkind <kernelkind@gmail.com>
Date:   Thu, 22 May 2025 20:03:24 -0400

use popup sheet for `CustomZapView`

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck_chrome/src/chrome.rs | 2+-
Mcrates/notedeck_columns/src/actionbar.rs | 22+++++++++++++++++++---
Mcrates/notedeck_columns/src/column.rs | 10+++++++---
Mcrates/notedeck_columns/src/nav.rs | 110++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 128 insertions(+), 16 deletions(-)

diff --git a/crates/notedeck_chrome/src/chrome.rs b/crates/notedeck_chrome/src/chrome.rs @@ -524,7 +524,7 @@ fn chrome_handle_app_action( if let Some(action) = m_action { let col = cols.column_mut(0); - action.process(col.router_mut()); + action.process(&mut col.router, &mut col.sheet_router); } } } diff --git a/crates/notedeck_columns/src/actionbar.rs b/crates/notedeck_columns/src/actionbar.rs @@ -40,6 +40,7 @@ fn execute_note_action( global_wallet: &mut GlobalWallet, zaps: &mut Zaps, images: &mut Images, + router_type: RouterType, ui: &mut egui::Ui, ) -> NoteActionResponse { let mut timeline_res = None; @@ -94,6 +95,10 @@ fn execute_note_action( break 'a; }; + if let RouterType::Sheet = router_type { + router_action = Some(RouterAction::GoBack); + } + send_zap( &sender, zaps, @@ -105,7 +110,7 @@ fn execute_note_action( ZapAction::ClearError(target) => clear_zap_error(&sender, zaps, target), ZapAction::CustomizeAmount(target) => { let route = Route::CustomizeZapAmount(target.to_owned()); - router_action = Some(RouterAction::route_to(route)); + router_action = Some(RouterAction::route_to_sheet(route)); } } } @@ -131,8 +136,8 @@ fn execute_note_action( pub fn execute_and_process_note_action( action: NoteAction, ndb: &Ndb, - _columns: &mut Columns, - _col: usize, + columns: &mut Columns, + col: usize, timeline_cache: &mut TimelineCache, note_cache: &mut NoteCache, pool: &mut RelayPool, @@ -144,6 +149,16 @@ pub fn execute_and_process_note_action( images: &mut Images, ui: &mut egui::Ui, ) -> Option<RouterAction> { + let router_type = { + let sheet_router = &mut columns.column_mut(col).sheet_router; + + if sheet_router.route().is_some() { + RouterType::Sheet + } else { + RouterType::Stack + } + }; + let resp = execute_note_action( action, ndb, @@ -155,6 +170,7 @@ pub fn execute_and_process_note_action( global_wallet, zaps, images, + router_type, ui, ); diff --git a/crates/notedeck_columns/src/column.rs b/crates/notedeck_columns/src/column.rs @@ -1,6 +1,6 @@ use crate::{ actionbar::TimelineOpenResult, - route::{Route, Router}, + route::{Route, Router, SingletonRouter}, timeline::{Timeline, TimelineCache, TimelineKind}, }; use enostr::RelayPool; @@ -11,13 +11,17 @@ use tracing::warn; #[derive(Clone, Debug)] pub struct Column { - router: Router<Route>, + pub router: Router<Route>, + pub sheet_router: SingletonRouter<Route>, } impl Column { pub fn new(routes: Vec<Route>) -> Self { let router = Router::new(routes); - Column { router } + Column { + router, + sheet_router: SingletonRouter::default(), + } } pub fn router(&self) -> &Router<Route> { diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs @@ -7,7 +7,7 @@ use crate::{ profile::{ProfileAction, SaveProfileChanges}, profile_state::ProfileState, relay_pool_manager::RelayPoolManager, - route::{Route, Router}, + route::{Route, Router, SingletonRouter}, timeline::{route::render_timeline_route, TimelineCache}, ui::{ self, @@ -25,7 +25,7 @@ use crate::{ Damus, }; -use egui_nav::{Nav, NavAction, NavResponse, NavUiType}; +use egui_nav::{Nav, NavAction, NavResponse, NavUiType, Percent, PopupResponse, PopupSheet}; use nostrdb::Transaction; use notedeck::{ get_current_default_msats, get_current_wallet, AccountsAction, AppContext, NoteAction, @@ -122,7 +122,10 @@ impl From<NoteAction> for RenderNavAction { } } -pub type NotedeckNavResponse = NavResponse<Option<RenderNavAction>>; +enum NotedeckNavResponse { + Popup(PopupResponse<Option<RenderNavAction>>), + Nav(NavResponse<Option<RenderNavAction>>), +} pub struct RenderNavResponse { column: usize, @@ -142,8 +145,39 @@ impl RenderNavResponse { ctx: &mut AppContext<'_>, ui: &mut egui::Ui, ) -> bool { - process_nav_resp(app, ctx, ui, self.response, self.column) + match self.response { + NotedeckNavResponse::Popup(nav_action) => { + process_popup_resp(nav_action, app, ctx, ui, self.column); + false + } + NotedeckNavResponse::Nav(nav_response) => { + process_nav_resp(app, ctx, ui, nav_response, self.column) + } + } + } +} + +fn process_popup_resp( + action: PopupResponse<Option<RenderNavAction>>, + app: &mut Damus, + ctx: &mut AppContext<'_>, + ui: &mut egui::Ui, + col: usize, +) -> bool { + let mut switching_occured = false; + if let Some(nav_action) = action.response { + switching_occured = process_render_nav_action(app, ctx, ui, col, nav_action); } + + if let Some(NavAction::Returned) = action.action { + let column = app.columns_mut(ctx.accounts).column_mut(col); + column.sheet_router.clear(); + } else if let Some(NavAction::Navigating) = action.action { + let column = app.columns_mut(ctx.accounts).column_mut(col); + column.sheet_router.navigating = false; + } + + switching_occured } fn process_nav_resp( @@ -204,23 +238,38 @@ pub enum RouterAction { } pub enum RouterType { + Sheet, Stack, } impl RouterAction { - pub fn process(self, stack_router: &mut Router<Route>) { + pub fn process( + self, + stack_router: &mut Router<Route>, + sheet_router: &mut SingletonRouter<Route>, + ) { match self { RouterAction::GoBack => { - stack_router.go_back(); + if sheet_router.route().is_some() { + sheet_router.go_back(); + } else { + stack_router.go_back(); + } } RouterAction::RouteTo(route, router_type) => match router_type { + RouterType::Sheet => sheet_router.route_to(route), RouterType::Stack => stack_router.route_to(route), }, } } + pub fn route_to(route: Route) -> Self { RouterAction::RouteTo(route, RouterType::Stack) } + + pub fn route_to_sheet(route: Route) -> Self { + RouterAction::RouteTo(route, RouterType::Sheet) + } } fn process_render_nav_action( @@ -291,8 +340,9 @@ fn process_render_nav_action( if let Some(action) = router_action { let cols = get_active_columns_mut(ctx.accounts, &mut app.decks_cache).column_mut(col); - let router = cols.router_mut(); - action.process(router); + let router = &mut cols.router; + let sheet_router = &mut cols.sheet_router; + action.process(router, sheet_router); } false @@ -660,6 +710,48 @@ pub fn render_nav( ctx: &mut AppContext<'_>, ui: &mut egui::Ui, ) -> RenderNavResponse { + if let Some(sheet_route) = app + .columns(ctx.accounts) + .column(col) + .sheet_router + .route() + .clone() + { + let navigating = app + .columns(ctx.accounts) + .column(col) + .sheet_router + .navigating; + let returning = app.columns(ctx.accounts).column(col).sheet_router.returning; + let bg_route = app + .columns(ctx.accounts) + .column(col) + .router() + .routes() + .last() + .cloned(); + if let Some(bg_route) = bg_route { + let resp = PopupSheet::new(&bg_route, &sheet_route) + .id_source(egui::Id::new(("nav", col))) + .navigating(navigating) + .returning(returning) + .with_split_percent_from_top(Percent::new(35).expect("35 <= 100")) + .show_mut(ui, |ui, typ, route| match typ { + NavUiType::Title => NavTitle::new( + ctx.ndb, + ctx.img_cache, + get_active_columns_mut(ctx.accounts, &mut app.decks_cache), + &[route.clone()], + col, + ) + .show(ui), + NavUiType::Body => render_nav_body(ui, app, ctx, route, 1, col, inner_rect), + }); + + return RenderNavResponse::new(col, NotedeckNavResponse::Popup(resp)); + } + }; + let nav_response = Nav::new( &app.columns(ctx.accounts) .column(col) @@ -698,5 +790,5 @@ pub fn render_nav( } }); - RenderNavResponse::new(col, nav_response) + RenderNavResponse::new(col, NotedeckNavResponse::Nav(nav_response)) }