Skip muted content

This commit is contained in:
Ken Sedgwick
2024-11-19 12:59:53 -08:00
parent d595631966
commit 84838478b3
14 changed files with 134 additions and 37 deletions

View File

@@ -1,11 +1,12 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
use enostr::{ClientMessage, FilledKeypair, FullKeypair, Keypair, RelayPool}; use enostr::{ClientMessage, FilledKeypair, FullKeypair, Keypair, RelayPool};
use nostrdb::{Filter, Ndb, NoteKey, Subscription, Transaction}; use nostrdb::{Filter, Ndb, Note, NoteKey, Subscription, Transaction};
use crate::{ use crate::{
column::Columns, column::Columns,
@@ -121,7 +122,7 @@ pub struct AccountMutedData {
filter: Filter, filter: Filter,
subid: String, subid: String,
sub: Option<Subscription>, sub: Option<Subscription>,
muted: Muted, muted: Arc<Muted>,
} }
impl AccountMutedData { impl AccountMutedData {
@@ -160,7 +161,7 @@ impl AccountMutedData {
filter, filter,
subid, subid,
sub: Some(ndbsub), sub: Some(ndbsub),
muted, muted: Arc::new(muted),
} }
} }
@@ -440,6 +441,19 @@ impl Accounts {
self.key_store.select_key(None); self.key_store.select_key(None);
} }
pub fn mutefun(&self) -> Box<dyn Fn(&Note) -> bool> {
if let Some(index) = self.currently_selected_account {
if let Some(account) = self.accounts.get(index) {
let pubkey = account.pubkey.bytes();
if let Some(account_data) = self.account_data.get(pubkey) {
let muted = Arc::clone(&account_data.muted.muted);
return Box::new(move |note: &Note| muted.is_muted(note));
}
}
}
Box::new(|_: &Note| false)
}
pub fn send_initial_filters(&mut self, pool: &mut RelayPool, relay_url: &str) { pub fn send_initial_filters(&mut self, pool: &mut RelayPool, relay_url: &str) {
for data in self.account_data.values() { for data in self.account_data.values() {
pool.send_to( pool.send_to(
@@ -510,7 +524,7 @@ impl Accounts {
let txn = Transaction::new(ndb).expect("txn"); let txn = Transaction::new(ndb).expect("txn");
let muted = AccountMutedData::harvest_nip51_muted(ndb, &txn, &nks); let muted = AccountMutedData::harvest_nip51_muted(ndb, &txn, &nks);
debug!("pubkey {}: updated muted {:?}", hex::encode(pubkey), muted); debug!("pubkey {}: updated muted {:?}", hex::encode(pubkey), muted);
data.muted.muted = muted; data.muted.muted = Arc::new(muted);
changed = true; changed = true;
} }
} }

View File

@@ -1,5 +1,6 @@
use crate::{ use crate::{
column::Columns, column::Columns,
muted::MuteFun,
note::NoteRef, note::NoteRef,
notecache::NoteCache, notecache::NoteCache,
notes_holder::{NotesHolder, NotesHolderStorage}, notes_holder::{NotesHolder, NotesHolderStorage},
@@ -32,6 +33,7 @@ pub enum NotesHolderResult {
/// making sure the thread is up to date. In a sense, it's a model for /// making sure the thread is up to date. In a sense, it's a model for
/// the thread view. We don't have a concept of model/view/controller etc /// the thread view. We don't have a concept of model/view/controller etc
/// in egui, but this is the closest thing to that. /// in egui, but this is the closest thing to that.
#[allow(clippy::too_many_arguments)]
fn open_thread( fn open_thread(
ndb: &Ndb, ndb: &Ndb,
txn: &Transaction, txn: &Transaction,
@@ -40,11 +42,12 @@ fn open_thread(
pool: &mut RelayPool, pool: &mut RelayPool,
threads: &mut NotesHolderStorage<Thread>, threads: &mut NotesHolderStorage<Thread>,
selected_note: &[u8; 32], selected_note: &[u8; 32],
is_muted: &MuteFun,
) -> Option<NotesHolderResult> { ) -> Option<NotesHolderResult> {
router.route_to(Route::thread(NoteId::new(selected_note.to_owned()))); router.route_to(Route::thread(NoteId::new(selected_note.to_owned())));
let root_id = crate::note::root_note_id_from_selected_id(ndb, note_cache, txn, selected_note); let root_id = crate::note::root_note_id_from_selected_id(ndb, note_cache, txn, selected_note);
Thread::open(ndb, note_cache, txn, pool, threads, root_id) Thread::open(ndb, note_cache, txn, pool, threads, root_id, is_muted)
} }
impl NoteAction { impl NoteAction {
@@ -58,6 +61,7 @@ impl NoteAction {
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
pool: &mut RelayPool, pool: &mut RelayPool,
txn: &Transaction, txn: &Transaction,
is_muted: &MuteFun,
) -> Option<NotesHolderResult> { ) -> Option<NotesHolderResult> {
match self { match self {
NoteAction::Reply(note_id) => { NoteAction::Reply(note_id) => {
@@ -65,13 +69,28 @@ impl NoteAction {
None None
} }
NoteAction::OpenThread(note_id) => { NoteAction::OpenThread(note_id) => open_thread(
open_thread(ndb, txn, router, note_cache, pool, threads, note_id.bytes()) ndb,
} txn,
router,
note_cache,
pool,
threads,
note_id.bytes(),
is_muted,
),
NoteAction::OpenProfile(pubkey) => { NoteAction::OpenProfile(pubkey) => {
router.route_to(Route::profile(pubkey)); router.route_to(Route::profile(pubkey));
Profile::open(ndb, note_cache, txn, pool, profiles, pubkey.bytes()) Profile::open(
ndb,
note_cache,
txn,
pool,
profiles,
pubkey.bytes(),
is_muted,
)
} }
NoteAction::Quote(note_id) => { NoteAction::Quote(note_id) => {
@@ -93,10 +112,13 @@ impl NoteAction {
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
pool: &mut RelayPool, pool: &mut RelayPool,
txn: &Transaction, txn: &Transaction,
is_muted: &MuteFun,
) { ) {
let router = columns.column_mut(col).router_mut(); let router = columns.column_mut(col).router_mut();
if let Some(br) = self.execute(ndb, router, threads, profiles, note_cache, pool, txn) { if let Some(br) = self.execute(
br.process(ndb, note_cache, txn, threads); ndb, router, threads, profiles, note_cache, pool, txn, is_muted,
) {
br.process(ndb, note_cache, txn, threads, is_muted);
} }
} }
} }
@@ -112,12 +134,13 @@ impl NotesHolderResult {
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
txn: &Transaction, txn: &Transaction,
storage: &mut NotesHolderStorage<N>, storage: &mut NotesHolderStorage<N>,
is_muted: &MuteFun,
) { ) {
match self { match self {
// update the thread for next render if we have new notes // update the thread for next render if we have new notes
NotesHolderResult::NewNotes(new_notes) => { NotesHolderResult::NewNotes(new_notes) => {
let holder = storage let holder = storage
.notes_holder_mutated(ndb, note_cache, txn, &new_notes.id) .notes_holder_mutated(ndb, note_cache, txn, &new_notes.id, is_muted)
.get_ptr(); .get_ptr();
new_notes.process(holder); new_notes.process(holder);
} }

View File

@@ -147,6 +147,7 @@ fn try_process_event(damus: &mut Damus, ctx: &egui::Context) -> Result<()> {
&mut damus.pool, &mut damus.pool,
&mut damus.note_cache, &mut damus.note_cache,
timeline, timeline,
&damus.accounts.mutefun(),
) )
}; };
@@ -160,6 +161,7 @@ fn try_process_event(damus: &mut Damus, ctx: &egui::Context) -> Result<()> {
&txn, &txn,
&mut damus.unknown_ids, &mut damus.unknown_ids,
&mut damus.note_cache, &mut damus.note_cache,
&damus.accounts.mutefun(),
) { ) {
error!("poll_notes_into_view: {err}"); error!("poll_notes_into_view: {err}");
} }
@@ -208,6 +210,7 @@ fn update_damus(damus: &mut Damus, ctx: &egui::Context) {
&damus.ndb, &damus.ndb,
&mut damus.note_cache, &mut damus.note_cache,
&mut damus.columns, &mut damus.columns,
&damus.accounts.mutefun(),
) { ) {
warn!("update_damus init: {err}"); warn!("update_damus init: {err}");
} }

View File

@@ -3,7 +3,7 @@ use nostrdb::{Ndb, Note, Transaction};
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use uuid::Uuid; use uuid::Uuid;
use crate::{filter::UnifiedSubscription, note::NoteRef, Error}; use crate::{filter::UnifiedSubscription, muted::MuteFun, note::NoteRef, Error};
pub struct MultiSubscriber { pub struct MultiSubscriber {
filters: Vec<Filter>, filters: Vec<Filter>,
@@ -105,7 +105,12 @@ impl MultiSubscriber {
} }
} }
pub fn poll_for_notes(&mut self, ndb: &Ndb, txn: &Transaction) -> Result<Vec<NoteRef>, Error> { pub fn poll_for_notes(
&mut self,
ndb: &Ndb,
txn: &Transaction,
is_muted: &MuteFun,
) -> Result<Vec<NoteRef>, Error> {
let sub = self.sub.as_ref().ok_or(Error::no_active_sub())?; let sub = self.sub.as_ref().ok_or(Error::no_active_sub())?;
let new_note_keys = ndb.poll_for_notes(sub.local, 500); let new_note_keys = ndb.poll_for_notes(sub.local, 500);
@@ -123,6 +128,10 @@ impl MultiSubscriber {
continue; continue;
}; };
if is_muted(&note) {
continue;
}
notes.push(note); notes.push(note);
} }

View File

@@ -3,6 +3,8 @@ use std::collections::BTreeSet;
use tracing::debug; use tracing::debug;
pub type MuteFun = dyn Fn(&Note) -> bool;
#[derive(Default)] #[derive(Default)]
pub struct Muted { pub struct Muted {
// TODO - implement private mutes // TODO - implement private mutes

View File

@@ -85,6 +85,7 @@ impl RenderNavResponse {
&mut app.note_cache, &mut app.note_cache,
&mut app.pool, &mut app.pool,
&txn, &txn,
&app.accounts.mutefun(),
); );
} }
} }
@@ -109,6 +110,7 @@ impl RenderNavResponse {
&mut app.threads, &mut app.threads,
&mut app.pool, &mut app.pool,
root_id, root_id,
&app.accounts.mutefun(),
); );
} }
@@ -120,6 +122,7 @@ impl RenderNavResponse {
&mut app.profiles, &mut app.profiles,
&mut app.pool, &mut app.pool,
pubkey.bytes(), pubkey.bytes(),
&app.accounts.mutefun(),
); );
} }
col_changed = true; col_changed = true;

