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 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};

View File

@@ -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 {

View File

@@ -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))
}
}

View File

@@ -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