NoteUnits: use UnitKey instead of just NoteKey

in preparation for multiple composite types

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-09-04 14:54:12 -04:00
parent 3a95ba05a8
commit 8f8ff42156
4 changed files with 58 additions and 19 deletions

View File

@@ -36,7 +36,7 @@ mod unit;
pub use cache::TimelineCache; pub use cache::TimelineCache;
pub use kind::{ColumnTitle, PubkeySource, ThreadSelection, TimelineKind}; 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 timeline_units::{TimelineUnits, UnknownPks};
pub use unit::{CompositeUnit, NoteUnit, ReactionUnit}; pub use unit::{CompositeUnit, NoteUnit, ReactionUnit};

View File

@@ -17,7 +17,7 @@ type StorageIndex = usize;
pub struct NoteUnits { pub struct NoteUnits {
reversed: bool, reversed: bool,
storage: Vec<NoteUnit>, 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` 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) self.lookup.contains_key(k)
} }
@@ -163,7 +163,7 @@ impl NoteUnits {
/// if `NoteUnitFragment::Composite` exists already, it will fold the fragment into the `CompositeUnit` /// if `NoteUnitFragment::Composite` exists already, it will fold the fragment into the `CompositeUnit`
/// otherwise, it will generate the `NoteUnit::CompositeUnit` from the `NoteUnitFragment::Composite` /// otherwise, it will generate the `NoteUnit::CompositeUnit` from the `NoteUnitFragment::Composite`
pub fn merge_fragments(&mut self, frags: Vec<NoteUnitFragment>) -> InsertManyResponse { 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_to_build: Vec<NoteRef> = Vec::new();
let mut singles_seen: HashSet<NoteKey> = HashSet::new(); let mut singles_seen: HashSet<NoteKey> = HashSet::new();
@@ -172,7 +172,7 @@ impl NoteUnits {
match frag { match frag {
NoteUnitFragment::Single(note_ref) => { NoteUnitFragment::Single(note_ref) => {
let key = note_ref.key; let key = note_ref.key;
if self.lookup.contains_key(&key) { if self.lookup.contains_key(&UnitKey::Single(key)) {
continue; continue;
} }
if singles_seen.insert(key) { if singles_seen.insert(key) {
@@ -181,8 +181,9 @@ impl NoteUnits {
} }
NoteUnitFragment::Composite(c_frag) => { NoteUnitFragment::Composite(c_frag) => {
let key = c_frag.get_underlying_noteref().key; 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 let Some(NoteUnit::Composite(c_unit)) = self.storage.get_mut(storage_idx)
{ {
if c_frag.get_latest_ref() < c_unit.get_latest_ref() { if c_frag.get_latest_ref() < c_unit.get_latest_ref() {
@@ -194,7 +195,10 @@ impl NoteUnits {
} }
// aggregate for new composite // aggregate for new composite
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
match to_build.entry(key) { match to_build.entry(CompositeKey {
key,
composite_type,
}) {
Entry::Occupied(mut o) => { Entry::Occupied(mut o) => {
c_frag.fold_into(o.get_mut()); 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 { pub enum InsertManyResponse {
Zero, Zero,
Some { Some {

View File

@@ -8,7 +8,11 @@ use notedeck::{NoteCache, NoteRef, UnknownIds};
use crate::{ use crate::{
actionbar::{process_thread_notes, NewThreadNotes}, actionbar::{process_thread_notes, NewThreadNotes},
multi_subscriber::ThreadSubs, multi_subscriber::ThreadSubs,
timeline::{note_units::NoteUnits, unit::NoteUnit, InsertionResponse}, timeline::{
note_units::{NoteUnits, UnitKey},
unit::NoteUnit,
InsertionResponse,
},
}; };
use super::ThreadSelection; use super::ThreadSelection;
@@ -417,6 +421,6 @@ impl SingleNoteUnits {
} }
pub fn contains_key(&self, k: &NoteKey) -> bool { pub fn contains_key(&self, k: &NoteKey) -> bool {
self.units.contains_key(k) self.units.contains_key(&UnitKey::Single(*k))
} }
} }

View File

@@ -1,9 +1,13 @@
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use enostr::Pubkey; use enostr::Pubkey;
use nostrdb::NoteKey;
use notedeck::NoteRef; use notedeck::NoteRef;
use crate::timeline::{
note_units::{CompositeKey, UnitKey},
CompositeType,
};
/// A `NoteUnit` represents a cohesive piece of data derived from notes /// A `NoteUnit` represents a cohesive piece of data derived from notes
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum NoteUnit { pub enum NoteUnit {
@@ -12,10 +16,10 @@ pub enum NoteUnit {
} }
impl NoteUnit { impl NoteUnit {
pub fn key(&self) -> NoteKey { pub fn key(&self) -> UnitKey {
match self { match self {
NoteUnit::Single(note_ref) => note_ref.key, NoteUnit::Single(note_ref) => UnitKey::Single(note_ref.key),
NoteUnit::Composite(clustered_entry) => clustered_entry.key(), NoteUnit::Composite(clustered_entry) => UnitKey::Composite(clustered_entry.key()),
} }
} }
@@ -79,9 +83,12 @@ impl PartialEq for CompositeUnit {
} }
impl CompositeUnit { impl CompositeUnit {
pub fn key(&self) -> NoteKey { pub fn key(&self) -> CompositeKey {
match self { 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 { match self {
CompositeFragment::Reaction(reaction_fragment) => { CompositeFragment::Reaction(reaction) => CompositeKey {
reaction_fragment.reaction_note_ref.key 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, 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 /// A singluar reaction to a note