Skip to content

Commit

Permalink
columns: move from Cow<'static, str> to ColumnTitle<'a>
Browse files Browse the repository at this point in the history
This further deliminates our column titles to those that are simple,
and to those that require additional information from the database.

This allows us to avoid creating many transactions pointlessly if we
don't need to.

Changelog-Changed: Show usernames in user columns
  • Loading branch information
jb55 committed Dec 17, 2024
1 parent 47e0b0e commit 482a3cb
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 49 deletions.
45 changes: 22 additions & 23 deletions crates/notedeck_columns/src/route.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use enostr::{NoteId, Pubkey};
use std::{
borrow::Cow,
fmt::{self},
};
use std::fmt::{self};

use crate::{
accounts::AccountsRoute,
column::Columns,
timeline::{TimelineId, TimelineRoute},
timeline::{kind::ColumnTitle, TimelineId, TimelineRoute},
ui::add_column::AddColumnRoute,
};

Expand Down Expand Up @@ -65,7 +62,7 @@ impl Route {
Route::Accounts(AccountsRoute::AddAccount)
}

pub fn title(&self, columns: &Columns) -> Cow<'static, str> {
pub fn title<'a>(&self, columns: &'a Columns) -> ColumnTitle<'a> {
match self {
Route::Timeline(tlr) => match tlr {
TimelineRoute::Timeline(id) => {
Expand All @@ -74,36 +71,38 @@ impl Route {
.expect("expected to find timeline");
timeline.kind.to_title()
}
TimelineRoute::Thread(_id) => Cow::Borrowed("Thread"),
TimelineRoute::Reply(_id) => Cow::Borrowed("Reply"),
TimelineRoute::Quote(_id) => Cow::Borrowed("Quote"),
TimelineRoute::Profile(_pubkey) => Cow::Borrowed("Profile"),
TimelineRoute::Thread(_id) => ColumnTitle::simple("Thread"),
TimelineRoute::Reply(_id) => ColumnTitle::simple("Reply"),
TimelineRoute::Quote(_id) => ColumnTitle::simple("Quote"),
TimelineRoute::Profile(_pubkey) => ColumnTitle::simple("Profile"),
},

Route::Relays => Cow::Borrowed("Relays"),
Route::Relays => ColumnTitle::simple("Relays"),

Route::Accounts(amr) => match amr {
AccountsRoute::Accounts => Cow::Borrowed("Accounts"),
AccountsRoute::AddAccount => Cow::Borrowed("Add Account"),
AccountsRoute::Accounts => ColumnTitle::simple("Accounts"),
AccountsRoute::AddAccount => ColumnTitle::simple("Add Account"),
},
Route::ComposeNote => Cow::Borrowed("Compose Note"),
Route::ComposeNote => ColumnTitle::simple("Compose Note"),
Route::AddColumn(c) => match c {
AddColumnRoute::Base => Cow::Borrowed("Add Column"),
AddColumnRoute::UndecidedNotification => Cow::Borrowed("Add Notifications Column"),
AddColumnRoute::Base => ColumnTitle::simple("Add Column"),
AddColumnRoute::UndecidedNotification => {
ColumnTitle::simple("Add Notifications Column")
}
AddColumnRoute::ExternalNotification => {
Cow::Borrowed("Add External Notifications Column")
ColumnTitle::simple("Add External Notifications Column")
}
AddColumnRoute::Hashtag => Cow::Borrowed("Add Hashtag Column"),
AddColumnRoute::Hashtag => ColumnTitle::simple("Add Hashtag Column"),
AddColumnRoute::UndecidedIndividual => {
Cow::Borrowed("Subscribe to someone's notes")
ColumnTitle::simple("Subscribe to someone's notes")
}
AddColumnRoute::ExternalIndividual => {
Cow::Borrowed("Subscribe to someone else's notes")
ColumnTitle::simple("Subscribe to someone else's notes")
}
},
Route::Support => Cow::Borrowed("Damus Support"),
Route::NewDeck => Cow::Borrowed("Add Deck"),
Route::EditDeck(_) => Cow::Borrowed("Edit Deck"),
Route::Support => ColumnTitle::simple("Damus Support"),
Route::NewDeck => ColumnTitle::simple("Add Deck"),
Route::EditDeck(_) => ColumnTitle::simple("Edit Deck"),
}
}
}
Expand Down
73 changes: 66 additions & 7 deletions crates/notedeck_columns/src/timeline/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,75 @@ impl TimelineKind {
}
}

pub fn to_title(&self) -> Cow<'static, str> {
pub fn to_title(&self) -> ColumnTitle<'_> {
match self {
TimelineKind::List(list_kind) => match list_kind {
ListKind::Contact(_pubkey_source) => Cow::Borrowed("Contacts"),
ListKind::Contact(_pubkey_source) => ColumnTitle::simple("Contacts"),
},
TimelineKind::Notifications(_pubkey_source) => Cow::Borrowed("Notifications"),
TimelineKind::Profile(_pubkey_source) => Cow::Borrowed("Notes"),
TimelineKind::Universe => Cow::Borrowed("Universe"),
TimelineKind::Generic => Cow::Borrowed("Custom"),
TimelineKind::Hashtag(hashtag) => Cow::Owned(format!("#{}", hashtag)),
TimelineKind::Notifications(_pubkey_source) => ColumnTitle::simple("Notifications"),
TimelineKind::Profile(_pubkey_source) => ColumnTitle::needs_db(self),
TimelineKind::Universe => ColumnTitle::simple("Universe"),
TimelineKind::Generic => ColumnTitle::simple("Custom"),
TimelineKind::Hashtag(hashtag) => ColumnTitle::formatted(format!("#{}", hashtag)),
}
}
}

