notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 8f8ff42156c7c046ca0ae9a255a9a8c51d07f0b0
parent 3a95ba05a84f64a74e981899f1832ce77f953501
Author: kernelkind <kernelkind@gmail.com>
Date:   Thu,  4 Sep 2025 14:54:12 -0400

NoteUnits: use `UnitKey` instead of just `NoteKey`

in preparation for multiple composite types

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck_columns/src/timeline/mod.rs | 2+-
Mcrates/notedeck_columns/src/timeline/note_units.rs | 33+++++++++++++++++++++++++++------
Mcrates/notedeck_columns/src/timeline/thread.rs | 8++++++--
Mcrates/notedeck_columns/src/timeline/unit.rs | 34++++++++++++++++++++++++----------
4 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/crates/notedeck_columns/src/timeline/mod.rs b/crates/notedeck_columns/src/timeline/mod.rs @@ -36,7 +36,7 @@ mod unit; pub use cache::TimelineCache; pub use kind::{ColumnTitle, PubkeySource, ThreadSelection, TimelineKind}; -pub use note_units::{InsertionResponse, NoteUnits}; +pub use note_units::{CompositeType, InsertionResponse, NoteUnits}; pub use timeline_units::{TimelineUnits, UnknownPks}; pub use unit::{CompositeUnit, NoteUnit, ReactionUnit}; diff --git a/crates/notedeck_columns/src/timeline/note_units.rs b/crates/notedeck_columns/src/timeline/note_units.rs @@ -17,7 +17,7 @@ type StorageIndex = usize; pub struct NoteUnits { reversed: bool, storage: Vec<NoteUnit>, - lookup: HashMap<NoteKey, StorageIndex>, // `NoteKey` to index in `NoteUnits::storage` + lookup: HashMap<UnitKey, StorageIndex>, // the key to index in `NoteUnits::storage` order: Vec<StorageIndex>, // the sorted order of the `NoteUnit`s in `NoteUnits::storage` } @@ -30,7 +30,7 @@ impl NoteUnits { } } - pub fn contains_key(&self, k: &NoteKey) -> bool { + pub fn contains_key(&self, k: &UnitKey) -> bool { self.lookup.contains_key(k) } @@ -163,7 +163,7 @@ impl NoteUnits { /// if `NoteUnitFragment::Composite` exists already, it will fold the fragment into the `CompositeUnit` /// otherwise, it will generate the `NoteUnit::CompositeUnit` from the `NoteUnitFragment::Composite` pub fn merge_fragments(&mut self, frags: Vec<NoteUnitFragment>) -> InsertManyResponse { - let mut to_build: HashMap<NoteKey, CompositeUnit> = HashMap::new(); // new composites by key + let mut to_build: HashMap<CompositeKey, CompositeUnit> = HashMap::new(); // new composites by key let mut singles_to_build: Vec<NoteRef> = Vec::new(); let mut singles_seen: HashSet<NoteKey> = HashSet::new(); @@ -172,7 +172,7 @@ impl NoteUnits { match frag { NoteUnitFragment::Single(note_ref) => { let key = note_ref.key; - if self.lookup.contains_key(&key) { + if self.lookup.contains_key(&UnitKey::Single(key)) { continue; } if singles_seen.insert(key) { @@ -181,8 +181,9 @@ impl NoteUnits { } NoteUnitFragment::Composite(c_frag) => { let key = c_frag.get_underlying_noteref().key; + let composite_type = c_frag.get_type(); - if let Some(&storage_idx) = self.lookup.get(&key) { + if let Some(&storage_idx) = self.lookup.get(&UnitKey::Composite(c_frag.key())) { if let Some(NoteUnit::Composite(c_unit)) = self.storage.get_mut(storage_idx) { if c_frag.get_latest_ref() < c_unit.get_latest_ref() { @@ -194,7 +195,10 @@ impl NoteUnits { } // aggregate for new composite use std::collections::hash_map::Entry; - match to_build.entry(key) { + match to_build.entry(CompositeKey { + key, + composite_type, + }) { Entry::Occupied(mut o) => { c_frag.fold_into(o.get_mut()); } @@ -234,6 +238,23 @@ impl NoteUnits { } } +#[derive(Hash, PartialEq, Eq, Debug)] +pub struct CompositeKey { + pub key: NoteKey, + pub composite_type: CompositeType, +} + +#[derive(Hash, PartialEq, Eq, Debug)] +pub enum CompositeType { + Reaction, +} + +#[derive(Hash, PartialEq, Eq, Debug)] +pub enum UnitKey { + Single(NoteKey), + Composite(CompositeKey), +} + pub enum InsertManyResponse { Zero, Some { diff --git a/crates/notedeck_columns/src/timeline/thread.rs b/crates/notedeck_columns/src/timeline/thread.rs @@ -8,7 +8,11 @@ use notedeck::{NoteCache, NoteRef, UnknownIds}; use crate::{ actionbar::{process_thread_notes, NewThreadNotes}, multi_subscriber::ThreadSubs, - timeline::{note_units::NoteUnits, unit::NoteUnit, InsertionResponse}, + timeline::{ + note_units::{NoteUnits, UnitKey}, + unit::NoteUnit, + InsertionResponse, + }, }; use super::ThreadSelection; @@ -417,6 +421,6 @@ impl SingleNoteUnits { } pub fn contains_key(&self, k: &NoteKey) -> bool { - self.units.contains_key(k) + self.units.contains_key(&UnitKey::Single(*k)) } } diff --git a/crates/notedeck_columns/src/timeline/unit.rs b/crates/notedeck_columns/src/timeline/unit.rs @@ -1,9 +1,13 @@ use std::collections::{BTreeMap, HashSet}; use enostr::Pubkey; -use nostrdb::NoteKey; use notedeck::NoteRef; +use crate::timeline::{ + note_units::{CompositeKey, UnitKey}, + CompositeType, +}; + /// A `NoteUnit` represents a cohesive piece of data derived from notes #[derive(Debug, Clone)] pub enum NoteUnit { @@ -12,10 +16,10 @@ pub enum NoteUnit { } impl NoteUnit { - pub fn key(&self) -> NoteKey { + pub fn key(&self) -> UnitKey { match self { - NoteUnit::Single(note_ref) => note_ref.key, - NoteUnit::Composite(clustered_entry) => clustered_entry.key(), + NoteUnit::Single(note_ref) => UnitKey::Single(note_ref.key), + NoteUnit::Composite(clustered_entry) => UnitKey::Composite(clustered_entry.key()), } } @@ -79,9 +83,12 @@ impl PartialEq for CompositeUnit { } impl CompositeUnit { - pub fn key(&self) -> NoteKey { + pub fn key(&self) -> CompositeKey { match self { - CompositeUnit::Reaction(reaction_entry) => reaction_entry.note_reacted_to.key, + CompositeUnit::Reaction(reaction_entry) => CompositeKey { + key: reaction_entry.note_reacted_to.key, + composite_type: CompositeType::Reaction, + }, } } } @@ -150,11 +157,12 @@ impl CompositeFragment { } } - pub fn key(&self) -> NoteKey { + pub fn key(&self) -> CompositeKey { match self { - CompositeFragment::Reaction(reaction_fragment) => { - reaction_fragment.reaction_note_ref.key - } + CompositeFragment::Reaction(reaction) => CompositeKey { + key: reaction.noteref_reacted_to.key, + composite_type: CompositeType::Reaction, + }, } } @@ -169,6 +177,12 @@ impl CompositeFragment { CompositeFragment::Reaction(reaction_fragment) => &reaction_fragment.reaction_note_ref, } } + + pub fn get_type(&self) -> CompositeType { + match self { + CompositeFragment::Reaction(_) => CompositeType::Reaction, + } + } } /// A singluar reaction to a note