integrate profile view caching
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -14,6 +14,7 @@ use crate::{
|
||||
note::NoteRef,
|
||||
notecache::{CachedNote, NoteCache},
|
||||
notes_holder::NotesHolderStorage,
|
||||
profile::Profile,
|
||||
subscriptions::{SubKind, Subscriptions},
|
||||
thread::Thread,
|
||||
timeline::{Timeline, TimelineId, TimelineKind, ViewFilter},
|
||||
@@ -55,6 +56,7 @@ pub struct Damus {
|
||||
pub unknown_ids: UnknownIds,
|
||||
pub drafts: Drafts,
|
||||
pub threads: NotesHolderStorage<Thread>,
|
||||
pub profiles: NotesHolderStorage<Profile>,
|
||||
pub img_cache: ImageCache,
|
||||
pub accounts: AccountManager,
|
||||
pub subscriptions: Subscriptions,
|
||||
@@ -711,6 +713,7 @@ impl Damus {
|
||||
subscriptions: Subscriptions::default(),
|
||||
since_optimize: parsed_args.since_optimize,
|
||||
threads: NotesHolderStorage::default(),
|
||||
profiles: NotesHolderStorage::default(),
|
||||
drafts: Drafts::default(),
|
||||
state: DamusState::Initializing,
|
||||
img_cache: ImageCache::new(imgcache_dir.into()),
|
||||
@@ -792,6 +795,7 @@ impl Damus {
|
||||
subscriptions: Subscriptions::default(),
|
||||
since_optimize: true,
|
||||
threads: NotesHolderStorage::default(),
|
||||
profiles: NotesHolderStorage::default(),
|
||||
drafts: Drafts::default(),
|
||||
state: DamusState::Initializing,
|
||||
pool: RelayPool::new(),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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};
|
||||
@@ -61,14 +60,6 @@ impl Columns {
|
||||
self.timelines.insert(col_id, timeline);
|
||||
}
|
||||
|
||||
pub fn route_profile_timeline(&mut self, col: usize, pubkey: Pubkey, timeline: Timeline) {
|
||||
self.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(Route::Profile(pubkey, timeline.id));
|
||||
|
||||
self.timelines.insert(Self::get_new_id(), timeline);
|
||||
}
|
||||
|
||||
pub fn new_column_picker(&mut self) {
|
||||
self.add_column(Column::new(vec![Route::AddColumn]));
|
||||
}
|
||||
|
||||
46
src/nav.rs
46
src/nav.rs
@@ -3,12 +3,13 @@ use crate::{
|
||||
app_style::{get_font_size, NotedeckTextStyle},
|
||||
fonts::NamedFontFamily,
|
||||
notes_holder::NotesHolder,
|
||||
profile::Profile,
|
||||
relay_pool_manager::RelayPoolManager,
|
||||
route::Route,
|
||||
thread::Thread,
|
||||
timeline::{
|
||||
route::{render_profile_route, render_timeline_route, AfterRouteExecution, TimelineRoute},
|
||||
PubkeySource, Timeline, TimelineKind,
|
||||
Timeline,
|
||||
},
|
||||
ui::{
|
||||
self,
|
||||
@@ -115,11 +116,11 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
None
|
||||
}
|
||||
|
||||
Route::Profile(pubkey, id) => render_profile_route(
|
||||
*id,
|
||||
Route::Profile(pubkey) => render_profile_route(
|
||||
*pubkey,
|
||||
&app.ndb,
|
||||
&mut app.columns,
|
||||
&mut app.profiles,
|
||||
&mut app.pool,
|
||||
&mut app.img_cache,
|
||||
&mut app.note_cache,
|
||||
@@ -144,18 +145,19 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
}
|
||||
|
||||
AfterRouteExecution::OpenProfile(pubkey) => {
|
||||
let pubkey_source = match app.accounts.get_selected_account() {
|
||||
Some(account) if account.pubkey == pubkey => PubkeySource::DeckAuthor,
|
||||
_ => PubkeySource::Explicit(pubkey),
|
||||
};
|
||||
|
||||
if let Some(timeline) =
|
||||
TimelineKind::profile(pubkey_source).into_timeline(&app.ndb, None)
|
||||
{
|
||||
let timeline_id = timeline.id;
|
||||
app.columns_mut()
|
||||
.route_profile_timeline(col, pubkey, timeline);
|
||||
app.subscribe_new_timeline(timeline_id);
|
||||
app.columns
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(Route::Profile(pubkey));
|
||||
let txn = Transaction::new(&app.ndb).expect("txn");
|
||||
if let Some(res) = Profile::open(
|
||||
&app.ndb,
|
||||
&txn,
|
||||
&mut app.pool,
|
||||
&mut app.profiles,
|
||||
pubkey.bytes(),
|
||||
) {
|
||||
res.process(&app.ndb, &txn, &mut app.profiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,8 +165,8 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
|
||||
if let Some(NavAction::Returned) = nav_response.action {
|
||||
let r = app.columns_mut().column_mut(col).router_mut().pop();
|
||||
let txn = Transaction::new(&app.ndb).expect("txn");
|
||||
if let Some(Route::Timeline(TimelineRoute::Thread(id))) = r {
|
||||
let txn = Transaction::new(&app.ndb).expect("txn");
|
||||
let root_id = {
|
||||
crate::note::root_note_id_from_selected_id(
|
||||
&app.ndb,
|
||||
@@ -176,10 +178,14 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
Thread::unsubscribe_locally(&txn, &app.ndb, &mut app.threads, &mut app.pool, root_id);
|
||||
}
|
||||
|
||||
if let Some(Route::Profile(_, id)) = r {
|
||||
if let Some(timeline) = app.columns.find_timeline(id) {
|
||||
unsubscribe_timeline(&app.ndb, timeline);
|
||||
}
|
||||
if let Some(Route::Profile(pubkey)) = r {
|
||||
Profile::unsubscribe_locally(
|
||||
&txn,
|
||||
&app.ndb,
|
||||
&mut app.profiles,
|
||||
&mut app.pool,
|
||||
pubkey.bytes(),
|
||||
);
|
||||
}
|
||||
} else if let Some(NavAction::Navigated) = nav_response.action {
|
||||
let cur_router = app.columns_mut().column_mut(col).router_mut();
|
||||
|
||||
@@ -9,11 +9,18 @@ use crate::{
|
||||
timeline::TimelineTab, Error, Result,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NotesHolderStorage<M: NotesHolder> {
|
||||
pub id_to_object: HashMap<[u8; 32], M>,
|
||||
}
|
||||
|
||||
impl<M: NotesHolder> Default for NotesHolderStorage<M> {
|
||||
fn default() -> Self {
|
||||
NotesHolderStorage {
|
||||
id_to_object: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Vitality<'a, M> {
|
||||
Fresh(&'a mut M),
|
||||
Stale(&'a mut M),
|
||||
@@ -75,8 +82,10 @@ impl<M: NotesHolder> NotesHolderStorage<M> {
|
||||
debug!("found thread with {} notes", notes.len());
|
||||
}
|
||||
|
||||
self.id_to_object
|
||||
.insert(id.to_owned(), M::new_notes_holder(notes));
|
||||
self.id_to_object.insert(
|
||||
id.to_owned(),
|
||||
M::new_notes_holder(id, M::filters(id), notes),
|
||||
);
|
||||
Vitality::Fresh(self.id_to_object.get_mut(id).unwrap())
|
||||
}
|
||||
}
|
||||
@@ -87,7 +96,7 @@ pub trait NotesHolder {
|
||||
fn get_view(&mut self) -> &mut TimelineTab;
|
||||
fn filters(for_id: &[u8; 32]) -> Vec<Filter>;
|
||||
fn filters_since(for_id: &[u8; 32], since: u64) -> Vec<Filter>;
|
||||
fn new_notes_holder(notes: Vec<NoteRef>) -> Self;
|
||||
fn new_notes_holder(id: &[u8; 32], filters: Vec<Filter>, notes: Vec<NoteRef>) -> Self;
|
||||
|
||||
#[must_use = "UnknownIds::update_from_note_refs should be used on this result"]
|
||||
fn poll_notes_into_view(&mut self, txn: &Transaction, ndb: &Ndb) -> Result<()> {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use enostr::Filter;
|
||||
use enostr::{Filter, Pubkey};
|
||||
use nostrdb::{FilterBuilder, ProfileRecord};
|
||||
|
||||
use crate::{
|
||||
filter,
|
||||
filter::{self, FilterState},
|
||||
multi_subscriber::MultiSubscriber,
|
||||
note::NoteRef,
|
||||
notes_holder::NotesHolder,
|
||||
timeline::{Timeline, TimelineTab, ViewFilter},
|
||||
timeline::{PubkeySource, Timeline, TimelineKind},
|
||||
};
|
||||
|
||||
pub enum DisplayName<'a> {
|
||||
@@ -48,21 +48,18 @@ pub fn get_profile_name<'a>(record: &'a ProfileRecord) -> Option<DisplayName<'a>
|
||||
}
|
||||
|
||||
pub struct Profile {
|
||||
view: TimelineTab,
|
||||
pub timeline: Timeline,
|
||||
pub multi_subscriber: Option<MultiSubscriber>,
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
pub fn new(notes: Vec<NoteRef>) -> Self {
|
||||
let mut cap = ((notes.len() as f32) * 1.5) as usize;
|
||||
if cap == 0 {
|
||||
cap = 25;
|
||||
}
|
||||
let mut view = TimelineTab::new_with_capacity(ViewFilter::NotesAndReplies, cap);
|
||||
view.notes = notes;
|
||||
pub fn new(source: PubkeySource, filters: Vec<Filter>, notes: Vec<NoteRef>) -> Self {
|
||||
let mut timeline =
|
||||
Timeline::new(TimelineKind::profile(source), FilterState::ready(filters));
|
||||
timeline.current_view_mut().notes = notes;
|
||||
|
||||
Profile {
|
||||
view,
|
||||
timeline,
|
||||
multi_subscriber: None,
|
||||
}
|
||||
}
|
||||
@@ -81,7 +78,7 @@ impl NotesHolder for Profile {
|
||||
}
|
||||
|
||||
fn get_view(&mut self) -> &mut crate::timeline::TimelineTab {
|
||||
&mut self.view
|
||||
self.timeline.current_view_mut()
|
||||
}
|
||||
|
||||
fn filters(for_id: &[u8; 32]) -> Vec<enostr::Filter> {
|
||||
@@ -98,7 +95,11 @@ impl NotesHolder for Profile {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn new_notes_holder(notes: Vec<NoteRef>) -> Self {
|
||||
Profile::new(notes)
|
||||
fn new_notes_holder(id: &[u8; 32], filters: Vec<Filter>, notes: Vec<NoteRef>) -> Self {
|
||||
Profile::new(PubkeySource::Explicit(Pubkey::new(*id)), filters, notes)
|
||||
}
|
||||
|
||||
fn set_multi_subscriber(&mut self, subscriber: MultiSubscriber) {
|
||||
self.multi_subscriber = Some(subscriber);
|
||||
}
|
||||
}
|
||||
|
||||
13
src/route.rs
13
src/route.rs
@@ -6,7 +6,7 @@ use crate::{
|
||||
account_manager::AccountsRoute,
|
||||
column::Columns,
|
||||
timeline::{TimelineId, TimelineRoute},
|
||||
ui::profile::preview::get_note_users_displayname_string,
|
||||
ui::profile::preview::{get_note_users_displayname_string, get_profile_displayname_string},
|
||||
};
|
||||
|
||||
/// App routing. These describe different places you can go inside Notedeck.
|
||||
@@ -17,7 +17,7 @@ pub enum Route {
|
||||
Relays,
|
||||
ComposeNote,
|
||||
AddColumn,
|
||||
Profile(Pubkey, TimelineId),
|
||||
Profile(Pubkey),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -97,11 +97,8 @@ impl Route {
|
||||
},
|
||||
Route::ComposeNote => "Compose Note".to_owned(),
|
||||
Route::AddColumn => "Add Column".to_owned(),
|
||||
Route::Profile(_, id) => {
|
||||
let timeline = columns
|
||||
.find_timeline(*id)
|
||||
.expect("expected to find timeline");
|
||||
timeline.kind.to_title(ndb)
|
||||
Route::Profile(pubkey) => {
|
||||
format!("{}'s Profile", get_profile_displayname_string(ndb, pubkey))
|
||||
}
|
||||
};
|
||||
|
||||
@@ -210,7 +207,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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ impl NotesHolder for Thread {
|
||||
Thread::filters(for_id)
|
||||
}
|
||||
|
||||
fn new_notes_holder(notes: Vec<NoteRef>) -> Self {
|
||||
fn new_notes_holder(_: &[u8; 32], _: Vec<Filter>, notes: Vec<NoteRef>) -> Self {
|
||||
Thread::new(notes)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::{
|
||||
imgcache::ImageCache,
|
||||
notecache::NoteCache,
|
||||
notes_holder::NotesHolderStorage,
|
||||
profile::Profile,
|
||||
thread::Thread,
|
||||
timeline::TimelineId,
|
||||
ui::{
|
||||
@@ -156,10 +157,10 @@ pub fn render_timeline_route(
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn render_profile_route(
|
||||
id: TimelineId,
|
||||
pubkey: Pubkey,
|
||||
ndb: &Ndb,
|
||||
columns: &mut Columns,
|
||||
profiles: &mut NotesHolderStorage<Profile>,
|
||||
pool: &mut RelayPool,
|
||||
img_cache: &mut ImageCache,
|
||||
note_cache: &mut NoteCache,
|
||||
@@ -168,7 +169,7 @@ pub fn render_profile_route(
|
||||
ui: &mut egui::Ui,
|
||||
) -> Option<AfterRouteExecution> {
|
||||
let timeline_response =
|
||||
ProfileView::new(pubkey, id, columns, ndb, note_cache, img_cache).ui(ui);
|
||||
ProfileView::new(pubkey, col, profiles, 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();
|
||||
|
||||
@@ -8,16 +8,16 @@ pub use picture::ProfilePic;
|
||||
pub use preview::ProfilePreview;
|
||||
|
||||
use crate::{
|
||||
actionbar::TimelineResponse, column::Columns, imgcache::ImageCache, notecache::NoteCache,
|
||||
timeline::TimelineId,
|
||||
actionbar::TimelineResponse, imgcache::ImageCache, notecache::NoteCache,
|
||||
notes_holder::NotesHolderStorage, profile::Profile,
|
||||
};
|
||||
|
||||
use super::TimelineView;
|
||||
use super::timeline::{tabs_ui, TimelineTabView};
|
||||
|
||||
pub struct ProfileView<'a> {
|
||||
pubkey: Pubkey,
|
||||
timeline_id: TimelineId,
|
||||
columns: &'a mut Columns,
|
||||
col_id: usize,
|
||||
profiles: &'a mut NotesHolderStorage<Profile>,
|
||||
ndb: &'a Ndb,
|
||||
note_cache: &'a mut NoteCache,
|
||||
img_cache: &'a mut ImageCache,
|
||||
@@ -26,16 +26,16 @@ pub struct ProfileView<'a> {
|
||||
impl<'a> ProfileView<'a> {
|
||||
pub fn new(
|
||||
pubkey: Pubkey,
|
||||
timeline_id: TimelineId,
|
||||
columns: &'a mut Columns,
|
||||
col_id: usize,
|
||||
profiles: &'a mut NotesHolderStorage<Profile>,
|
||||
ndb: &'a Ndb,
|
||||
note_cache: &'a mut NoteCache,
|
||||
img_cache: &'a mut ImageCache,
|
||||
) -> Self {
|
||||
ProfileView {
|
||||
pubkey,
|
||||
timeline_id,
|
||||
columns,
|
||||
col_id,
|
||||
profiles,
|
||||
ndb,
|
||||
note_cache,
|
||||
img_cache,
|
||||
@@ -43,27 +43,32 @@ impl<'a> ProfileView<'a> {
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> TimelineResponse {
|
||||
let scroll_id = egui::Id::new(("profile_scroll", self.timeline_id, self.pubkey));
|
||||
let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey));
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
let profile = self
|
||||
.profiles
|
||||
.notes_holder_mutated(self.ndb, &txn, self.pubkey.bytes())
|
||||
.get_ptr();
|
||||
|
||||
TimelineView::new(
|
||||
self.timeline_id,
|
||||
self.columns,
|
||||
profile.timeline.selected_view = tabs_ui(ui);
|
||||
|
||||
TimelineTabView::new(
|
||||
profile.timeline.current_view(),
|
||||
false,
|
||||
false,
|
||||
&txn,
|
||||
self.ndb,
|
||||
self.note_cache,
|
||||
self.img_cache,
|
||||
false,
|
||||
)
|
||||
.ui_no_scroll(ui)
|
||||
.show(ui)
|
||||
})
|
||||
.inner
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ fn timeline_ui_no_scroll(
|
||||
.show(ui)
|
||||
}
|
||||
|
||||
fn tabs_ui(ui: &mut egui::Ui) -> i32 {
|
||||
pub fn tabs_ui(ui: &mut egui::Ui) -> i32 {
|
||||
ui.spacing_mut().item_spacing.y = 0.0;
|
||||
|
||||
let tab_res = egui_tabs::Tabs::new(2)
|
||||
|
||||
Reference in New Issue
Block a user