commit e47f45e24ace9bd37044e5035373b39220c64f8b parent c5fdff8f30c42dfd40bd5021d9c807c0bcc49bd2 Author: kernelkind <kernelkind@gmail.com> Date: Thu, 11 Dec 2025 12:49:46 -0600 refactor(nav): Move BodyResponse to notedeck crate Signed-off-by: kernelkind <kernelkind@gmail.com> Diffstat:
19 files changed, 108 insertions(+), 123 deletions(-)
diff --git a/crates/notedeck/src/lib.rs b/crates/notedeck/src/lib.rs @@ -17,6 +17,7 @@ pub mod jobs; pub mod media; mod muted; pub mod name; +pub mod nav; mod nip51_set; pub mod note; mod notecache; @@ -67,6 +68,7 @@ pub use media::{ }; pub use muted::{MuteFun, Muted}; pub use name::NostrName; +pub use nav::BodyResponse; pub use nip51_set::{create_nip51_set, Nip51Set, Nip51SetCache}; pub use note::{ BroadcastContext, ContextSelection, NoteAction, NoteContext, NoteContextSelection, NoteRef, diff --git a/crates/notedeck/src/nav.rs b/crates/notedeck/src/nav.rs @@ -0,0 +1,82 @@ +use egui::scroll_area::ScrollAreaOutput; + +pub struct BodyResponse<R> { + pub drag_id: Option<egui::Id>, // the id which was used for dragging. + pub output: Option<R>, +} + +impl<R> BodyResponse<R> { + pub fn none() -> Self { + Self { + drag_id: None, + output: None, + } + } + + pub fn scroll(output: ScrollAreaOutput<Option<R>>) -> Self { + Self { + drag_id: Some(Self::scroll_output_to_drag_id(output.id)), + output: output.inner, + } + } + + pub fn set_scroll_id(&mut self, output: &ScrollAreaOutput<Option<R>>) { + self.drag_id = Some(Self::scroll_output_to_drag_id(output.id)); + } + + pub fn output(output: Option<R>) -> Self { + Self { + drag_id: None, + output, + } + } + + pub fn set_output(&mut self, output: R) { + self.output = Some(output); + } + + /// The id of an `egui::ScrollAreaOutput` + /// Should use `Self::scroll` when possible + pub fn scroll_raw(mut self, id: egui::Id) -> Self { + self.drag_id = Some(Self::scroll_output_to_drag_id(id)); + self + } + + /// The id which is directly used for dragging + pub fn set_drag_id_raw(&mut self, id: egui::Id) { + self.drag_id = Some(id); + } + + fn scroll_output_to_drag_id(id: egui::Id) -> egui::Id { + id.with("area") + } + + pub fn map_output<S>(self, f: impl FnOnce(R) -> S) -> BodyResponse<S> { + BodyResponse { + drag_id: self.drag_id, + output: self.output.map(f), + } + } + + pub fn map_output_maybe<S>(self, f: impl FnOnce(R) -> Option<S>) -> BodyResponse<S> { + BodyResponse { + drag_id: self.drag_id, + output: self.output.and_then(f), + } + } + + pub fn maybe_map_output<S>(self, f: impl FnOnce(Option<R>) -> S) -> BodyResponse<S> { + BodyResponse { + drag_id: self.drag_id, + output: Some(f(self.output)), + } + } + + /// insert the contents of the new BodyResponse if they are empty in Self + pub fn insert(&mut self, body: BodyResponse<R>) { + self.drag_id = self.drag_id.or(body.drag_id); + if self.output.is_none() { + self.output = body.output; + } + } +} diff --git a/crates/notedeck_columns/src/accounts/mod.rs b/crates/notedeck_columns/src/accounts/mod.rs @@ -1,13 +1,12 @@ use enostr::{FullKeypair, Pubkey}; use nostrdb::{Ndb, Transaction}; -use notedeck::{Accounts, AppContext, Localization, SingleUnkIdAction, UnknownIds}; +use notedeck::{Accounts, AppContext, BodyResponse, Localization, SingleUnkIdAction, UnknownIds}; use notedeck_ui::nip51_set::Nip51SetUiCache; pub use crate::accounts::route::AccountsResponse; use crate::app::get_active_columns_mut; use crate::decks::DecksCache; -use crate::nav::BodyResponse; use crate::onboarding::Onboarding; use crate::profile::send_new_contact_list; use crate::subscriptions::Subscriptions; diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs @@ -32,15 +32,14 @@ use crate::{ Damus, }; -use egui::scroll_area::ScrollAreaOutput; use egui_nav::{ Nav, NavAction, NavResponse, NavUiType, PopupResponse, PopupSheet, RouteResponse, Split, }; use enostr::{ProfileState, RelayPool}; use nostrdb::{Filter, Ndb, Transaction}; use notedeck::{ - get_current_default_msats, tr, ui::is_narrow, Accounts, AppContext, NoteAction, NoteCache, - NoteContext, RelayAction, + get_current_default_msats, nav::BodyResponse, tr, ui::is_narrow, Accounts, AppContext, + NoteAction, NoteCache, NoteContext, RelayAction, }; use notedeck_ui::NoteOptions; use tracing::error; @@ -1092,87 +1091,6 @@ fn render_nav_body( } } -pub struct BodyResponse<R> { - pub drag_id: Option<egui::Id>, // the id which was used for dragging. - pub output: Option<R>, -} - -impl<R> BodyResponse<R> { - pub fn none() -> Self { - Self { - drag_id: None, - output: None, - } - } - - pub fn scroll(output: ScrollAreaOutput<Option<R>>) -> Self { - Self { - drag_id: Some(Self::scroll_output_to_drag_id(output.id)), - output: output.inner, - } - } - - pub fn set_scroll_id(&mut self, output: &ScrollAreaOutput<Option<R>>) { - self.drag_id = Some(Self::scroll_output_to_drag_id(output.id)); - } - - pub fn output(output: Option<R>) -> Self { - Self { - drag_id: None, - output, - } - } - - pub fn set_output(&mut self, output: R) { - self.output = Some(output); - } - - /// The id of an `egui::ScrollAreaOutput` - /// Should use `Self::scroll` when possible - pub fn scroll_raw(mut self, id: egui::Id) -> Self { - self.drag_id = Some(Self::scroll_output_to_drag_id(id)); - self - } - - /// The id which is directly used for dragging - pub fn set_drag_id_raw(&mut self, id: egui::Id) { - self.drag_id = Some(id); - } - - fn scroll_output_to_drag_id(id: egui::Id) -> egui::Id { - id.with("area") - } - - pub fn map_output<S>(self, f: impl FnOnce(R) -> S) -> BodyResponse<S> { - BodyResponse { - drag_id: self.drag_id, - output: self.output.map(f), - } - } - - pub fn map_output_maybe<S>(self, f: impl FnOnce(R) -> Option<S>) -> BodyResponse<S> { - BodyResponse { - drag_id: self.drag_id, - output: self.output.and_then(f), - } - } - - pub fn maybe_map_output<S>(self, f: impl FnOnce(Option<R>) -> S) -> BodyResponse<S> { - BodyResponse { - drag_id: self.drag_id, - output: Some(f(self.output)), - } - } - - /// insert the contents of the new BodyResponse if they are empty in Self - pub fn insert(&mut self, body: BodyResponse<R>) { - self.drag_id = self.drag_id.or(body.drag_id); - if self.output.is_none() { - self.output = body.output; - } - } -} - #[must_use = "RenderNavResponse must be handled by calling .process_render_nav_response(..)"] #[profiling::function] pub fn render_nav( diff --git a/crates/notedeck_columns/src/timeline/route.rs b/crates/notedeck_columns/src/timeline/route.rs @@ -1,12 +1,12 @@ use crate::{ - nav::{BodyResponse, RenderNavAction}, + nav::RenderNavAction, profile::ProfileAction, timeline::{thread::Threads, ThreadSelection, TimelineCache, TimelineKind}, ui::{self, ProfileView}, }; use enostr::Pubkey; -use notedeck::NoteContext; +use notedeck::{BodyResponse, NoteContext}; use notedeck_ui::NoteOptions; #[allow(clippy::too_many_arguments)] diff --git a/crates/notedeck_columns/src/ui/accounts.rs b/crates/notedeck_columns/src/ui/accounts.rs @@ -3,14 +3,12 @@ use egui::{ }; use enostr::Pubkey; use nostrdb::{Ndb, Transaction}; -use notedeck::{tr, Accounts, Images, Localization, MediaJobSender}; +use notedeck::{tr, Accounts, BodyResponse, Images, Localization, MediaJobSender}; use notedeck_ui::colors::PINK; use notedeck_ui::profile::preview::SimpleProfilePreview; use notedeck_ui::app_images; -use crate::nav::BodyResponse; - pub struct AccountsView<'a> { ndb: &'a Ndb, accounts: &'a Accounts, diff --git a/crates/notedeck_columns/src/ui/mentions_picker.rs b/crates/notedeck_columns/src/ui/mentions_picker.rs @@ -1,8 +1,8 @@ use egui::{vec2, FontId, Layout, Pos2, Rect, ScrollArea, UiBuilder, Vec2b}; use nostrdb::{Ndb, ProfileRecord, Transaction}; use notedeck::{ - fonts::get_font_size, name::get_display_name, profile::get_profile_url, Images, MediaJobSender, - NotedeckTextStyle, + fonts::get_font_size, name::get_display_name, profile::get_profile_url, BodyResponse, Images, + MediaJobSender, NotedeckTextStyle, }; use notedeck_ui::{ anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE}, @@ -11,8 +11,6 @@ use notedeck_ui::{ }; use tracing::error; -use crate::nav::BodyResponse; - /// Displays user profiles for the user to pick from. /// Useful for manually typing a username and selecting the profile desired pub struct MentionPickerView<'a> { diff --git a/crates/notedeck_columns/src/ui/note/post.rs b/crates/notedeck_columns/src/ui/note/post.rs @@ -1,6 +1,5 @@ use crate::draft::{Draft, Drafts, MentionHint}; use crate::media_upload::nostrbuild_nip96_upload; -use crate::nav::BodyResponse; use crate::post::{downcast_post_buffer, MentionType, NewPost}; use crate::ui::mentions_picker::MentionPickerView; use crate::ui::{self, Preview, PreviewConfig}; @@ -18,10 +17,10 @@ use notedeck::media::AnimationMode; #[cfg(target_os = "android")] use notedeck::platform::android::try_open_file_picker; use notedeck::platform::get_next_selected_file; -use notedeck::PixelDimensions; use notedeck::{ name::get_display_name, supported_mime_hosted_at_url, tr, Localization, NoteAction, NoteContext, }; +use notedeck::{BodyResponse, PixelDimensions}; use notedeck_ui::{ app_images, context_menu::{input_context, PasteBehavior}, diff --git a/crates/notedeck_columns/src/ui/note/quote_repost.rs b/crates/notedeck_columns/src/ui/note/quote_repost.rs @@ -1,13 +1,12 @@ use super::{PostResponse, PostType}; use crate::{ draft::Draft, - nav::BodyResponse, ui::{self}, }; use egui::ScrollArea; use enostr::{FilledKeypair, NoteId}; -use notedeck::NoteContext; +use notedeck::{BodyResponse, NoteContext}; use notedeck_ui::NoteOptions; pub struct QuoteRepostView<'a, 'd> { diff --git a/crates/notedeck_columns/src/ui/note/reply.rs b/crates/notedeck_columns/src/ui/note/reply.rs @@ -1,5 +1,4 @@ use crate::draft::Draft; -use crate::nav::BodyResponse; use crate::ui::{ self, note::{PostAction, PostResponse, PostType}, @@ -7,7 +6,7 @@ use crate::ui::{ use egui::{Rect, Response, ScrollArea, Ui}; use enostr::{FilledKeypair, NoteId}; -use notedeck::NoteContext; +use notedeck::{BodyResponse, NoteContext}; use notedeck_ui::{NoteOptions, NoteView, ProfilePic}; pub struct PostReplyView<'a, 'd> { diff --git a/crates/notedeck_columns/src/ui/onboarding.rs b/crates/notedeck_columns/src/ui/onboarding.rs @@ -2,13 +2,13 @@ use std::mem; use egui::{Layout, ScrollArea}; use nostrdb::Ndb; -use notedeck::{tr, Images, Localization, MediaJobSender}; +use notedeck::{tr, BodyResponse, Images, Localization, MediaJobSender}; use notedeck_ui::{ colors, nip51_set::{Nip51SetUiCache, Nip51SetWidget, Nip51SetWidgetAction, Nip51SetWidgetFlags}, }; -use crate::{nav::BodyResponse, onboarding::Onboarding, ui::widgets::styled_button}; +use crate::{onboarding::Onboarding, ui::widgets::styled_button}; /// Display Follow Packs for the user to choose from authors trusted by the Damus team pub struct FollowPackOnboardingView<'a> { diff --git a/crates/notedeck_columns/src/ui/profile/contacts_list.rs b/crates/notedeck_columns/src/ui/profile/contacts_list.rs @@ -1,11 +1,9 @@ use egui::{RichText, Sense}; use enostr::Pubkey; use nostrdb::Transaction; -use notedeck::{name::get_display_name, profile::get_profile_url, NoteContext}; +use notedeck::{name::get_display_name, profile::get_profile_url, BodyResponse, NoteContext}; use notedeck_ui::ProfilePic; -use crate::nav::BodyResponse; - pub struct ContactsListView<'a, 'd, 'txn> { contacts: Vec<Pubkey>, note_context: &'a mut NoteContext<'d>, diff --git a/crates/notedeck_columns/src/ui/profile/edit.rs b/crates/notedeck_columns/src/ui/profile/edit.rs @@ -3,14 +3,13 @@ use core::f32; use egui::{vec2, Button, CornerRadius, Layout, Margin, RichText, ScrollArea, TextEdit}; use egui_winit::clipboard::Clipboard; use enostr::ProfileState; +use notedeck::BodyResponse; use notedeck::{ profile::unwrap_profile_url, tr, Images, Localization, MediaJobSender, NotedeckTextStyle, }; use notedeck_ui::context_menu::{input_context, PasteBehavior}; use notedeck_ui::{profile::banner, ProfilePic}; -use crate::nav::BodyResponse; - pub struct EditProfileView<'a> { state: &'a mut ProfileState, clipboard: &'a mut Clipboard, diff --git a/crates/notedeck_columns/src/ui/profile/mod.rs b/crates/notedeck_columns/src/ui/profile/mod.rs @@ -6,13 +6,12 @@ pub use edit::EditProfileView; use egui::{vec2, Color32, CornerRadius, Layout, Rect, RichText, ScrollArea, Sense, Stroke}; use enostr::Pubkey; use nostrdb::{ProfileRecord, Transaction}; -use notedeck::{tr, Localization, ProfileContext}; +use notedeck::{tr, BodyResponse, Localization, ProfileContext}; use notedeck_ui::profile::{context::ProfileContextWidget, follow_button}; use robius_open::Uri; use tracing::error; use crate::{ - nav::BodyResponse, timeline::{TimelineCache, TimelineKind}, ui::timeline::{tabs_ui, TimelineTabView}, }; diff --git a/crates/notedeck_columns/src/ui/relay.rs b/crates/notedeck_columns/src/ui/relay.rs @@ -1,10 +1,9 @@ use std::collections::HashMap; -use crate::nav::BodyResponse; use crate::ui::{Preview, PreviewConfig}; use egui::{Align, Button, CornerRadius, Frame, Id, Layout, Margin, Rgba, RichText, Ui, Vec2}; use enostr::{RelayPool, RelayStatus}; -use notedeck::{tr, Localization, NotedeckTextStyle, RelayAction}; +use notedeck::{tr, BodyResponse, Localization, NotedeckTextStyle, RelayAction}; use notedeck_ui::app_images; use notedeck_ui::{colors::PINK, padding}; use tracing::debug; diff --git a/crates/notedeck_columns/src/ui/search/mod.rs b/crates/notedeck_columns/src/ui/search/mod.rs @@ -3,15 +3,15 @@ use enostr::{NoteId, Pubkey}; use state::TypingType; use crate::{ - nav::BodyResponse, timeline::{TimelineTab, TimelineUnits}, ui::timeline::TimelineTabView, }; use egui_winit::clipboard::Clipboard; use nostrdb::{Filter, Ndb, ProfileRecord, Transaction}; use notedeck::{ - fonts::get_font_size, name::get_display_name, profile::get_profile_url, tr, tr_plural, Images, - Localization, MediaJobSender, NoteAction, NoteContext, NoteRef, NotedeckTextStyle, + fonts::get_font_size, name::get_display_name, profile::get_profile_url, tr, tr_plural, + BodyResponse, Images, Localization, MediaJobSender, NoteAction, NoteContext, NoteRef, + NotedeckTextStyle, }; use notedeck_ui::{ diff --git a/crates/notedeck_columns/src/ui/settings.rs b/crates/notedeck_columns/src/ui/settings.rs @@ -6,7 +6,7 @@ use egui_extras::{Size, StripBuilder}; use enostr::NoteId; use nostrdb::Transaction; use notedeck::{ - tr, ui::richtext_small, Images, LanguageIdentifier, Localization, NoteContext, + tr, ui::richtext_small, BodyResponse, Images, LanguageIdentifier, Localization, NoteContext, NotedeckTextStyle, Settings, SettingsHandler, DEFAULT_MAX_HASHTAGS_PER_NOTE, DEFAULT_NOTE_BODY_FONT_SIZE, }; @@ -15,11 +15,7 @@ use notedeck_ui::{ AnimationHelper, NoteOptions, NoteView, }; -use crate::{ - nav::{BodyResponse, RouterAction}, - ui::account_login_view::eye_button, - Damus, Route, -}; +use crate::{nav::RouterAction, ui::account_login_view::eye_button, Damus, Route}; const PREVIEW_NOTE_ID: &str = "note1edjc8ggj07hwv77g2405uh6j2jkk5aud22gktxrvc2wnre4vdwgqzlv2gw"; diff --git a/crates/notedeck_columns/src/ui/thread.rs b/crates/notedeck_columns/src/ui/thread.rs @@ -6,8 +6,8 @@ use notedeck::{NoteAction, NoteContext}; use notedeck_ui::note::NoteResponse; use notedeck_ui::{NoteOptions, NoteView}; -use crate::nav::BodyResponse; use crate::timeline::thread::{NoteSeenFlags, ParentState, Threads}; +use notedeck::BodyResponse; pub struct ThreadView<'a, 'd> { threads: &'a mut Threads, diff --git a/crates/notedeck_columns/src/ui/timeline.rs b/crates/notedeck_columns/src/ui/timeline.rs @@ -12,11 +12,11 @@ use notedeck_ui::{ProfilePic, ProfilePreview}; use std::f32::consts::PI; use tracing::{error, warn}; -use crate::nav::BodyResponse; use crate::timeline::{ CompositeType, CompositeUnit, NoteUnit, ReactionUnit, RepostUnit, TimelineCache, TimelineKind, TimelineTab, }; +use notedeck::BodyResponse; use notedeck::{ note::root_note_id_from_selected_id, tr, Localization, NoteAction, NoteContext, ScrollInfo, };