Skip to content

Commit eafe23c

Browse files
fernandolguevarajb55
authored andcommitted
columns: add ctrl or command click open new column
hashtag, mention, embedded note, profile pic, reply, quote
1 parent 24f7093 commit eafe23c

File tree

17 files changed

+370
-66
lines changed

17 files changed

+370
-66
lines changed

crates/notedeck/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub use muted::{MuteFun, Muted};
6767
pub use name::NostrName;
6868
pub use note::{
6969
BroadcastContext, ContextSelection, NoteAction, NoteContext, NoteContextSelection, NoteRef,
70-
RootIdError, RootNoteId, RootNoteIdBuf, ScrollInfo, ZapAction,
70+
OpenColumnInfo, RootIdError, RootNoteId, RootNoteIdBuf, ScrollInfo, ZapAction,
7171
};
7272
pub use notecache::{CachedNote, NoteCache};
7373
pub use options::NotedeckOptions;

crates/notedeck/src/note/action.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ pub struct ScrollInfo {
99
pub offset: Vec2,
1010
}
1111

12+
#[derive(Debug, PartialEq)]
13+
pub enum OpenColumnInfo {
14+
/// User has clicked the quote reply action
15+
Reply(NoteId),
16+
17+
/// User has clicked the quote repost action
18+
Quote(NoteId),
19+
20+
/// User has clicked a hashtag
21+
Hashtag(String),
22+
23+
/// User has clicked a profile
24+
Profile(Pubkey),
25+
26+
Note {
27+
note_id: NoteId,
28+
},
29+
}
30+
1231
#[derive(Debug)]
1332
pub enum NoteAction {
1433
/// User has clicked the quote reply action
@@ -24,7 +43,10 @@ pub enum NoteAction {
2443
Profile(Pubkey),
2544

2645
/// User has clicked a note link
27-
Note { note_id: NoteId, preview: bool },
46+
Note {
47+
note_id: NoteId,
48+
preview: bool,
49+
},
2850

2951
/// User has selected some context option
3052
Context(ContextSelection),
@@ -37,6 +59,8 @@ pub enum NoteAction {
3759

3860
/// User scrolled the timeline
3961
Scroll(ScrollInfo),
62+
63+
OpenColumn(OpenColumnInfo),
4064
}
4165

4266
impl NoteAction {

crates/notedeck/src/note/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod action;
22
mod context;
33

4-
pub use action::{NoteAction, ScrollInfo, ZapAction, ZapTargetAmount};
4+
pub use action::{NoteAction, OpenColumnInfo, ScrollInfo, ZapAction, ZapTargetAmount};
55
pub use context::{BroadcastContext, ContextSelection, NoteContextSelection};
66

77
use crate::Accounts;

crates/notedeck_chrome/src/chrome.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ impl ChromePanelAction {
101101
chrome.switch_to_columns();
102102

103103
if let Some(c) = chrome.get_columns_app().and_then(|columns| {
104+
columns
105+
.decks_cache
106+
.active_columns_mut(ctx.i18n, ctx.accounts)
107+
.unwrap()
108+
.selected = 0;
109+
104110
columns
105111
.decks_cache
106112
.selected_column_mut(ctx.i18n, ctx.accounts)
@@ -847,7 +853,7 @@ fn chrome_handle_app_action(
847853
if let Some(action) = m_action {
848854
let col = cols.selected_mut();
849855

850-
action.process(&mut col.router, &mut col.sheet_router);
856+
action.process(0, &mut col.router, &mut col.sheet_router);
851857
}
852858
}
853859
}
@@ -903,7 +909,7 @@ fn columns_route_to_profile(
903909
if let Some(action) = m_action {
904910
let col = cols.selected_mut();
905911

906-
action.process(&mut col.router, &mut col.sheet_router);
912+
action.process(0, &mut col.router, &mut col.sheet_router);
907913
}
908914
}
909915

crates/notedeck_columns/src/actionbar.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,27 @@ pub enum NotesOpenResult {
3030
Thread(NewThreadNotes),
3131
}
3232

33+
impl NotesOpenResult {
34+
pub fn process(
35+
self,
36+
threads: &mut Threads,
37+
ndb: &Ndb,
38+
note_cache: &mut NoteCache,
39+
txn: &Transaction,
40+
timeline_cache: &mut TimelineCache,
41+
unknown_ids: &mut UnknownIds,
42+
) {
43+
match self {
44+
NotesOpenResult::Timeline(timeline_open_result) => {
45+
timeline_open_result.process(ndb, note_cache, txn, timeline_cache, unknown_ids);
46+
}
47+
NotesOpenResult::Thread(thread_open_result) => {
48+
thread_open_result.process(threads, ndb, txn, unknown_ids, note_cache);
49+
}
50+
}
51+
}
52+
}
53+
3354
pub enum TimelineOpenResult {
3455
NewNotes(NewNotes),
3556
}
@@ -81,6 +102,9 @@ fn execute_note_action(
81102
.open(ndb, note_cache, txn, pool, &kind)
82103
.map(NotesOpenResult::Timeline);
83104
}
105+
NoteAction::OpenColumn(args) => {
106+
router_action = Some(RouterAction::OpenColumn(args));
107+
}
84108
NoteAction::Note { note_id, preview } => 'ex: {
85109
let Ok(thread_selection) = ThreadSelection::from_note_id(ndb, note_cache, txn, note_id)
86110
else {
@@ -224,14 +248,7 @@ pub fn execute_and_process_note_action(
224248
);
225249

226250
if let Some(br) = resp.timeline_res {
227-
match br {
228-
NotesOpenResult::Timeline(timeline_open_result) => {
229-
timeline_open_result.process(ndb, note_cache, txn, timeline_cache, unknown_ids);
230-
}
231-
NotesOpenResult::Thread(thread_open_result) => {
232-
thread_open_result.process(threads, ndb, txn, unknown_ids, note_cache);
233-
}
234-
}
251+
br.process(threads, ndb, note_cache, txn, timeline_cache, unknown_ids);
235252
}
236253

237254
resp.router_action

crates/notedeck_columns/src/app.rs

Lines changed: 128 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{
2+
actionbar::NotesOpenResult,
23
args::{ColumnsArgs, ColumnsFlag},
34
column::Columns,
45
decks::{Decks, DecksCache},
@@ -9,7 +10,9 @@ use crate::{
910
storage,
1011
subscriptions::{SubKind, Subscriptions},
1112
support::Support,
12-
timeline::{self, kind::ListKind, thread::Threads, TimelineCache, TimelineKind},
13+
timeline::{
14+
self, kind::ListKind, thread::Threads, ThreadSelection, TimelineCache, TimelineKind,
15+
},
1316
ui::{self, DesktopSidePanel, ShowSourceClientOption, SidePanelAction},
1417
view_state::ViewState,
1518
Result,
@@ -19,7 +22,7 @@ use enostr::{ClientMessage, PoolRelay, Pubkey, RelayEvent, RelayMessage, RelayPo
1922
use nostrdb::Transaction;
2023
use notedeck::{
2124
tr, ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState,
22-
Images, JobsCache, Localization, NotedeckOptions, SettingsHandler, UnknownIds,
25+
Images, JobsCache, Localization, NotedeckOptions, OpenColumnInfo, SettingsHandler, UnknownIds,
2326
};
2427
use notedeck_ui::{
2528
media::{MediaViewer, MediaViewerFlags, MediaViewerState},
@@ -574,6 +577,102 @@ impl Damus {
574577
pub fn unrecognized_args(&self) -> &BTreeSet<String> {
575578
&self.unrecognized_args
576579
}
580+
581+
fn process_open_column(
582+
&mut self,
583+
info: &OpenColumnInfo,
584+
next_col: usize,
585+
app_ctx: &mut AppContext,
586+
) {
587+
match info {
588+
OpenColumnInfo::Profile(_) | OpenColumnInfo::Hashtag(_) => {
589+
let kind = {
590+
if let OpenColumnInfo::Hashtag(htag) = info {
591+
Some(TimelineKind::Hashtag(vec![htag.clone()]))
592+
} else if let OpenColumnInfo::Profile(pk) = info {
593+
Some(TimelineKind::Profile(*pk))
594+
} else {
595+
None
596+
}
597+
};
598+
599+
let kind = kind.expect("kind expected");
600+
601+
let txn = Transaction::new(app_ctx.ndb).unwrap();
602+
603+
if let Some(result) = self
604+
.timeline_cache
605+
.open(app_ctx.ndb, app_ctx.note_cache, &txn, app_ctx.pool, &kind)
606+
.map(NotesOpenResult::Timeline)
607+
{
608+
result.process(
609+
&mut self.threads,
610+
app_ctx.ndb,
611+
app_ctx.note_cache,
612+
&txn,
613+
&mut self.timeline_cache,
614+
app_ctx.unknown_ids,
615+
);
616+
}
617+
618+
let route = Route::Timeline(kind.clone());
619+
620+
let columns = self.columns_mut(app_ctx.i18n, app_ctx.accounts);
621+
622+
columns.new_column_at_with_route(next_col, route);
623+
columns.select_column(next_col as i32);
624+
}
625+
OpenColumnInfo::Note { note_id } => 'ex: {
626+
let txn = Transaction::new(app_ctx.ndb).unwrap();
627+
let Ok(thread_selection) =
628+
ThreadSelection::from_note_id(app_ctx.ndb, app_ctx.note_cache, &txn, *note_id)
629+
else {
630+
tracing::error!("No thread selection for {}?", hex::encode(note_id.bytes()));
631+
break 'ex;
632+
};
633+
let route = Route::Thread(thread_selection.clone());
634+
635+
if let Some(result) = self
636+
.threads
637+
.open(
638+
app_ctx.ndb,
639+
&txn,
640+
app_ctx.pool,
641+
&thread_selection,
642+
true,
643+
next_col,
644+
)
645+
.map(NotesOpenResult::Thread)
646+
{
647+
result.process(
648+
&mut self.threads,
649+
app_ctx.ndb,
650+
app_ctx.note_cache,
651+
&txn,
652+
&mut self.timeline_cache,
653+
app_ctx.unknown_ids,
654+
);
655+
}
656+
657+
let columns = self.columns_mut(app_ctx.i18n, app_ctx.accounts);
658+
659+
columns.new_column_at_with_route(next_col, route);
660+
columns.select_column(next_col as i32);
661+
}
662+
OpenColumnInfo::Quote(note_id) => {
663+
let columns = self.columns_mut(app_ctx.i18n, app_ctx.accounts);
664+
665+
columns.new_column_at_with_route(next_col, Route::quote(*note_id));
666+
columns.select_column(next_col as i32);
667+
}
668+
OpenColumnInfo::Reply(note_id) => {
669+
let columns = self.columns_mut(app_ctx.i18n, app_ctx.accounts);
670+
671+
columns.new_column_at_with_route(next_col, Route::reply(*note_id));
672+
columns.select_column(next_col as i32);
673+
}
674+
}
675+
}
577676
}
578677

579678
fn get_note_options(args: ColumnsArgs, settings_handler: &mut SettingsHandler) -> NoteOptions {
@@ -651,6 +750,11 @@ fn render_damus_mobile(
651750
ProcessNavResult::PfpClicked => {
652751
app_action = Some(AppAction::ToggleChrome);
653752
}
753+
754+
ProcessNavResult::OpenColumn((col, info)) => {
755+
let next_col = *col + 1;
756+
app.process_open_column(info, next_col, app_ctx);
757+
}
654758
}
655759
}
656760
}
@@ -767,9 +871,9 @@ fn timelines_view(
767871
ui: &mut egui::Ui,
768872
sizes: Size,
769873
app: &mut Damus,
770-
ctx: &mut AppContext<'_>,
874+
app_ctx: &mut AppContext<'_>,
771875
) -> Option<AppAction> {
772-
let num_cols = get_active_columns(ctx.accounts, &app.decks_cache).num_columns();
876+
let num_cols = get_active_columns(app_ctx.accounts, &app.decks_cache).num_columns();
773877
let mut side_panel_action: Option<nav::SwitchingAction> = None;
774878
let mut responses = Vec::with_capacity(num_cols);
775879

@@ -781,19 +885,19 @@ fn timelines_view(
781885
strip.cell(|ui| {
782886
let rect = ui.available_rect_before_wrap();
783887
let side_panel = DesktopSidePanel::new(
784-
ctx.accounts.get_selected_account(),
888+
app_ctx.accounts.get_selected_account(),
785889
&app.decks_cache,
786-
ctx.i18n,
890+
app_ctx.i18n,
787891
)
788892
.show(ui);
789893

790894
if let Some(side_panel) = side_panel {
791895
if side_panel.response.clicked() || side_panel.response.secondary_clicked() {
792896
if let Some(action) = DesktopSidePanel::perform_action(
793897
&mut app.decks_cache,
794-
ctx.accounts,
898+
app_ctx.accounts,
795899
side_panel.action,
796-
ctx.i18n,
900+
app_ctx.i18n,
797901
) {
798902
side_panel_action = Some(action);
799903
}
@@ -828,7 +932,7 @@ fn timelines_view(
828932
inner.set_right(rect.right() - v_line_stroke.width);
829933
inner
830934
};
831-
responses.push(nav::render_nav(col_index, inner_rect, app, ctx, ui));
935+
responses.push(nav::render_nav(col_index, inner_rect, app, app_ctx, ui));
832936

833937
// vertical line
834938
ui.painter()
@@ -849,13 +953,18 @@ fn timelines_view(
849953
let mut save_cols = false;
850954
if let Some(action) = side_panel_action {
851955
save_cols = save_cols
852-
|| action.process(&mut app.timeline_cache, &mut app.decks_cache, ctx, ui.ctx());
956+
|| action.process(
957+
&mut app.timeline_cache,
958+
&mut app.decks_cache,
959+
app_ctx,
960+
ui.ctx(),
961+
);
853962
}
854963

855964
let mut app_action: Option<AppAction> = None;
856965

857966
for response in responses {
858-
let nav_result = response.process_render_nav_response(app, ctx, ui);
967+
let nav_result = response.process_render_nav_response(app, app_ctx, ui);
859968

860969
if let Some(nr) = &nav_result {
861970
match nr {
@@ -864,6 +973,13 @@ fn timelines_view(
864973
ProcessNavResult::PfpClicked => {
865974
app_action = Some(AppAction::ToggleChrome);
866975
}
976+
977+
ProcessNavResult::OpenColumn((col, info)) => {
978+
let next_col = *col + 1;
979+
app.process_open_column(info, next_col, app_ctx);
980+
981+
save_cols = true
982+
}
867983
}
868984
}
869985
}
@@ -873,7 +989,7 @@ fn timelines_view(
873989
}
874990

875991
if save_cols {
876-
storage::save_decks_cache(ctx.path, &app.decks_cache);
992+
storage::save_decks_cache(app_ctx.path, &app.decks_cache);
877993
}
878994

879995
app_action

0 commit comments

Comments
 (0)