Skip to content

Commit

Permalink
Mute rendering instead of ingress
Browse files Browse the repository at this point in the history
Previous approach was to keep muted content from getting inserted.

Instead, this version alters it's display.  This makes toggling mutes
on and off externally much more stable (the display changes but we
don't have to rebuild content trees)

For now muted content is collapsed to a red "Muted" tombstone w/ a reason.
  • Loading branch information
ksedgwic committed Jan 2, 2025
1 parent 2d7de8f commit e193e00
Show file tree
Hide file tree
Showing 15 changed files with 95 additions and 127 deletions.
10 changes: 6 additions & 4 deletions crates/notedeck/src/accounts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use tracing::{debug, error, info};

use crate::{
KeyStorageResponse, KeyStorageType, Muted, SingleUnkIdAction, UnknownIds, UserAccount,
KeyStorageResponse, KeyStorageType, MuteFun, Muted, SingleUnkIdAction, UnknownIds, UserAccount,
};
use enostr::{ClientMessage, FilledKeypair, Keypair, RelayPool};
use nostrdb::{Filter, Ndb, Note, NoteKey, Subscription, Transaction};
Expand Down Expand Up @@ -401,17 +401,19 @@ impl Accounts {
self.key_store.select_key(None);
}

pub fn mutefun(&self) -> Box<dyn Fn(&Note) -> bool> {
pub fn mutefun(&self) -> Box<MuteFun> {
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));
return Box::new(move |note: &Note, thread: &[u8; 32]| {
muted.is_muted(note, thread)
});
}
}
}
Box::new(|_: &Note| false)
Box::new(|_: &Note, _: &[u8; 32]| None)
}

