mirror of
https://github.com/aljazceru/notedeck.git
synced 2026-01-14 22:04:19 +01:00
add profile preview and implement scrolling
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use crate::route::{Route, Router};
|
||||
use crate::timeline::{Timeline, TimelineId};
|
||||
use enostr::Pubkey;
|
||||
use indexmap::IndexMap;
|
||||
use std::iter::Iterator;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
@@ -60,10 +61,10 @@ impl Columns {
|
||||
self.timelines.insert(col_id, timeline);
|
||||
}
|
||||
|
||||
pub fn route_profile_timeline(&mut self, col: usize, timeline: Timeline) {
|
||||
pub fn route_profile_timeline(&mut self, col: usize, pubkey: Pubkey, timeline: Timeline) {
|
||||
self.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(Route::Profile(timeline.id));
|
||||
.route_to(Route::Profile(pubkey, timeline.id));
|
||||
|
||||
self.timelines.insert(Self::get_new_id(), timeline);
|
||||
}
|
||||
|
||||
@@ -113,8 +113,9 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
None
|
||||
}
|
||||
|
||||
Route::Profile(id) => render_profile_route(
|
||||
Route::Profile(pubkey, id) => render_profile_route(
|
||||
*id,
|
||||
*pubkey,
|
||||
&app.ndb,
|
||||
&mut app.columns,
|
||||
&mut app.pool,
|
||||
@@ -150,7 +151,8 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
TimelineKind::profile(pubkey_source).into_timeline(&app.ndb, None)
|
||||
{
|
||||
let timeline_id = timeline.id;
|
||||
app.columns_mut().route_profile_timeline(col, timeline);
|
||||
app.columns_mut()
|
||||
.route_profile_timeline(col, pubkey, timeline);
|
||||
app.subscribe_new_timeline(timeline_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use enostr::NoteId;
|
||||
use enostr::{NoteId, Pubkey};
|
||||
use nostrdb::Ndb;
|
||||
use std::fmt::{self};
|
||||
|
||||
@@ -17,7 +17,7 @@ pub enum Route {
|
||||
Relays,
|
||||
ComposeNote,
|
||||
AddColumn,
|
||||
Profile(TimelineId),
|
||||
Profile(Pubkey, TimelineId),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -97,7 +97,7 @@ impl Route {
|
||||
},
|
||||
Route::ComposeNote => "Compose Note".to_owned(),
|
||||
Route::AddColumn => "Add Column".to_owned(),
|
||||
Route::Profile(id) => {
|
||||
Route::Profile(_, id) => {
|
||||
let timeline = columns
|
||||
.find_timeline(*id)
|
||||
.expect("expected to find timeline");
|
||||
@@ -210,7 +210,7 @@ impl fmt::Display for Route {
|
||||
Route::ComposeNote => write!(f, "Compose Note"),
|
||||
|
||||
Route::AddColumn => write!(f, "Add Column"),
|
||||
Route::Profile(_) => write!(f, "Profile"),
|
||||
Route::Profile(_, _) => write!(f, "Profile"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ pub fn render_timeline_route(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn render_profile_route(
|
||||
id: TimelineId,
|
||||
pubkey: Pubkey,
|
||||
ndb: &Ndb,
|
||||
columns: &mut Columns,
|
||||
pool: &mut RelayPool,
|
||||
@@ -163,7 +164,7 @@ pub fn render_profile_route(
|
||||
col: usize,
|
||||
ui: &mut egui::Ui,
|
||||
) -> Option<AfterRouteExecution> {
|
||||
let timeline_response = ProfileView::new(id, columns, ndb, note_cache, img_cache).ui(ui);
|
||||
let timeline_response = ProfileView::new(pubkey, id, columns, ndb, note_cache, img_cache).ui(ui);
|
||||
if let Some(bar_action) = timeline_response.bar_action {
|
||||
let txn = nostrdb::Transaction::new(ndb).expect("txn");
|
||||
let mut cur_column = columns.columns_mut();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
pub mod picture;
|
||||
pub mod preview;
|
||||
|
||||
use egui::{Label, RichText};
|
||||
use nostrdb::Ndb;
|
||||
use egui::{ScrollArea, Widget};
|
||||
use enostr::Pubkey;
|
||||
use nostrdb::{Ndb, Transaction};
|
||||
pub use picture::ProfilePic;
|
||||
pub use preview::ProfilePreview;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
actionbar::TimelineResponse, column::Columns, imgcache::ImageCache, notecache::NoteCache,
|
||||
@@ -15,6 +15,7 @@ use crate::{
|
||||
use super::TimelineView;
|
||||
|
||||
pub struct ProfileView<'a> {
|
||||
pubkey: Pubkey,
|
||||
timeline_id: TimelineId,
|
||||
columns: &'a mut Columns,
|
||||
ndb: &'a Ndb,
|
||||
@@ -24,6 +25,7 @@ pub struct ProfileView<'a> {
|
||||
|
||||
impl<'a> ProfileView<'a> {
|
||||
pub fn new(
|
||||
pubkey: Pubkey,
|
||||
timeline_id: TimelineId,
|
||||
columns: &'a mut Columns,
|
||||
ndb: &'a Ndb,
|
||||
@@ -31,6 +33,7 @@ impl<'a> ProfileView<'a> {
|
||||
img_cache: &'a mut ImageCache,
|
||||
) -> Self {
|
||||
ProfileView {
|
||||
pubkey,
|
||||
timeline_id,
|
||||
columns,
|
||||
ndb,
|
||||
@@ -40,18 +43,28 @@ impl<'a> ProfileView<'a> {
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> TimelineResponse {
|
||||
ui.add(Label::new(
|
||||
RichText::new("PROFILE VIEW").text_style(egui::TextStyle::Heading),
|
||||
));
|
||||
let scroll_id = egui::Id::new(("profile_scroll", self.timeline_id, self.pubkey));
|
||||
|
||||
TimelineView::new(
|
||||
self.timeline_id,
|
||||
self.columns,
|
||||
self.ndb,
|
||||
self.note_cache,
|
||||
self.img_cache,
|
||||
false,
|
||||
)
|
||||
.ui(ui)
|
||||
ScrollArea::vertical()
|
||||
.id_source(scroll_id)
|
||||
.show(ui, |ui| {
|
||||
{
|
||||
let txn = Transaction::new(self.ndb).expect("txn");
|
||||
if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, self.pubkey.bytes()) {
|
||||
ProfilePreview::new(&profile, self.img_cache).ui(ui);
|
||||
}
|
||||
}
|
||||
|
||||
TimelineView::new(
|
||||
self.timeline_id,
|
||||
self.columns,
|
||||
self.ndb,
|
||||
self.note_cache,
|
||||
self.img_cache,
|
||||
false,
|
||||
)
|
||||
.ui_no_scroll(ui)
|
||||
})
|
||||
.inner
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,23 @@ impl<'a> TimelineView<'a> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn ui_no_scroll(&mut self, ui: &mut egui::Ui) -> TimelineResponse {
|
||||
if let Some(timeline) = self.columns.find_timeline_mut(self.timeline_id) {
|
||||
timeline.selected_view = tabs_ui(ui);
|
||||
};
|
||||
|
||||
timeline_ui_no_scroll(
|
||||
ui,
|
||||
self.ndb,
|
||||
self.timeline_id,
|
||||
self.columns,
|
||||
self.note_cache,
|
||||
self.img_cache,
|
||||
self.reverse,
|
||||
self.textmode,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn reversed(mut self) -> Self {
|
||||
self.reverse = true;
|
||||
self
|
||||
@@ -96,82 +113,105 @@ fn timeline_ui(
|
||||
egui::Id::new(("tlscroll", timeline.view_id()))
|
||||
};
|
||||
|
||||
let mut open_profile: Option<Pubkey> = None;
|
||||
let mut bar_action: Option<BarAction> = None;
|
||||
egui::ScrollArea::vertical()
|
||||
.id_source(scroll_id)
|
||||
.animated(false)
|
||||
.auto_shrink([false, false])
|
||||
.scroll_bar_visibility(ScrollBarVisibility::AlwaysVisible)
|
||||
.show(ui, |ui| {
|
||||
let timeline = if let Some(timeline) = columns.find_timeline_mut(timeline_id) {
|
||||
timeline
|
||||
timeline_ui_no_scroll(
|
||||
ui,
|
||||
ndb,
|
||||
timeline_id,
|
||||
columns,
|
||||
note_cache,
|
||||
img_cache,
|
||||
reversed,
|
||||
textmode,
|
||||
)
|
||||
})
|
||||
.inner
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn timeline_ui_no_scroll(
|
||||
ui: &mut egui::Ui,
|
||||
ndb: &Ndb,
|
||||
timeline_id: TimelineId,
|
||||
columns: &mut Columns,
|
||||
note_cache: &mut NoteCache,
|
||||
img_cache: &mut ImageCache,
|
||||
reversed: bool,
|
||||
textmode: bool,
|
||||
) -> TimelineResponse {
|
||||
let mut open_profile: Option<Pubkey> = None;
|
||||
let mut bar_action: Option<BarAction> = None;
|
||||
|
||||
let timeline = if let Some(timeline) = columns.find_timeline_mut(timeline_id) {
|
||||
timeline
|
||||
} else {
|
||||
error!("tried to render timeline in column, but timeline was missing");
|
||||
// TODO (jb55): render error when timeline is missing?
|
||||
// this shouldn't happen...
|
||||
return TimelineResponse::default();
|
||||
};
|
||||
|
||||
let view = timeline.current_view();
|
||||
let len = view.notes.len();
|
||||
let txn = if let Ok(txn) = Transaction::new(ndb) {
|
||||
txn
|
||||
} else {
|
||||
warn!("failed to create transaction");
|
||||
return TimelineResponse::default();
|
||||
};
|
||||
|
||||
view.list
|
||||
.clone()
|
||||
.borrow_mut()
|
||||
.ui_custom_layout(ui, len, |ui, start_index| {
|
||||
ui.spacing_mut().item_spacing.y = 0.0;
|
||||
ui.spacing_mut().item_spacing.x = 4.0;
|
||||
|
||||
let ind = if reversed {
|
||||
len - start_index - 1
|
||||
} else {
|
||||
error!("tried to render timeline in column, but timeline was missing");
|
||||
// TODO (jb55): render error when timeline is missing?
|
||||
// this shouldn't happen...
|
||||
start_index
|
||||
};
|
||||
|
||||
let note_key = timeline.current_view().notes[ind].key;
|
||||
|
||||
let note = if let Ok(note) = ndb.get_note_by_key(&txn, note_key) {
|
||||
note
|
||||
} else {
|
||||
warn!("failed to query note {:?}", note_key);
|
||||
return 0;
|
||||
};
|
||||
|
||||
let view = timeline.current_view();
|
||||
let len = view.notes.len();
|
||||
let txn = if let Ok(txn) = Transaction::new(ndb) {
|
||||
txn
|
||||
} else {
|
||||
warn!("failed to create transaction");
|
||||
return 0;
|
||||
};
|
||||
ui::padding(8.0, ui, |ui| {
|
||||
let resp = ui::NoteView::new(ndb, note_cache, img_cache, ¬e)
|
||||
.note_previews(!textmode)
|
||||
.selectable_text(false)
|
||||
.options_button(true)
|
||||
.show(ui);
|
||||
|
||||
view.list
|
||||
.clone()
|
||||
.borrow_mut()
|
||||
.ui_custom_layout(ui, len, |ui, start_index| {
|
||||
ui.spacing_mut().item_spacing.y = 0.0;
|
||||
ui.spacing_mut().item_spacing.x = 4.0;
|
||||
if let Some(ba) = resp.action {
|
||||
bar_action = Some(ba);
|
||||
} else if resp.response.clicked() {
|
||||
debug!("clicked note");
|
||||
}
|
||||
|
||||
let ind = if reversed {
|
||||
len - start_index - 1
|
||||
} else {
|
||||
start_index
|
||||
};
|
||||
if let Some(context) = resp.context_selection {
|
||||
context.process(ui, ¬e);
|
||||
}
|
||||
|
||||
let note_key = timeline.current_view().notes[ind].key;
|
||||
if resp.clicked_profile {
|
||||
info!("clicked profile");
|
||||
open_profile = Some(Pubkey::new(*note.pubkey()))
|
||||
}
|
||||
});
|
||||
|
||||
let note = if let Ok(note) = ndb.get_note_by_key(&txn, note_key) {
|
||||
note
|
||||
} else {
|
||||
warn!("failed to query note {:?}", note_key);
|
||||
return 0;
|
||||
};
|
||||
|
||||
ui::padding(8.0, ui, |ui| {
|
||||
let resp = ui::NoteView::new(ndb, note_cache, img_cache, ¬e)
|
||||
.note_previews(!textmode)
|
||||
.selectable_text(false)
|
||||
.options_button(true)
|
||||
.show(ui);
|
||||
|
||||
if let Some(ba) = resp.action {
|
||||
bar_action = Some(ba);
|
||||
} else if resp.response.clicked() {
|
||||
debug!("clicked note");
|
||||
}
|
||||
|
||||
if let Some(context) = resp.context_selection {
|
||||
context.process(ui, ¬e);
|
||||
}
|
||||
|
||||
if resp.clicked_profile {
|
||||
info!("clicked profile");
|
||||
open_profile = Some(Pubkey::new(*note.pubkey()))
|
||||
}
|
||||
});
|
||||
|
||||
ui::hline(ui);
|
||||
//ui.add(egui::Separator::default().spacing(0.0));
|
||||
|
||||
1
|
||||
});
|
||||
ui::hline(ui);
|
||||
//ui.add(egui::Separator::default().spacing(0.0));
|
||||
|
||||
1
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user