refactor: unify note, post and nav actions
There was a bunch of redundant responses. Let's unify them under the RenderNavAction enum. We unify all action processing under this type. This also centralizes all of our side effects into a single function instead of scattering them everywhere
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::actionbar::NoteActionResponse;
|
||||
use crate::actionbar::NoteAction;
|
||||
use crate::images::ImageType;
|
||||
use crate::imgcache::ImageCache;
|
||||
use crate::notecache::NoteCache;
|
||||
@@ -17,7 +17,7 @@ pub struct NoteContents<'a> {
|
||||
note: &'a Note<'a>,
|
||||
note_key: NoteKey,
|
||||
options: NoteOptions,
|
||||
action: NoteActionResponse,
|
||||
action: Option<NoteAction>,
|
||||
}
|
||||
|
||||
impl<'a> NoteContents<'a> {
|
||||
@@ -38,11 +38,11 @@ impl<'a> NoteContents<'a> {
|
||||
note,
|
||||
note_key,
|
||||
options,
|
||||
action: NoteActionResponse::default(),
|
||||
action: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn action(&self) -> &NoteActionResponse {
|
||||
pub fn action(&self) -> &Option<NoteAction> {
|
||||
&self.action
|
||||
}
|
||||
}
|
||||
@@ -212,7 +212,7 @@ fn render_note_contents(
|
||||
let note_action = if let Some((id, block_str)) = inline_note {
|
||||
render_note_preview(ui, ndb, note_cache, img_cache, txn, id, block_str).action
|
||||
} else {
|
||||
NoteActionResponse::default()
|
||||
None
|
||||
};
|
||||
|
||||
if !images.is_empty() && !options.has_textmode() {
|
||||
|
||||
@@ -8,12 +8,12 @@ pub mod reply;
|
||||
pub use contents::NoteContents;
|
||||
pub use context::{NoteContextButton, NoteContextSelection};
|
||||
pub use options::NoteOptions;
|
||||
pub use post::{PostAction, PostResponse, PostView};
|
||||
pub use post::{PostAction, PostResponse, PostType, PostView};
|
||||
pub use quote_repost::QuoteRepostView;
|
||||
pub use reply::PostReplyView;
|
||||
|
||||
use crate::{
|
||||
actionbar::{BarAction, NoteActionResponse},
|
||||
actionbar::NoteAction,
|
||||
app_style::NotedeckTextStyle,
|
||||
colors,
|
||||
imgcache::ImageCache,
|
||||
@@ -38,7 +38,7 @@ pub struct NoteView<'a> {
|
||||
pub struct NoteResponse {
|
||||
pub response: egui::Response,
|
||||
pub context_selection: Option<NoteContextSelection>,
|
||||
pub action: NoteActionResponse,
|
||||
pub action: Option<NoteAction>,
|
||||
}
|
||||
|
||||
impl NoteResponse {
|
||||
@@ -46,11 +46,11 @@ impl NoteResponse {
|
||||
Self {
|
||||
response,
|
||||
context_selection: None,
|
||||
action: NoteActionResponse::default(),
|
||||
action: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_action(mut self, action: NoteActionResponse) -> Self {
|
||||
pub fn with_action(mut self, action: Option<NoteAction>) -> Self {
|
||||
self.action = action;
|
||||
self
|
||||
}
|
||||
@@ -437,8 +437,7 @@ impl<'a> NoteView<'a> {
|
||||
let note_key = self.note.key().expect("todo: support non-db notes");
|
||||
let txn = self.note.txn().expect("todo: support non-db notes");
|
||||
|
||||
let mut open_profile: Option<Pubkey> = None;
|
||||
let mut bar_action: Option<BarAction> = None;
|
||||
let mut note_action: Option<NoteAction> = None;
|
||||
let mut selected_option: Option<NoteContextSelection> = None;
|
||||
|
||||
let profile = self.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
||||
@@ -454,7 +453,7 @@ impl<'a> NoteView<'a> {
|
||||
let response = if self.options().has_wide() {
|
||||
ui.horizontal(|ui| {
|
||||
if self.pfp(note_key, &profile, ui).clicked() {
|
||||
open_profile = Some(Pubkey::new(*self.note.pubkey()));
|
||||
note_action = Some(NoteAction::OpenProfile(Pubkey::new(*self.note.pubkey())));
|
||||
};
|
||||
|
||||
let size = ui.available_size();
|
||||
@@ -498,12 +497,15 @@ impl<'a> NoteView<'a> {
|
||||
self.options(),
|
||||
);
|
||||
let resp = ui.add(&mut contents);
|
||||
bar_action = bar_action.or(contents.action().bar_action);
|
||||
open_profile = open_profile.or(contents.action().open_profile);
|
||||
|
||||
if let Some(action) = contents.action() {
|
||||
note_action = Some(*action);
|
||||
}
|
||||
|
||||
if self.options().has_actionbar() {
|
||||
let ab = render_note_actionbar(ui, self.note.id(), note_key);
|
||||
bar_action = bar_action.or(ab.inner);
|
||||
if let Some(action) = render_note_actionbar(ui, self.note.id(), note_key).inner {
|
||||
note_action = Some(action);
|
||||
}
|
||||
}
|
||||
|
||||
resp
|
||||
@@ -511,7 +513,7 @@ impl<'a> NoteView<'a> {
|
||||
// main design
|
||||
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
|
||||
if self.pfp(note_key, &profile, ui).clicked() {
|
||||
open_profile = Some(Pubkey::new(*self.note.pubkey()));
|
||||
note_action = Some(NoteAction::OpenProfile(Pubkey::new(*self.note.pubkey())));
|
||||
};
|
||||
|
||||
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
||||
@@ -548,32 +550,34 @@ impl<'a> NoteView<'a> {
|
||||
self.options(),
|
||||
);
|
||||
ui.add(&mut contents);
|
||||
bar_action = bar_action.or(contents.action().bar_action);
|
||||
open_profile = open_profile.or(contents.action().open_profile);
|
||||
|
||||
if let Some(action) = contents.action() {
|
||||
note_action = Some(*action);
|
||||
}
|
||||
|
||||
if self.options().has_actionbar() {
|
||||
let ab = render_note_actionbar(ui, self.note.id(), note_key);
|
||||
bar_action = bar_action.or(ab.inner);
|
||||
if let Some(action) =
|
||||
render_note_actionbar(ui, self.note.id(), note_key).inner
|
||||
{
|
||||
note_action = Some(action);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.response
|
||||
};
|
||||
|
||||
bar_action = check_note_hitbox(
|
||||
note_action = check_note_hitbox(
|
||||
ui,
|
||||
self.note.id(),
|
||||
note_key,
|
||||
&response,
|
||||
maybe_hitbox,
|
||||
bar_action,
|
||||
note_action,
|
||||
);
|
||||
|
||||
NoteResponse::new(response)
|
||||
.with_action(NoteActionResponse {
|
||||
bar_action,
|
||||
open_profile,
|
||||
})
|
||||
.with_action(note_action)
|
||||
.select_option(selected_option)
|
||||
}
|
||||
}
|
||||
@@ -630,8 +634,8 @@ fn check_note_hitbox(
|
||||
note_key: NoteKey,
|
||||
note_response: &Response,
|
||||
maybe_hitbox: Option<Response>,
|
||||
prior_action: Option<BarAction>,
|
||||
) -> Option<BarAction> {
|
||||
prior_action: Option<NoteAction>,
|
||||
) -> Option<NoteAction> {
|
||||
// Stash the dimensions of the note content so we can render the
|
||||
// hitbox in the next frame
|
||||
ui.ctx().data_mut(|d| {
|
||||
@@ -640,7 +644,7 @@ fn check_note_hitbox(
|
||||
|
||||
// If there was an hitbox and it was clicked open the thread
|
||||
match maybe_hitbox {
|
||||
Some(hitbox) if hitbox.clicked() => Some(BarAction::OpenThread(NoteId::new(*note_id))),
|
||||
Some(hitbox) if hitbox.clicked() => Some(NoteAction::OpenThread(NoteId::new(*note_id))),
|
||||
_ => prior_action,
|
||||
}
|
||||
}
|
||||
@@ -649,15 +653,15 @@ fn render_note_actionbar(
|
||||
ui: &mut egui::Ui,
|
||||
note_id: &[u8; 32],
|
||||
note_key: NoteKey,
|
||||
) -> egui::InnerResponse<Option<BarAction>> {
|
||||
) -> egui::InnerResponse<Option<NoteAction>> {
|
||||
ui.horizontal(|ui| {
|
||||
let reply_resp = reply_button(ui, note_key);
|
||||
let quote_resp = quote_repost_button(ui, note_key);
|
||||
|
||||
if reply_resp.clicked() {
|
||||
Some(BarAction::Reply(NoteId::new(*note_id)))
|
||||
Some(NoteAction::Reply(NoteId::new(*note_id)))
|
||||
} else if quote_resp.clicked() {
|
||||
Some(BarAction::Quote(NoteId::new(*note_id)))
|
||||
Some(NoteAction::Quote(NoteId::new(*note_id)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use crate::draft::{Draft, DraftSource};
|
||||
use crate::draft::{Draft, Drafts};
|
||||
use crate::imgcache::ImageCache;
|
||||
use crate::notecache::NoteCache;
|
||||
use crate::post::NewPost;
|
||||
use crate::ui;
|
||||
use crate::ui::{Preview, PreviewConfig, View};
|
||||
use crate::Result;
|
||||
use egui::widgets::text_edit::TextEdit;
|
||||
use egui::{Frame, Layout};
|
||||
use enostr::{FilledKeypair, FullKeypair, RelayPool};
|
||||
use nostrdb::{Config, Ndb, Note, Transaction};
|
||||
use enostr::{FilledKeypair, FullKeypair, NoteId, RelayPool};
|
||||
use nostrdb::{Config, Ndb, Transaction};
|
||||
use tracing::info;
|
||||
|
||||
use super::contents::render_note_preview;
|
||||
@@ -15,35 +16,59 @@ use super::contents::render_note_preview;
|
||||
pub struct PostView<'a> {
|
||||
ndb: &'a Ndb,
|
||||
draft: &'a mut Draft,
|
||||
draft_source: DraftSource<'a>,
|
||||
post_type: PostType,
|
||||
img_cache: &'a mut ImageCache,
|
||||
note_cache: &'a mut NoteCache,
|
||||
poster: FilledKeypair<'a>,
|
||||
id_source: Option<egui::Id>,
|
||||
}
|
||||
|
||||
pub enum PostAction {
|
||||
Post(NewPost),
|
||||
#[derive(Clone)]
|
||||
pub enum PostType {
|
||||
New,
|
||||
Quote(NoteId),
|
||||
Reply(NoteId),
|
||||
}
|
||||
|
||||
pub struct PostAction {
|
||||
post_type: PostType,
|
||||
post: NewPost,
|
||||
}
|
||||
|
||||
impl PostAction {
|
||||
pub fn execute<'b>(
|
||||
poster: FilledKeypair<'_>,
|
||||
action: &'b PostAction,
|
||||
pool: &mut RelayPool,
|
||||
draft: &mut Draft,
|
||||
get_note: impl Fn(&'b NewPost, &[u8; 32]) -> Note<'b>,
|
||||
) {
|
||||
match action {
|
||||
PostAction::Post(np) => {
|
||||
let note = get_note(np, &poster.secret_key.to_secret_bytes());
|
||||
pub fn new(post_type: PostType, post: NewPost) -> Self {
|
||||
PostAction { post_type, post }
|
||||
}
|
||||
|
||||
let raw_msg = format!("[\"EVENT\",{}]", note.json().unwrap());
|
||||
info!("sending {}", raw_msg);
|
||||
pool.send(&enostr::ClientMessage::raw(raw_msg));
|
||||
draft.clear();
|
||||
pub fn execute(
|
||||
&self,
|
||||
ndb: &Ndb,
|
||||
txn: &Transaction,
|
||||
pool: &mut RelayPool,
|
||||
drafts: &mut Drafts,
|
||||
) -> Result<()> {
|
||||
let seckey = self.post.account.secret_key.to_secret_bytes();
|
||||
|
||||
let note = match self.post_type {
|
||||
PostType::New => self.post.to_note(&seckey),
|
||||
|
||||
PostType::Reply(target) => {
|
||||
let replying_to = ndb.get_note_by_id(txn, target.bytes())?;
|
||||
self.post.to_reply(&seckey, &replying_to)
|
||||
}
|
||||
}
|
||||
|
||||
PostType::Quote(target) => {
|
||||
let quoting = ndb.get_note_by_id(txn, target.bytes())?;
|
||||
self.post.to_quote(&seckey, "ing)
|
||||
}
|
||||
};
|
||||
|
||||
let raw_msg = format!("[\"EVENT\",{}]", note.json().unwrap());
|
||||
info!("sending {}", raw_msg);
|
||||
pool.send(&enostr::ClientMessage::raw(raw_msg));
|
||||
drafts.get_from_post_type(&self.post_type).clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +81,7 @@ impl<'a> PostView<'a> {
|
||||
pub fn new(
|
||||
ndb: &'a Ndb,
|
||||
draft: &'a mut Draft,
|
||||
draft_source: DraftSource<'a>,
|
||||
post_type: PostType,
|
||||
img_cache: &'a mut ImageCache,
|
||||
note_cache: &'a mut NoteCache,
|
||||
poster: FilledKeypair<'a>,
|
||||
@@ -69,7 +94,7 @@ impl<'a> PostView<'a> {
|
||||
note_cache,
|
||||
poster,
|
||||
id_source,
|
||||
draft_source,
|
||||
post_type,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +187,7 @@ impl<'a> PostView<'a> {
|
||||
|
||||
let action = ui
|
||||
.horizontal(|ui| {
|
||||
if let DraftSource::Quote(id) = self.draft_source {
|
||||
if let PostType::Quote(id) = self.post_type {
|
||||
let avail_size = ui.available_size_before_wrap();
|
||||
ui.with_layout(Layout::left_to_right(egui::Align::TOP), |ui| {
|
||||
Frame::none().show(ui, |ui| {
|
||||
@@ -174,7 +199,7 @@ impl<'a> PostView<'a> {
|
||||
self.note_cache,
|
||||
self.img_cache,
|
||||
txn,
|
||||
id,
|
||||
id.bytes(),
|
||||
"",
|
||||
);
|
||||
});
|
||||
@@ -187,10 +212,11 @@ impl<'a> PostView<'a> {
|
||||
.add_sized([91.0, 32.0], egui::Button::new("Post now"))
|
||||
.clicked()
|
||||
{
|
||||
Some(PostAction::Post(NewPost::new(
|
||||
let new_post = NewPost::new(
|
||||
self.draft.buffer.clone(),
|
||||
self.poster.to_full(),
|
||||
)))
|
||||
);
|
||||
Some(PostAction::new(self.post_type.clone(), new_post))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -241,7 +267,7 @@ mod preview {
|
||||
PostView::new(
|
||||
&self.ndb,
|
||||
&mut self.draft,
|
||||
DraftSource::Compose,
|
||||
PostType::New,
|
||||
&mut self.img_cache,
|
||||
&mut self.note_cache,
|
||||
self.poster.to_filled(),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use enostr::FilledKeypair;
|
||||
use enostr::{FilledKeypair, NoteId};
|
||||
use nostrdb::Ndb;
|
||||
|
||||
use crate::{draft::Draft, imgcache::ImageCache, notecache::NoteCache, ui};
|
||||
|
||||
use super::PostResponse;
|
||||
use super::{PostResponse, PostType};
|
||||
|
||||
pub struct QuoteRepostView<'a> {
|
||||
ndb: &'a Ndb,
|
||||
@@ -43,7 +43,7 @@ impl<'a> QuoteRepostView<'a> {
|
||||
ui::PostView::new(
|
||||
self.ndb,
|
||||
self.draft,
|
||||
crate::draft::DraftSource::Quote(quoting_note_id),
|
||||
PostType::Quote(NoteId::new(quoting_note_id.to_owned())),
|
||||
self.img_cache,
|
||||
self.note_cache,
|
||||
self.poster,
|
||||
|
||||
@@ -2,8 +2,8 @@ use crate::draft::Draft;
|
||||
use crate::imgcache::ImageCache;
|
||||
use crate::notecache::NoteCache;
|
||||
use crate::ui;
|
||||
use crate::ui::note::PostResponse;
|
||||
use enostr::FilledKeypair;
|
||||
use crate::ui::note::{PostResponse, PostType};
|
||||
use enostr::{FilledKeypair, NoteId};
|
||||
use nostrdb::Ndb;
|
||||
|
||||
pub struct PostReplyView<'a> {
|
||||
@@ -79,7 +79,7 @@ impl<'a> PostReplyView<'a> {
|
||||
ui::PostView::new(
|
||||
self.ndb,
|
||||
self.draft,
|
||||
crate::draft::DraftSource::Reply(replying_to),
|
||||
PostType::Reply(NoteId::new(*replying_to)),
|
||||
self.img_cache,
|
||||
self.note_cache,
|
||||
self.poster,
|
||||
|
||||
@@ -9,7 +9,7 @@ pub use picture::ProfilePic;
|
||||
pub use preview::ProfilePreview;
|
||||
|
||||
use crate::{
|
||||
actionbar::NoteActionResponse, imgcache::ImageCache, notecache::NoteCache,
|
||||
actionbar::NoteAction, imgcache::ImageCache, notecache::NoteCache,
|
||||
notes_holder::NotesHolderStorage, profile::Profile,
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ impl<'a> ProfileView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> NoteActionResponse {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||
let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey));
|
||||
|
||||
ScrollArea::vertical()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
actionbar::NoteActionResponse,
|
||||
actionbar::NoteAction,
|
||||
imgcache::ImageCache,
|
||||
notecache::NoteCache,
|
||||
notes_holder::{NotesHolder, NotesHolderStorage},
|
||||
@@ -52,7 +52,7 @@ impl<'a> ThreadView<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> NoteActionResponse {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||
let txn = Transaction::new(self.ndb).expect("txn");
|
||||
|
||||
let selected_note_key = if let Ok(key) = self
|
||||
@@ -63,7 +63,7 @@ impl<'a> ThreadView<'a> {
|
||||
key
|
||||
} else {
|
||||
// TODO: render 404 ?
|
||||
return NoteActionResponse::default();
|
||||
return None;
|
||||
};
|
||||
|
||||
ui.label(
|
||||
@@ -80,7 +80,7 @@ impl<'a> ThreadView<'a> {
|
||||
let note = if let Ok(note) = self.ndb.get_note_by_key(&txn, selected_note_key) {
|
||||
note
|
||||
} else {
|
||||
return NoteActionResponse::default();
|
||||
return None;
|
||||
};
|
||||
|
||||
let root_id = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::actionbar::{BarAction, NoteActionResponse};
|
||||
use crate::actionbar::NoteAction;
|
||||
use crate::timeline::TimelineTab;
|
||||
use crate::{
|
||||
column::Columns, imgcache::ImageCache, notecache::NoteCache, timeline::TimelineId, ui,
|
||||
@@ -41,7 +41,7 @@ impl<'a> TimelineView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> NoteActionResponse {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||
timeline_ui(
|
||||
ui,
|
||||
self.ndb,
|
||||
@@ -70,7 +70,7 @@ fn timeline_ui(
|
||||
img_cache: &mut ImageCache,
|
||||
reversed: bool,
|
||||
note_options: NoteOptions,
|
||||
) -> NoteActionResponse {
|
||||
) -> Option<NoteAction> {
|
||||
//padding(4.0, ui, |ui| ui.heading("Notifications"));
|
||||
/*
|
||||
let font_id = egui::TextStyle::Body.resolve(ui.style());
|
||||
@@ -85,7 +85,7 @@ fn timeline_ui(
|
||||
error!("tried to render timeline in column, but timeline was missing");
|
||||
// TODO (jb55): render error when timeline is missing?
|
||||
// this shouldn't happen...
|
||||
return NoteActionResponse::default();
|
||||
return None;
|
||||
};
|
||||
|
||||
timeline.selected_view = tabs_ui(ui);
|
||||
@@ -108,7 +108,7 @@ fn timeline_ui(
|
||||
error!("tried to render timeline in column, but timeline was missing");
|
||||
// TODO (jb55): render error when timeline is missing?
|
||||
// this shouldn't happen...
|
||||
return NoteActionResponse::default();
|
||||
return None;
|
||||
};
|
||||
|
||||
let txn = Transaction::new(ndb).expect("failed to create txn");
|
||||
@@ -241,9 +241,8 @@ impl<'a> TimelineTabView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(&mut self, ui: &mut egui::Ui) -> NoteActionResponse {
|
||||
let mut open_profile = None;
|
||||
let mut bar_action: Option<BarAction> = None;
|
||||
pub fn show(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||
let mut action: Option<NoteAction> = None;
|
||||
let len = self.tab.notes.len();
|
||||
|
||||
self.tab
|
||||
@@ -274,8 +273,9 @@ impl<'a> TimelineTabView<'a> {
|
||||
.note_options(self.note_options)
|
||||
.show(ui);
|
||||
|
||||
bar_action = bar_action.or(resp.action.bar_action);
|
||||
open_profile = open_profile.or(resp.action.open_profile);
|
||||
if let Some(note_action) = resp.action {
|
||||
action = Some(note_action)
|
||||
}
|
||||
|
||||
if let Some(context) = resp.context_selection {
|
||||
context.process(ui, ¬e);
|
||||
@@ -288,9 +288,6 @@ impl<'a> TimelineTabView<'a> {
|
||||
1
|
||||
});
|
||||
|
||||
NoteActionResponse {
|
||||
open_profile,
|
||||
bar_action,
|
||||
}
|
||||
action
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user