Skip to content

Commit

Permalink
wip threads
Browse files Browse the repository at this point in the history
Signed-off-by: William Casarin <[email protected]>
  • Loading branch information
jb55 committed Jul 15, 2024
1 parent 6b63464 commit aeebafd
Show file tree
Hide file tree
Showing 10 changed files with 282 additions and 73 deletions.
27 changes: 19 additions & 8 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use crate::error::Error;
use crate::frame_history::FrameHistory;
use crate::imgcache::ImageCache;
use crate::key_storage::KeyStorageType;
use crate::note::NoteRef;
use crate::notecache::{CachedNote, NoteCache};
use crate::relay_pool_manager::RelayPoolManager;
use crate::route::Route;
use crate::thread::Threads;
use crate::timeline;
use crate::timeline::{MergeKind, NoteRef, Timeline, ViewFilter};
use crate::timeline::{MergeKind, Timeline, ViewFilter};
use crate::ui::note::PostAction;
use crate::ui::{self, AccountSelectionWidget, DesktopGlobalPopup};
use crate::ui::{DesktopSidePanel, RelayView, View};
Expand Down Expand Up @@ -52,10 +54,11 @@ pub struct Damus {

pub timelines: Vec<Timeline>,
pub selected_timeline: i32,
pub drafts: Drafts,

pub img_cache: ImageCache,
pub ndb: Ndb,
pub drafts: Drafts,
pub threads: Threads,
pub img_cache: ImageCache,
pub account_manager: AccountManager,

frame_history: crate::frame_history::FrameHistory,
Expand Down Expand Up @@ -819,6 +822,7 @@ impl Damus {
Self {
pool,
is_mobile,
threads: Threads::default(),
drafts: Drafts::default(),
state: DamusState::Initializing,
img_cache: ImageCache::new(imgcache_dir),
Expand Down Expand Up @@ -848,6 +852,7 @@ impl Damus {
config.set_ingester_threads(2);
Self {
is_mobile,
threads: Threads::default(),
drafts: Drafts::default(),
state: DamusState::Initializing,
pool: RelayPool::new(),
Expand Down Expand Up @@ -1012,18 +1017,24 @@ fn render_nav(routes: Vec<Route>, timeline_ind: usize, app: &mut Damus, ui: &mut
None
}

Route::Thread(_key) => {
ui.label("thread view");
None
}

Route::Relays => {
let pool = &mut app_ctx.borrow_mut().pool;
let manager = RelayPoolManager::new(pool);
RelayView::new(manager).ui(ui);
None
}

Route::Thread(id) => {
let app = &mut app_ctx.borrow_mut();
if let Ok(txn) = Transaction::new(&app.ndb) {
if let Ok(note) = app.ndb.get_note_by_id(&txn, id.bytes()) {
ui::ThreadView::new(app, &note).ui(ui);
}
}

None
}

Route::Reply(id) => {
let mut app = app_ctx.borrow_mut();

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod login_manager;
mod macos_key_storage;
mod note;
mod notecache;
mod note;

Check failure on line 23 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Clippy

the name `note` is defined multiple times

Check failure on line 23 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Check

the name `note` is defined multiple times

Check failure on line 23 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test Suite

the name `note` is defined multiple times
mod post;
mod profile;
pub mod relay_pool_manager;
Expand All @@ -29,6 +30,7 @@ mod test_data;
mod time;
mod timecache;
mod timeline;
mod thread;
pub mod ui;
mod user_account;

Expand Down
36 changes: 36 additions & 0 deletions src/note.rs
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@
use nostrdb::{NoteKey, QueryResult};
use std::cmp::Ordering;

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct NoteRef {
pub key: NoteKey,
pub created_at: u64,
}

impl NoteRef {
pub fn new(key: NoteKey, created_at: u64) -> Self {
NoteRef { key, created_at }
}

pub fn from_query_result<'a>(qr: QueryResult<'a>) -> Self {
NoteRef {
key: qr.key,
created_at: qr.created_at,
}
}
}

impl Ord for NoteRef {
fn cmp(&self, other: &Self) -> Ordering {
match self.created_at.cmp(&other.created_at) {
Ordering::Equal => self.key.cmp(&other.key),
Ordering::Less => Ordering::Greater,
Ordering::Greater => Ordering::Less,
}
}
}

impl PartialOrd for NoteRef {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
73 changes: 73 additions & 0 deletions src/thread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::note::NoteRef;
use crate::timeline::{NotesAndReplies, TimelineView};

Check failure on line 2 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Clippy

unresolved import `crate::timeline::NotesAndReplies`

Check failure on line 2 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Check

unresolved import `crate::timeline::NotesAndReplies`

Check failure on line 2 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unresolved import `crate::timeline::NotesAndReplies`
use nostrdb::{Ndb, NoteKey};
use std::collections::hash_map::Entry;
use std::collections::HashMap;

#[derive(Default)]
pub struct Thread {
pub view: TimelineView,
}

impl Thread {
fn new(notes: Vec<NoteRef>) -> Self {
let mut cap = ((notes.len() as f32) * 1.5) as usize;
if cap == 0 {
cap = 25;
}
let mut view = TimelineView::new_with_capacity(ViewFilter::NotesAndReplies, cap);

Check failure on line 18 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Clippy

failed to resolve: use of undeclared type `ViewFilter`

Check failure on line 18 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Check

failed to resolve: use of undeclared type `ViewFilter`

Check failure on line 18 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Test Suite

failed to resolve: use of undeclared type `ViewFilter`
view.notes = notes;

Thread { view }
}
}

#[derive(Default)]
pub struct Threads {
pub threads: HashMap<NoteKey, Thread>,
}

impl Threads {
fn thread_mut(&self, ndb: &Ndb, key: NoteKey) -> &mut Thread {
let thread = self.threads.entry(key).or_default();

match self.threads.entry(key) {
Entry::Occupied(o) => o.get_mut(),

Entry::Vacant(v) => {
// looks like we don't have this thread yet, populate it
// TODO: should we do this in the caller?

let root = if let Some(root) = ndb.get_note_by_key(key) {
root
} else {
// can't find the root note!? :(
return v.insert(Thread::new(vec![]));
};

// we don't have the thread, query for it!
let filter = nostrdb::FilterBuilder::new()

Check failure on line 49 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Clippy

failed to resolve: could not find `FilterBuilder` in `nostrdb`

Check failure on line 49 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Check

failed to resolve: could not find `FilterBuilder` in `nostrdb`

Check failure on line 49 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Test Suite

failed to resolve: could not find `FilterBuilder` in `nostrdb`
.start_tag_field('e')
.add_id_element(root.id)
.end_field()
.build();

// TODO: what should be the max results ?
let notes = if let Ok(results) = ndb.query(txn, vec![filter], 10000) {

Check failure on line 56 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Clippy

cannot find value `txn` in this scope

Check failure on line 56 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Check

cannot find value `txn` in this scope

Check failure on line 56 in src/thread.rs

View workflow job for this annotation

GitHub Actions / Test Suite

cannot find value `txn` in this scope
results.map(NoteRef::from_query_result)
} else {
vec![]
};

v.insert(Thread::new(notes))
}
}
}

fn thread(&self, ndb: &Ndb, key: NoteKey) -> &Thread {
self.thread_mut(ndb, key)
}

//fn thread_by_id(&self, ndb: &Ndb, id: &[u8; 32]) -> &mut Thread {
//}
}
60 changes: 20 additions & 40 deletions src/timeline.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::draft::DraftSource;
use crate::note::NoteRef;
use crate::notecache::CachedNote;
use crate::ui::note::PostAction;
use crate::{ui, Damus};
Expand All @@ -11,41 +12,24 @@ use crate::ui::BarAction;
use egui_tabs::TabColor;
use egui_virtual_list::VirtualList;
use enostr::{Filter, NoteId};

Check warning on line 14 in src/timeline.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `NoteId`

Check warning on line 14 in src/timeline.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused import: `NoteId`
use nostrdb::{Note, NoteKey, Subscription, Transaction};
use nostrdb::{Note, Subscription, Transaction};
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;

use tracing::{debug, info, warn};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct NoteRef {
pub key: NoteKey,
pub created_at: u64,
}

impl Ord for NoteRef {
fn cmp(&self, other: &Self) -> Ordering {
match self.created_at.cmp(&other.created_at) {
Ordering::Equal => self.key.cmp(&other.key),
Ordering::Less => Ordering::Greater,
Ordering::Greater => Ordering::Less,
}
}
}

impl PartialOrd for NoteRef {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ViewFilter {
Notes,
NotesAndReplies,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TimelineSource {
Deck(usize),
Thread(NoteKey),

Check failure on line 30 in src/timeline.rs

View workflow job for this annotation

GitHub Actions / Clippy

cannot find type `NoteKey` in this scope

Check failure on line 30 in src/timeline.rs

View workflow job for this annotation

GitHub Actions / Check

cannot find type `NoteKey` in this scope

Check failure on line 30 in src/timeline.rs

View workflow job for this annotation

GitHub Actions / Test Suite

cannot find type `NoteKey` in this scope
}

impl ViewFilter {
pub fn name(&self) -> &'static str {
match self {
Expand Down Expand Up @@ -90,11 +74,15 @@ pub struct TimelineView {

impl TimelineView {
pub fn new(filter: ViewFilter) -> Self {
TimelineView::new_with_capacity(filter, 1000)
}

pub fn new_with_capacity(filter: ViewFilter, cap: usize) -> Self {
let selection = 0i32;
let mut list = VirtualList::new();
list.hide_on_resize(None);
let list = Rc::new(RefCell::new(list));
let notes: Vec<NoteRef> = Vec::with_capacity(1000);
let notes: Vec<NoteRef> = Vec::with_capacity(cap);

TimelineView {
notes,
Expand Down Expand Up @@ -194,7 +182,7 @@ fn shrink_range_to_width(range: egui::Rangef, width: f32) -> egui::Rangef {
egui::Rangef::new(min, max)
}

fn tabs_ui(timeline: &mut Timeline, ui: &mut egui::Ui) {
fn tabs_ui(ui: &mut egui::Ui) -> i32 {
ui.spacing_mut().item_spacing.y = 0.0;

let tab_res = egui_tabs::Tabs::new(2)
Expand Down Expand Up @@ -232,9 +220,6 @@ fn tabs_ui(timeline: &mut Timeline, ui: &mut egui::Ui) {

let sel = tab_res.selected().unwrap_or_default();

// fun animation
timeline.selected_view = sel;

let (underline, underline_y) = tab_res.inner()[sel as usize].inner;
let underline_width = underline.span();

Expand All @@ -261,6 +246,8 @@ fn tabs_ui(timeline: &mut Timeline, ui: &mut egui::Ui) {
let underline = egui::Rangef::new(x, x + w);

ui.painter().hline(underline, underline_y, stroke);

sel
}

pub fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
Expand Down Expand Up @@ -308,7 +295,7 @@ pub fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
}
}

tabs_ui(&mut app.timelines[timeline], ui);
timeline.selected_view = tabs_ui(ui);

// need this for some reason??
ui.add_space(3.0);
Expand Down Expand Up @@ -352,16 +339,9 @@ pub fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
.show(ui);

if let Some(action) = resp.action {
debug!("bar action: {:?}", action);
match action {
BarAction::Reply => {
let timeline = &mut app.timelines[timeline];
timeline
.routes
.push(Route::Reply(NoteId::new(note.id().to_owned())));
timeline.navigating = true;
}
}
action.execute(app, timeline);
} else if resp.response.clicked() {
debug!("clicked note");
}
});

Expand Down
8 changes: 8 additions & 0 deletions src/ui/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ pub fn hover_expand(
let size = size + val * expand_size;
(rect, size, response)
}

pub fn hover_expand_small(ui: &mut egui::Ui, id: egui::Id) -> (egui::Rect, f32, egui::Response) {
let size = 10.0;
let expand_size = 5.0;
let anim_speed = 0.05;

hover_expand(ui, id, size, expand_size, anim_speed)
}
2 changes: 2 additions & 0 deletions src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod preview;
pub mod profile;
pub mod relay;
pub mod side_panel;
pub mod thread;
pub mod username;

pub use account_management::AccountManagementView;
Expand All @@ -22,6 +23,7 @@ pub use preview::{Preview, PreviewApp, PreviewConfig};
pub use profile::{profile_preview_controller, ProfilePic, ProfilePreview};
pub use relay::RelayView;
pub use side_panel::{DesktopSidePanel, SidePanelAction};
pub use thread::ThreadView;
pub use username::Username;

use egui::Margin;
Expand Down
Loading

0 comments on commit aeebafd

Please sign in to comment.