View File

@@ -5,7 +5,7 @@ use nostrdb::{Ndb, Transaction};
use tracing::{debug, info, warn}; use tracing::{debug, info, warn};
use crate::{ use crate::{
actionbar::NotesHolderResult, multi_subscriber::MultiSubscriber, note::NoteRef, actionbar::NotesHolderResult, multi_subscriber::MultiSubscriber, muted::MuteFun, note::NoteRef,
notecache::NoteCache, timeline::TimelineTab, unknowns::NoteRefsUnkIdAction, Error, Result, notecache::NoteCache, timeline::TimelineTab, unknowns::NoteRefsUnkIdAction, Error, Result,
}; };
@@ -55,6 +55,7 @@ impl<M: NotesHolder> NotesHolderStorage<M> {
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
txn: &Transaction, txn: &Transaction,
id: &[u8; 32], id: &[u8; 32],
is_muted: &MuteFun,
) -> Vitality<'a, M> { ) -> Vitality<'a, M> {
// we can't use the naive hashmap entry API here because lookups // we can't use the naive hashmap entry API here because lookups
// require a copy, wait until we have a raw entry api. We could // require a copy, wait until we have a raw entry api. We could
@@ -88,7 +89,7 @@ impl<M: NotesHolder> NotesHolderStorage<M> {
self.id_to_object.insert( self.id_to_object.insert(
id.to_owned(), id.to_owned(),
M::new_notes_holder(txn, ndb, note_cache, id, M::filters(id), notes), M::new_notes_holder(txn, ndb, note_cache, id, M::filters(id), notes, is_muted),
); );
Vitality::Fresh(self.id_to_object.get_mut(id).unwrap()) Vitality::Fresh(self.id_to_object.get_mut(id).unwrap())
} }
@@ -107,6 +108,7 @@ pub trait NotesHolder {
id: &[u8; 32], id: &[u8; 32],
filters: Vec<Filter>, filters: Vec<Filter>,
notes: Vec<NoteRef>, notes: Vec<NoteRef>,
is_muted: &MuteFun,
) -> Self; ) -> Self;
#[must_use = "process_action must be handled in the Ok(action) case"] #[must_use = "process_action must be handled in the Ok(action) case"]
@@ -114,10 +116,11 @@ pub trait NotesHolder {
&mut self, &mut self,
txn: &Transaction, txn: &Transaction,
ndb: &Ndb, ndb: &Ndb,
is_muted: &MuteFun,
) -> Result<NoteRefsUnkIdAction> { ) -> Result<NoteRefsUnkIdAction> {
if let Some(multi_subscriber) = self.get_multi_subscriber() { if let Some(multi_subscriber) = self.get_multi_subscriber() {
let reversed = true; let reversed = true;
let note_refs: Vec<NoteRef> = multi_subscriber.poll_for_notes(ndb, txn)?; let note_refs: Vec<NoteRef> = multi_subscriber.poll_for_notes(ndb, txn, is_muted)?;
self.get_view().insert(&note_refs, reversed); self.get_view().insert(&note_refs, reversed);
Ok(NoteRefsUnkIdAction::new(note_refs)) Ok(NoteRefsUnkIdAction::new(note_refs))
} else { } else {
@@ -156,9 +159,10 @@ pub trait NotesHolder {
notes_holder_storage: &mut NotesHolderStorage<M>, notes_holder_storage: &mut NotesHolderStorage<M>,
pool: &mut RelayPool, pool: &mut RelayPool,
id: &[u8; 32], id: &[u8; 32],
is_muted: &MuteFun,
) { ) {
let notes_holder = notes_holder_storage let notes_holder = notes_holder_storage
.notes_holder_mutated(ndb, note_cache, txn, id) .notes_holder_mutated(ndb, note_cache, txn, id, is_muted)
.get_ptr(); .get_ptr();
if let Some(multi_subscriber) = notes_holder.get_multi_subscriber() { if let Some(multi_subscriber) = notes_holder.get_multi_subscriber() {
@@ -173,8 +177,9 @@ pub trait NotesHolder {
pool: &mut RelayPool, pool: &mut RelayPool,
storage: &mut NotesHolderStorage<M>, storage: &mut NotesHolderStorage<M>,
id: &[u8; 32], id: &[u8; 32],
is_muted: &MuteFun,
) -> Option<NotesHolderResult> { ) -> Option<NotesHolderResult> {
let vitality = storage.notes_holder_mutated(ndb, note_cache, txn, id); let vitality = storage.notes_holder_mutated(ndb, note_cache, txn, id, is_muted);
let (holder, result) = match vitality { let (holder, result) = match vitality {
Vitality::Stale(holder) => { Vitality::Stale(holder) => {

View File

@@ -4,6 +4,7 @@ use nostrdb::{FilterBuilder, Ndb, ProfileRecord, Transaction};
use crate::{ use crate::{
filter::{self, FilterState}, filter::{self, FilterState},
multi_subscriber::MultiSubscriber, multi_subscriber::MultiSubscriber,
muted::MuteFun,
note::NoteRef, note::NoteRef,
notecache::NoteCache, notecache::NoteCache,
notes_holder::NotesHolder, notes_holder::NotesHolder,
@@ -61,11 +62,12 @@ impl Profile {
source: PubkeySource, source: PubkeySource,
filters: Vec<Filter>, filters: Vec<Filter>,
notes: Vec<NoteRef>, notes: Vec<NoteRef>,
is_muted: &MuteFun,
) -> Self { ) -> Self {
let mut timeline = let mut timeline =
Timeline::new(TimelineKind::profile(source), FilterState::ready(filters)); Timeline::new(TimelineKind::profile(source), FilterState::ready(filters));
copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes); copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes, is_muted);
Profile { Profile {
timeline, timeline,
@@ -111,6 +113,7 @@ impl NotesHolder for Profile {
id: &[u8; 32], id: &[u8; 32],
filters: Vec<Filter>, filters: Vec<Filter>,
notes: Vec<NoteRef>, notes: Vec<NoteRef>,
is_muted: &MuteFun,
) -> Self { ) -> Self {
Profile::new( Profile::new(
txn, txn,
@@ -119,6 +122,7 @@ impl NotesHolder for Profile {
PubkeySource::Explicit(Pubkey::new(*id)), PubkeySource::Explicit(Pubkey::new(*id)),
filters, filters,
notes, notes,
is_muted,
) )
} }

View File

@@ -1,5 +1,6 @@
use crate::{ use crate::{
multi_subscriber::MultiSubscriber, multi_subscriber::MultiSubscriber,
muted::MuteFun,
note::NoteRef, note::NoteRef,
notecache::NoteCache, notecache::NoteCache,
notes_holder::NotesHolder, notes_holder::NotesHolder,
@@ -74,6 +75,7 @@ impl NotesHolder for Thread {
_: &[u8; 32], _: &[u8; 32],
_: Vec<Filter>, _: Vec<Filter>,
notes: Vec<NoteRef>, notes: Vec<NoteRef>,
_: &MuteFun,
) -> Self { ) -> Self {
Thread::new(notes) Thread::new(notes)
} }

View File

@@ -2,6 +2,7 @@ use crate::{
column::Columns, column::Columns,
error::{Error, FilterError}, error::{Error, FilterError},
filter::{self, FilterState, FilterStates}, filter::{self, FilterState, FilterStates},
muted::MuteFun,
note::NoteRef, note::NoteRef,
notecache::{CachedNote, NoteCache}, notecache::{CachedNote, NoteCache},
subscriptions::{self, SubKind, Subscriptions}, subscriptions::{self, SubKind, Subscriptions},
@@ -277,6 +278,7 @@ impl Timeline {
txn: &Transaction, txn: &Transaction,
unknown_ids: &mut UnknownIds, unknown_ids: &mut UnknownIds,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
is_muted: &MuteFun,
) -> Result<()> { ) -> Result<()> {
let timeline = timelines let timeline = timelines
.get_mut(timeline_idx) .get_mut(timeline_idx)
@@ -299,6 +301,9 @@ impl Timeline {
error!("hit race condition in poll_notes_into_view: https://github.com/damus-io/nostrdb/issues/35 note {:?} was not added to timeline", key); error!("hit race condition in poll_notes_into_view: https://github.com/damus-io/nostrdb/issues/35 note {:?} was not added to timeline", key);
continue; continue;
}; };
if is_muted(&note) {
continue;
}
UnknownIds::update_from_note(txn, ndb, unknown_ids, note_cache, &note); UnknownIds::update_from_note(txn, ndb, unknown_ids, note_cache, &note);
@@ -407,10 +412,11 @@ pub fn setup_new_timeline(
pool: &mut RelayPool, pool: &mut RelayPool,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
since_optimize: bool, since_optimize: bool,
is_muted: &MuteFun,
) { ) {
// if we're ready, setup local subs // if we're ready, setup local subs
if is_timeline_ready(ndb, pool, note_cache, timeline) { if is_timeline_ready(ndb, pool, note_cache, timeline, is_muted) {
if let Err(err) = setup_timeline_nostrdb_sub(ndb, note_cache, timeline) { if let Err(err) = setup_timeline_nostrdb_sub(ndb, note_cache, timeline, is_muted) {
error!("setup_new_timeline: {err}"); error!("setup_new_timeline: {err}");
} }
} }
@@ -540,6 +546,7 @@ fn setup_initial_timeline(
timeline: &mut Timeline, timeline: &mut Timeline,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
filters: &[Filter], filters: &[Filter],
is_muted: &MuteFun,
) -> Result<()> { ) -> Result<()> {
timeline.subscription = Some(ndb.subscribe(filters)?); timeline.subscription = Some(ndb.subscribe(filters)?);
let txn = Transaction::new(ndb)?; let txn = Transaction::new(ndb)?;
@@ -554,7 +561,7 @@ fn setup_initial_timeline(
.map(NoteRef::from_query_result) .map(NoteRef::from_query_result)
.collect(); .collect();
copy_notes_into_timeline(timeline, &txn, ndb, note_cache, notes); copy_notes_into_timeline(timeline, &txn, ndb, note_cache, notes, is_muted);
Ok(()) Ok(())
} }
@@ -565,6 +572,7 @@ pub fn copy_notes_into_timeline(
ndb: &Ndb, ndb: &Ndb,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
notes: Vec<NoteRef>, notes: Vec<NoteRef>,
is_muted: &MuteFun,
) { ) {
let filters = { let filters = {
let views = &timeline.views; let views = &timeline.views;
@@ -576,6 +584,9 @@ pub fn copy_notes_into_timeline(
for note_ref in notes { for note_ref in notes {
for (view, filter) in filters.iter().enumerate() { for (view, filter) in filters.iter().enumerate() {
if let Ok(note) = ndb.get_note_by_key(txn, note_ref.key) { if let Ok(note) = ndb.get_note_by_key(txn, note_ref.key) {
if is_muted(&note) {
continue;
}
if filter( if filter(
note_cache.cached_note_or_insert_mut(note_ref.key, &note), note_cache.cached_note_or_insert_mut(note_ref.key, &note),
&note, &note,
@@ -591,9 +602,10 @@ pub fn setup_initial_nostrdb_subs(
ndb: &Ndb, ndb: &Ndb,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
columns: &mut Columns, columns: &mut Columns,
is_muted: &MuteFun,
) -> Result<()> { ) -> Result<()> {
for timeline in columns.timelines_mut() { for timeline in columns.timelines_mut() {
if let Err(err) = setup_timeline_nostrdb_sub(ndb, note_cache, timeline) { if let Err(err) = setup_timeline_nostrdb_sub(ndb, note_cache, timeline, is_muted) {
error!("setup_initial_nostrdb_subs: {err}"); error!("setup_initial_nostrdb_subs: {err}");
} }
} }
@@ -605,6 +617,7 @@ fn setup_timeline_nostrdb_sub(
ndb: &Ndb, ndb: &Ndb,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
timeline: &mut Timeline, timeline: &mut Timeline,
is_muted: &MuteFun,
) -> Result<()> { ) -> Result<()> {
let filter_state = timeline let filter_state = timeline
.filter .filter
@@ -612,7 +625,7 @@ fn setup_timeline_nostrdb_sub(
.ok_or(Error::empty_contact_list())? .ok_or(Error::empty_contact_list())?
.to_owned(); .to_owned();
setup_initial_timeline(ndb, timeline, note_cache, &filter_state)?; setup_initial_timeline(ndb, timeline, note_cache, &filter_state, is_muted)?;
Ok(()) Ok(())
} }
@@ -626,6 +639,7 @@ pub fn is_timeline_ready(
pool: &mut RelayPool, pool: &mut RelayPool,
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
timeline: &mut Timeline, timeline: &mut Timeline,
is_muted: &MuteFun,
) -> bool { ) -> bool {
// TODO: we should debounce the filter states a bit to make sure we have // TODO: we should debounce the filter states a bit to make sure we have
// seen all of the different contact lists from each relay // seen all of the different contact lists from each relay
@@ -680,7 +694,8 @@ pub fn is_timeline_ready(
// we just switched to the ready state, we should send initial // we just switched to the ready state, we should send initial
// queries and setup the local subscription // queries and setup the local subscription
info!("Found contact list! Setting up local and remote contact list query"); info!("Found contact list! Setting up local and remote contact list query");
setup_initial_timeline(ndb, timeline, note_cache, &filter).expect("setup init"); setup_initial_timeline(ndb, timeline, note_cache, &filter, is_muted)
.expect("setup init");
timeline timeline
.filter .filter
.set_relay_state(relay_id, FilterState::ready(filter.clone())); .set_relay_state(relay_id, FilterState::ready(filter.clone()));

View File

@@ -3,6 +3,7 @@ use crate::{
column::Columns, column::Columns,
draft::Drafts, draft::Drafts,
imgcache::ImageCache, imgcache::ImageCache,
muted::MuteFun,
nav::RenderNavAction, nav::RenderNavAction,
notecache::NoteCache, notecache::NoteCache,
notes_holder::NotesHolderStorage, notes_holder::NotesHolderStorage,
@@ -82,7 +83,7 @@ pub fn render_timeline_route(
textmode, textmode,
) )
.id_source(egui::Id::new(("threadscroll", col))) .id_source(egui::Id::new(("threadscroll", col)))
.ui(ui) .ui(ui, &accounts.mutefun())
.map(Into::into), .map(Into::into),
TimelineRoute::Reply(id) => { TimelineRoute::Reply(id) => {
@@ -118,9 +119,16 @@ pub fn render_timeline_route(
action.map(Into::into) action.map(Into::into)
} }
TimelineRoute::Profile(pubkey) => { TimelineRoute::Profile(pubkey) => render_profile_route(
render_profile_route(&pubkey, ndb, profiles, img_cache, note_cache, col, ui) &pubkey,
} ndb,
profiles,
img_cache,
note_cache,
col,
ui,
&accounts.mutefun(),
),
TimelineRoute::Quote(id) => { TimelineRoute::Quote(id) => {
let txn = Transaction::new(ndb).expect("txn"); let txn = Transaction::new(ndb).expect("txn");
@@ -157,6 +165,7 @@ pub fn render_profile_route(
note_cache: &mut NoteCache, note_cache: &mut NoteCache,
col: usize, col: usize,
ui: &mut egui::Ui, ui: &mut egui::Ui,
is_muted: &MuteFun,
) -> Option<RenderNavAction> { ) -> Option<RenderNavAction> {
let note_action = ProfileView::new( let note_action = ProfileView::new(
pubkey, pubkey,
@@ -167,7 +176,7 @@ pub fn render_profile_route(
img_cache, img_cache,
NoteOptions::default(), NoteOptions::default(),
) )
.ui(ui); .ui(ui, is_muted);
note_action.map(RenderNavAction::NoteAction) note_action.map(RenderNavAction::NoteAction)
} }

View File

@@ -374,6 +374,7 @@ pub fn render_add_column_routes(
&mut app.pool, &mut app.pool,
&mut app.note_cache, &mut app.note_cache,
app.since_optimize, app.since_optimize,
&app.accounts.mutefun(),
); );
app.columns_mut().add_timeline_to_column(col, timeline); app.columns_mut().add_timeline_to_column(col, timeline);
} }

View File

@@ -9,7 +9,7 @@ pub use picture::ProfilePic;
pub use preview::ProfilePreview; pub use preview::ProfilePreview;
use crate::{ use crate::{
actionbar::NoteAction, imgcache::ImageCache, notecache::NoteCache, actionbar::NoteAction, imgcache::ImageCache, muted::MuteFun, notecache::NoteCache,
notes_holder::NotesHolderStorage, profile::Profile, notes_holder::NotesHolderStorage, profile::Profile,
}; };
@@ -46,7 +46,7 @@ impl<'a> ProfileView<'a> {
} }
} }
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> { pub fn ui(&mut self, ui: &mut egui::Ui, is_muted: &MuteFun) -> Option<NoteAction> {
let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey)); let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey));
ScrollArea::vertical() ScrollArea::vertical()
@@ -58,7 +58,13 @@ impl<'a> ProfileView<'a> {
} }
let profile = self let profile = self
.profiles .profiles
.notes_holder_mutated(self.ndb, self.note_cache, &txn, self.pubkey.bytes()) .notes_holder_mutated(
self.ndb,
self.note_cache,
&txn,
self.pubkey.bytes(),
is_muted,
)
.get_ptr(); .get_ptr();
profile.timeline.selected_view = tabs_ui(ui); profile.timeline.selected_view = tabs_ui(ui);

View File

@@ -1,6 +1,7 @@
use crate::{ use crate::{
actionbar::NoteAction, actionbar::NoteAction,
imgcache::ImageCache, imgcache::ImageCache,
muted::MuteFun,
notecache::NoteCache, notecache::NoteCache,
notes_holder::{NotesHolder, NotesHolderStorage}, notes_holder::{NotesHolder, NotesHolderStorage},
thread::Thread, thread::Thread,
@@ -52,7 +53,7 @@ impl<'a> ThreadView<'a> {
self self
} }
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> { pub fn ui(&mut self, ui: &mut egui::Ui, is_muted: &MuteFun) -> Option<NoteAction> {
let txn = Transaction::new(self.ndb).expect("txn"); let txn = Transaction::new(self.ndb).expect("txn");
let selected_note_key = if let Ok(key) = self let selected_note_key = if let Ok(key) = self
@@ -97,13 +98,13 @@ impl<'a> ThreadView<'a> {
let thread = self let thread = self
.threads .threads
.notes_holder_mutated(self.ndb, self.note_cache, &txn, root_id) .notes_holder_mutated(self.ndb, self.note_cache, &txn, root_id, is_muted)
.get_ptr(); .get_ptr();
// TODO(jb55): skip poll if ThreadResult is fresh? // TODO(jb55): skip poll if ThreadResult is fresh?
// poll for new notes and insert them into our existing notes // poll for new notes and insert them into our existing notes
match thread.poll_notes_into_view(&txn, self.ndb) { match thread.poll_notes_into_view(&txn, self.ndb, is_muted) {
Ok(action) => { Ok(action) => {
action.process_action(&txn, self.ndb, self.unknown_ids, self.note_cache) action.process_action(&txn, self.ndb, self.unknown_ids, self.note_cache)
} }