integrate new threads conception

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-06-17 12:49:09 -04:00
parent f6753bae97
commit d560e84eab
10 changed files with 260 additions and 185 deletions

View File

@@ -1,5 +1,5 @@
use enostr::{NoteId, Pubkey};
use notedeck::{NoteZapTargetOwned, WalletType};
use notedeck::{NoteZapTargetOwned, RootNoteIdBuf, WalletType};
use std::{
fmt::{self},
ops::Range,
@@ -20,6 +20,7 @@ use tokenator::{ParseError, TokenParser, TokenSerializable, TokenWriter};
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Route {
Timeline(TimelineKind),
Thread(ThreadSelection),
Accounts(AccountsRoute),
Reply(NoteId),
Quote(NoteId),
@@ -53,7 +54,7 @@ impl Route {
}
pub fn thread(thread_selection: ThreadSelection) -> Self {
Route::Timeline(TimelineKind::Thread(thread_selection))
Route::Thread(thread_selection)
}
pub fn profile(pubkey: Pubkey) -> Self {
@@ -79,6 +80,18 @@ impl Route {
pub fn serialize_tokens(&self, writer: &mut TokenWriter) {
match self {
Route::Timeline(timeline_kind) => timeline_kind.serialize_tokens(writer),
Route::Thread(selection) => {
writer.write_token("thread");
if let Some(reply) = selection.selected_note {
writer.write_token("root");
writer.write_token(&NoteId::new(*selection.root_id.bytes()).hex());
writer.write_token("reply");
writer.write_token(&reply.hex());
} else {
writer.write_token(&NoteId::new(*selection.root_id.bytes()).hex());
}
}
Route::Accounts(routes) => routes.serialize_tokens(writer),
Route::AddColumn(routes) => routes.serialize_tokens(writer),
Route::Search => writer.write_token("search"),
@@ -199,6 +212,31 @@ impl Route {
Ok(Route::Search)
})
},
|p| {
p.parse_all(|p| {
p.parse_token("thread")?;
p.parse_token("root")?;
let root = tokenator::parse_hex_id(p)?;
p.parse_token("reply")?;
let selected = tokenator::parse_hex_id(p)?;
Ok(Route::Thread(ThreadSelection {
root_id: RootNoteIdBuf::new_unsafe(root),
selected_note: Some(NoteId::new(selected)),
}))
})
},
|p| {
p.parse_all(|p| {
p.parse_token("thread")?;
Ok(Route::Thread(ThreadSelection::from_root_id(
RootNoteIdBuf::new_unsafe(tokenator::parse_hex_id(p)?),
)))
})
},
],
)
}
@@ -206,6 +244,7 @@ impl Route {
pub fn title(&self) -> ColumnTitle<'_> {
match self {
Route::Timeline(kind) => kind.to_title(),
Route::Thread(_) => ColumnTitle::simple("Thread"),
Route::Reply(_id) => ColumnTitle::simple("Reply"),
Route::Quote(_id) => ColumnTitle::simple("Quote"),
Route::Relays => ColumnTitle::simple("Relays"),
@@ -423,9 +462,9 @@ impl fmt::Display for Route {
TimelineKind::Generic(_) => write!(f, "Custom"),
TimelineKind::Search(_) => write!(f, "Search"),
TimelineKind::Hashtag(ht) => write!(f, "Hashtag ({})", ht),
TimelineKind::Thread(_id) => write!(f, "Thread"),
TimelineKind::Profile(_id) => write!(f, "Profile"),
},
Route::Thread(_) => write!(f, "Thread"),
Route::Reply(_id) => write!(f, "Reply"),
Route::Quote(_id) => write!(f, "Quote"),
Route::Relays => write!(f, "Relays"),
@@ -482,3 +521,30 @@ impl<R: Clone> Default for SingletonRouter<R> {
}
}
}
#[cfg(test)]
mod tests {
use enostr::NoteId;
use tokenator::{TokenParser, TokenWriter};
use crate::{timeline::ThreadSelection, Route};
use enostr::Pubkey;
use notedeck::RootNoteIdBuf;
#[test]
fn test_thread_route_serialize() {
let note_id_hex = "1c54e5b0c386425f7e017d9e068ddef8962eb2ce1bb08ed27e24b93411c12e60";
let note_id = NoteId::from_hex(note_id_hex).unwrap();
let data_str = format!("thread:{}", note_id_hex);
let data = &data_str.split(":").collect::<Vec<&str>>();
let mut token_writer = TokenWriter::default();
let mut parser = TokenParser::new(&data);
let parsed = Route::parse(&mut parser, &Pubkey::new(*note_id.bytes())).unwrap();
let expected = Route::Thread(ThreadSelection::from_root_id(RootNoteIdBuf::new_unsafe(
*note_id.bytes(),
)));
parsed.serialize_tokens(&mut token_writer);
assert_eq!(expected, parsed);
assert_eq!(token_writer.str(), data_str);
}
}