pub fn send_initial_filters(&mut self, pool: &mut RelayPool, relay_url: &str) {
Expand Down
31 changes: 24 additions & 7 deletions crates/notedeck/src/muted.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use nostrdb::Note;
use std::collections::BTreeSet;

use tracing::debug;
use tracing::{debug, trace};

pub type MuteFun = dyn Fn(&Note) -> bool;
// If the note is muted return a reason string, otherwise None
pub type MuteFun = dyn Fn(&Note, &[u8; 32]) -> Option<String>;

#[derive(Default)]
pub struct Muted {
Expand Down Expand Up @@ -32,14 +33,21 @@ impl std::fmt::Debug for Muted {
}

impl Muted {
pub fn is_muted(&self, note: &Note) -> bool {
// If the note is muted return a reason string, otherwise None
pub fn is_muted(&self, note: &Note, thread: &[u8; 32]) -> Option<String> {
trace!(
"{}: thread: {}",
hex::encode(note.id()),
hex::encode(thread)
);

if self.pubkeys.contains(note.pubkey()) {
debug!(
"{}: MUTED pubkey: {}",
hex::encode(note.id()),
hex::encode(note.pubkey())
);
return true;
return Some(format!("pubkey {}", hex::encode(note.pubkey())));
}
// FIXME - Implement hashtag muting here

Expand All @@ -51,11 +59,20 @@ impl Muted {
// for word in &self.words {
// if content.contains(&word.to_lowercase()) {
// debug!("{}: MUTED word: {}", hex::encode(note.id()), word);
// return true;
// return Some(format!("muted word {}", word));
// }
// }

// FIXME - Implement thread muting here
false
if self.threads.contains(thread) {
debug!(
"{}: MUTED thread: {}",
hex::encode(note.id()),
hex::encode(thread)
);
return Some(format!("thread {}", hex::encode(thread)));
}

// if we get here it's not muted
None
}
}
39 changes: 9 additions & 30 deletions crates/notedeck_columns/src/actionbar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{

use enostr::{NoteId, Pubkey, RelayPool};
use nostrdb::{Ndb, Transaction};
use notedeck::{note::root_note_id_from_selected_id, MuteFun, NoteCache, NoteRef};
use notedeck::{note::root_note_id_from_selected_id, NoteCache, NoteRef};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum NoteAction {
Expand Down Expand Up @@ -41,12 +41,11 @@ fn open_thread(
pool: &mut RelayPool,
threads: &mut NotesHolderStorage<Thread>,
selected_note: &[u8; 32],
is_muted: &MuteFun,
) -> Option<NotesHolderResult> {
router.route_to(Route::thread(NoteId::new(selected_note.to_owned())));

let root_id = root_note_id_from_selected_id(ndb, note_cache, txn, selected_note);
Thread::open(ndb, note_cache, txn, pool, threads, root_id, is_muted)
Thread::open(ndb, note_cache, txn, pool, threads, root_id)
}

impl NoteAction {
Expand All @@ -60,36 +59,20 @@ impl NoteAction {
note_cache: &mut NoteCache,
pool: &mut RelayPool,
txn: &Transaction,
is_muted: &MuteFun,
) -> Option<NotesHolderResult> {
match self {
NoteAction::Reply(note_id) => {
router.route_to(Route::reply(note_id));
None
}

NoteAction::OpenThread(note_id) => open_thread(
ndb,
txn,
router,
note_cache,
pool,
threads,
note_id.bytes(),
is_muted,
),
NoteAction::OpenThread(note_id) => {
open_thread(ndb, txn, router, note_cache, pool, threads, note_id.bytes())
}

NoteAction::OpenProfile(pubkey) => {
router.route_to(Route::profile(pubkey));
Profile::open(
ndb,
note_cache,
txn,
pool,
profiles,
pubkey.bytes(),
is_muted,
)
Profile::open(ndb, note_cache, txn, pool, profiles, pubkey.bytes())
}

NoteAction::Quote(note_id) => {
Expand All @@ -111,13 +94,10 @@ impl NoteAction {
note_cache: &mut NoteCache,
pool: &mut RelayPool,
txn: &Transaction,
is_muted: &MuteFun,
) {
let router = columns.column_mut(col).router_mut();
if let Some(br) = self.execute(
ndb, router, threads, profiles, note_cache, pool, txn, is_muted,
) {
br.process(ndb, note_cache, txn, threads, is_muted);
if let Some(br) = self.execute(ndb, router, threads, profiles, note_cache, pool, txn) {
br.process(ndb, note_cache, txn, threads);
}
}
}
Expand All @@ -133,13 +113,12 @@ impl NotesHolderResult {
note_cache: &mut NoteCache,
txn: &Transaction,
storage: &mut NotesHolderStorage<N>,
is_muted: &MuteFun,
) {
match self {
// update the thread for next render if we have new notes
NotesHolderResult::NewNotes(new_notes) => {
let holder = storage
.notes_holder_mutated(ndb, note_cache, txn, &new_notes.id, is_muted)
.notes_holder_mutated(ndb, note_cache, txn, &new_notes.id)
.get_ptr();
new_notes.process(holder);
}
Expand Down
3 changes: 0 additions & 3 deletions crates/notedeck_columns/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ fn try_process_event(
app_ctx.pool,
app_ctx.note_cache,
timeline,
&app_ctx.accounts.mutefun(),
app_ctx
.accounts
.get_selected_account()
Expand All @@ -157,7 +156,6 @@ fn try_process_event(
&txn,
app_ctx.unknown_ids,
app_ctx.note_cache,
&app_ctx.accounts.mutefun(),
) {
error!("poll_notes_into_view: {err}");
}
Expand Down Expand Up @@ -198,7 +196,6 @@ fn update_damus(damus: &mut Damus, app_ctx: &mut AppContext<'_>, ctx: &egui::Con
app_ctx.ndb,
app_ctx.note_cache,
&mut damus.decks_cache,
&app_ctx.accounts.mutefun(),
) {
warn!("update_damus init: {err}");
}
Expand Down
13 changes: 2 additions & 11 deletions crates/notedeck_columns/src/multi_subscriber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use tracing::{debug, error, info};
use uuid::Uuid;

use crate::Error;
use notedeck::{MuteFun, NoteRef, UnifiedSubscription};
use notedeck::{NoteRef, UnifiedSubscription};

pub struct MultiSubscriber {
filters: Vec<Filter>,
Expand Down Expand Up @@ -106,12 +106,7 @@ impl MultiSubscriber {
}
}

pub fn poll_for_notes(
&mut self,
ndb: &Ndb,
txn: &Transaction,
is_muted: &MuteFun,
) -> Result<Vec<NoteRef>, Error> {
pub fn poll_for_notes(&mut self, ndb: &Ndb, txn: &Transaction) -> Result<Vec<NoteRef>, Error> {
let sub = self.sub.as_ref().ok_or(notedeck::Error::no_active_sub())?;
let new_note_keys = ndb.poll_for_notes(sub.local, 500);

Expand All @@ -129,10 +124,6 @@ impl MultiSubscriber {
continue;
};

if is_muted(&note) {
continue;
}

notes.push(note);
}

Expand Down
3 changes: 0 additions & 3 deletions crates/notedeck_columns/src/nav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ impl RenderNavResponse {
ctx.note_cache,
ctx.pool,
&txn,
&ctx.accounts.mutefun(),
);
}

Expand Down Expand Up @@ -196,7 +195,6 @@ impl RenderNavResponse {
&mut app.threads,
ctx.pool,
root_id,
&ctx.accounts.mutefun(),
);
}

Expand All @@ -208,7 +206,6 @@ impl RenderNavResponse {
&mut app.profiles,
ctx.pool,
pubkey.bytes(),
&ctx.accounts.mutefun(),
);
}

Expand Down
15 changes: 5 additions & 10 deletions crates/notedeck_columns/src/notes_holder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;

use enostr::{Filter, RelayPool};
use nostrdb::{Ndb, Transaction};
use notedeck::{MuteFun, NoteCache, NoteRef, NoteRefsUnkIdAction};
use notedeck::{NoteCache, NoteRef, NoteRefsUnkIdAction};
use tracing::{debug, info, warn};

use crate::{
Expand Down Expand Up @@ -56,7 +56,6 @@ impl<M: NotesHolder> NotesHolderStorage<M> {
note_cache: &mut NoteCache,
txn: &Transaction,
id: &[u8; 32],
is_muted: &MuteFun,
) -> Vitality<'a, M> {
// 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
Expand Down Expand Up @@ -90,7 +89,7 @@ impl<M: NotesHolder> NotesHolderStorage<M> {

self.id_to_object.insert(
id.to_owned(),
M::new_notes_holder(txn, ndb, note_cache, id, M::filters(id), notes, is_muted),
M::new_notes_holder(txn, ndb, note_cache, id, M::filters(id), notes),
);
Vitality::Fresh(self.id_to_object.get_mut(id).unwrap())
}
Expand All @@ -109,19 +108,17 @@ pub trait NotesHolder {
id: &[u8; 32],
filters: Vec<Filter>,
notes: Vec<NoteRef>,
is_muted: &MuteFun,
) -> Self;

#[must_use = "process_action must be handled in the Ok(action) case"]
fn poll_notes_into_view(
&mut self,
txn: &Transaction,
ndb: &Ndb,
is_muted: &MuteFun,
) -> Result<NoteRefsUnkIdAction> {
if let Some(multi_subscriber) = self.get_multi_subscriber() {
let reversed = true;
let note_refs: Vec<NoteRef> = multi_subscriber.poll_for_notes(ndb, txn, is_muted)?;
let note_refs: Vec<NoteRef> = multi_subscriber.poll_for_notes(ndb, txn)?;
self.get_view().insert(&note_refs, reversed);
Ok(NoteRefsUnkIdAction::new(note_refs))
} else {
Expand Down Expand Up @@ -160,10 +157,9 @@ pub trait NotesHolder {
notes_holder_storage: &mut NotesHolderStorage<M>,
pool: &mut RelayPool,
id: &[u8; 32],
is_muted: &MuteFun,
) {
let notes_holder = notes_holder_storage
.notes_holder_mutated(ndb, note_cache, txn, id, is_muted)
.notes_holder_mutated(ndb, note_cache, txn, id)
.get_ptr();

if let Some(multi_subscriber) = notes_holder.get_multi_subscriber() {
Expand All @@ -178,9 +174,8 @@ pub trait NotesHolder {
pool: &mut RelayPool,
storage: &mut NotesHolderStorage<M>,
id: &[u8; 32],
is_muted: &MuteFun,
) -> Option<NotesHolderResult> {
let vitality = storage.notes_holder_mutated(ndb, note_cache, txn, id, is_muted);
let vitality = storage.notes_holder_mutated(ndb, note_cache, txn, id);

let (holder, result) = match vitality {
Vitality::Stale(holder) => {
Expand Down
7 changes: 2 additions & 5 deletions crates/notedeck_columns/src/profile.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use enostr::{Filter, Pubkey};
use nostrdb::{FilterBuilder, Ndb, ProfileRecord, Transaction};

use notedeck::{filter::default_limit, FilterState, MuteFun, NoteCache, NoteRef};
use notedeck::{filter::default_limit, FilterState, NoteCache, NoteRef};

use crate::{
multi_subscriber::MultiSubscriber,
Expand Down Expand Up @@ -60,15 +60,14 @@ impl Profile {
source: PubkeySource,
filters: Vec<Filter>,
notes: Vec<NoteRef>,
is_muted: &MuteFun,
) -> Self {
let mut timeline = Timeline::new(
TimelineKind::profile(source),
FilterState::ready(filters),
TimelineTab::full_tabs(),
);

copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes, is_muted);
copy_notes_into_timeline(&mut timeline, txn, ndb, note_cache, notes);

Profile {
timeline,
Expand Down Expand Up @@ -114,7 +113,6 @@ impl NotesHolder for Profile {
id: &[u8; 32],
filters: Vec<Filter>,
notes: Vec<NoteRef>,
is_muted: &MuteFun,
) -> Self {
Profile::new(
txn,
Expand All @@ -123,7 +121,6 @@ impl NotesHolder for Profile {
PubkeySource::Explicit(Pubkey::new(*id)),
filters,
notes,
is_muted,
)
}

Expand Down
3 changes: 1 addition & 2 deletions crates/notedeck_columns/src/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
};

use nostrdb::{Filter, FilterBuilder, Ndb, Transaction};
use notedeck::{MuteFun, NoteCache, NoteRef};
use notedeck::{NoteCache, NoteRef};

#[derive(Default)]
pub struct Thread {
Expand Down Expand Up @@ -74,7 +74,6 @@ impl NotesHolder for Thread {
_: &[u8; 32],
_: Vec<Filter>,
notes: Vec<NoteRef>,
_: &MuteFun,
) -> Self {
Thread::new(notes)
}
Expand Down
Loading

0 comments on commit e193e00

Please sign in to comment.