#[derive(Debug)]
pub struct TitleNeedsDb<'a> {
kind: &'a TimelineKind,
}

impl<'a> TitleNeedsDb<'a> {
pub fn new(kind: &'a TimelineKind) -> Self {
TitleNeedsDb { kind }
}

pub fn title<'txn>(
&self,
txn: &'txn Transaction,
ndb: &Ndb,
deck_author: Option<&Pubkey>,
) -> &'txn str {
if let TimelineKind::Profile(pubkey_source) = self.kind {
if let Some(deck_author) = deck_author {
let pubkey = pubkey_source.to_pubkey(deck_author);
let profile = ndb.get_profile_by_pubkey(txn, pubkey);
let m_name = profile
.ok()
.as_ref()
.and_then(|p| crate::profile::get_profile_name(p))
.map(|display_name| display_name.username());

m_name.unwrap_or("Profile")
} else {
// why would be there be no deck author? weird
"nostrich"
}
} else {
"Unknown"
}
}
}

/// This saves us from having to construct a transaction if we don't need to
/// for a particular column when rendering the title
#[derive(Debug)]
pub enum ColumnTitle<'a> {
Simple(Cow<'static, str>),
NeedsDb(TitleNeedsDb<'a>),
}

impl<'a> ColumnTitle<'a> {
pub fn simple(title: &'static str) -> Self {
Self::Simple(Cow::Borrowed(title))
}

pub fn formatted(title: String) -> Self {
Self::Simple(Cow::Owned(title))
}

pub fn needs_db(kind: &'a TimelineKind) -> ColumnTitle<'a> {
Self::NeedsDb(TitleNeedsDb::new(kind))
}
}
2 changes: 1 addition & 1 deletion crates/notedeck_columns/src/timeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use tracing::{debug, error, info, warn};
pub mod kind;
pub mod route;

pub use kind::{PubkeySource, TimelineKind};
pub use kind::{ColumnTitle, PubkeySource, TimelineKind};
pub use route::TimelineRoute;

#[derive(Debug, Hash, Copy, Clone, Eq, PartialEq)]
Expand Down
59 changes: 41 additions & 18 deletions crates/notedeck_columns/src/ui/column/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
column::Columns,
nav::RenderNavAction,
route::Route,
timeline::{TimelineId, TimelineRoute},
timeline::{ColumnTitle, TimelineId, TimelineRoute},
ui::{
self,
anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE},
Expand Down Expand Up @@ -105,17 +105,29 @@ impl<'a> NavTitle<'a> {
// not it looks cool
self.title_pfp(ui, prev, 32.0);

let back_label = ui.add(
egui::Label::new(
RichText::new(prev.title(self.columns).to_string())
.color(color)
.text_style(NotedeckTextStyle::Body.text_style()),
)
.selectable(false)
.sense(egui::Sense::click()),
);
let column_title = prev.title(self.columns);

let back_resp = match &column_title {
ColumnTitle::Simple(title) => ui.add(Self::back_label(title, color)),

ColumnTitle::NeedsDb(need_db) => {
let txn = Transaction::new(self.ndb).unwrap();
let title = need_db.title(&txn, self.ndb, self.deck_author);
ui.add(Self::back_label(title, color))
}
};

back_resp.union(chev_resp)
}

back_label.union(chev_resp)
fn back_label(title: &str, color: egui::Color32) -> egui::Label {
egui::Label::new(
RichText::new(title.to_string())
.color(color)
.text_style(NotedeckTextStyle::Body.text_style()),
)
.selectable(false)
.sense(egui::Sense::click())
}

fn delete_column_button(&self, ui: &mut egui::Ui, icon_width: f32) -> egui::Response {
Expand Down Expand Up @@ -209,14 +221,25 @@ impl<'a> NavTitle<'a> {
}
}

fn title_label_value(title: &str) -> egui::Label {
egui::Label::new(RichText::new(title).text_style(NotedeckTextStyle::Body.text_style()))
.selectable(false)
}

fn title_label(&self, ui: &mut egui::Ui, top: &Route) {
ui.add(
egui::Label::new(
RichText::new(top.title(self.columns))
.text_style(NotedeckTextStyle::Body.text_style()),
)
.selectable(false),
);
let column_title = top.title(self.columns);

match &column_title {
ColumnTitle::Simple(title) => {
ui.add(Self::title_label_value(title));
}

ColumnTitle::NeedsDb(need_db) => {
let txn = Transaction::new(self.ndb).unwrap();
let title = need_db.title(&txn, self.ndb, self.deck_author);
ui.add(Self::title_label_value(title));
}
};
}

fn title(
Expand Down

0 comments on commit 482a3cb

Please sign in to comment.