notedeck

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

commit e4e8d7fcf363c982c6dba14407381112f5f64afb
parent bb0262e09e18abb985c753a6149c17c92b893811
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 10 Jul 2025 09:01:41 -0700

note/action: add ScrollInfo

I might need this... lets add it just in case

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mcrates/notedeck/src/lib.rs | 2+-
Mcrates/notedeck/src/note/action.rs | 10++++++++++
Mcrates/notedeck/src/note/mod.rs | 2+-
Mcrates/notedeck_columns/src/actionbar.rs | 4++++
Mcrates/notedeck_columns/src/ui/timeline.rs | 15+++++++++++++--
5 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/crates/notedeck/src/lib.rs b/crates/notedeck/src/lib.rs @@ -51,7 +51,7 @@ pub use muted::{MuteFun, Muted}; pub use name::NostrName; pub use note::{ BroadcastContext, ContextSelection, NoteAction, NoteContext, NoteContextSelection, NoteRef, - RootIdError, RootNoteId, RootNoteIdBuf, ZapAction, + RootIdError, RootNoteId, RootNoteIdBuf, ScrollInfo, ZapAction, }; pub use notecache::{CachedNote, NoteCache}; pub use persist::*; diff --git a/crates/notedeck/src/note/action.rs b/crates/notedeck/src/note/action.rs @@ -1,9 +1,16 @@ use super::context::ContextSelection; use crate::{zaps::NoteZapTargetOwned, Images, MediaCacheType, TexturedImage}; +use egui::Vec2; use enostr::{NoteId, Pubkey}; use poll_promise::Promise; #[derive(Debug)] +pub struct ScrollInfo { + pub velocity: Vec2, + pub offset: Vec2, +} + +#[derive(Debug)] pub enum NoteAction { /// User has clicked the quote reply action Reply(NoteId), @@ -28,6 +35,9 @@ pub enum NoteAction { /// User clicked on media Media(MediaAction), + + /// User scrolled the timeline + Scroll(ScrollInfo), } impl NoteAction { diff --git a/crates/notedeck/src/note/mod.rs b/crates/notedeck/src/note/mod.rs @@ -1,7 +1,7 @@ mod action; mod context; -pub use action::{MediaAction, NoteAction, ZapAction, ZapTargetAmount}; +pub use action::{MediaAction, NoteAction, ScrollInfo, ZapAction, ZapTargetAmount}; pub use context::{BroadcastContext, ContextSelection, NoteContextSelection}; use crate::JobPool; diff --git a/crates/notedeck_columns/src/actionbar.rs b/crates/notedeck_columns/src/actionbar.rs @@ -59,6 +59,10 @@ fn execute_note_action( let mut router_action = None; match action { + NoteAction::Scroll(ref scroll_info) => { + tracing::trace!("timeline scroll {scroll_info:?}") + } + NoteAction::Reply(note_id) => { router_action = Some(RouterAction::route_to(Route::reply(note_id))); } diff --git a/crates/notedeck_columns/src/ui/timeline.rs b/crates/notedeck_columns/src/ui/timeline.rs @@ -8,7 +8,7 @@ use std::f32::consts::PI; use tracing::{error, warn}; use crate::timeline::{TimelineCache, TimelineKind, TimelineTab, ViewFilter}; -use notedeck::{note::root_note_id_from_selected_id, MuteFun, NoteAction, NoteContext}; +use notedeck::{note::root_note_id_from_selected_id, MuteFun, NoteAction, NoteContext, ScrollInfo}; use notedeck_ui::{ anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE}, show_pointer, NoteOptions, NoteView, @@ -184,7 +184,18 @@ fn timeline_ui( .data_mut(|d| d.insert_temp(show_top_button_id, true)); } - scroll_output.inner + scroll_output.inner.or_else(|| { + // if we're scrolling, return that as a response. We need this + // for auto-closing the side menu + + let velocity = scroll_output.state.velocity(); + let offset = scroll_output.state.offset; + if velocity.length_sq() > 0.0 { + Some(NoteAction::Scroll(ScrollInfo { velocity, offset })) + } else { + None + } + }) } fn goto_top_button(center: Pos2) -> impl egui::Widget {