Skip to content

Commit 2ae023b

Browse files
committed
wip: render profile pics in column headers
Signed-off-by: William Casarin <[email protected]>
1 parent 82aee7d commit 2ae023b

File tree

3 files changed

+48
-143
lines changed

3 files changed

+48
-143
lines changed

src/route.rs

+19-40
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use enostr::{NoteId, Pubkey};
22
use nostrdb::{Ndb, Transaction};
33
use serde::{Deserialize, Serialize};
4-
use std::fmt::{self};
4+
use std::{
5+
borrow::Cow,
6+
fmt::{self},
7+
};
58

69
use crate::{
710
accounts::AccountsRoute,
@@ -65,61 +68,37 @@ impl Route {
6568
Route::Accounts(AccountsRoute::AddAccount)
6669
}
6770

68-
pub fn title(&self, columns: &Columns, ndb: &Ndb) -> String {
71+
pub fn title(&self, columns: &Columns) -> Cow<'static, str> {
6972
match self {
7073
Route::Timeline(tlr) => match tlr {
7174
TimelineRoute::Timeline(id) => {
7275
let timeline = columns
7376
.find_timeline(*id)
7477
.expect("expected to find timeline");
75-
timeline.kind.to_title(ndb)
76-
}
77-
TimelineRoute::Thread(id) => {
78-
let txn = Transaction::new(ndb).expect("txn");
79-
format!(
80-
"{}'s Thread",
81-
get_note_users_displayname_string(&txn, ndb, id)
82-
)
83-
}
84-
TimelineRoute::Reply(id) => {
85-
let txn = Transaction::new(ndb).expect("txn");
86-
format!(
87-
"{}'s Reply",
88-
get_note_users_displayname_string(&txn, ndb, id)
89-
)
90-
}
91-
TimelineRoute::Quote(id) => {
92-
let txn = Transaction::new(ndb).expect("txn");
93-
format!(
94-
"{}'s Quote",
95-
get_note_users_displayname_string(&txn, ndb, id)
96-
)
97-
}
98-
TimelineRoute::Profile(pubkey) => {
99-
let txn = Transaction::new(ndb).expect("txn");
100-
format!(
101-
"{}'s Profile",
102-
get_profile_displayname_string(&txn, ndb, pubkey)
103-
)
78+
timeline.kind.to_title()
10479
}
80+
TimelineRoute::Thread(_id) => Cow::Borrowed("Thread"),
81+
TimelineRoute::Reply(_id) => Cow::Borrowed("Reply"),
82+
TimelineRoute::Quote(_id) => Cow::Borrowed("Quote"),
83+
TimelineRoute::Profile(_pubkey) => Cow::Borrowed("Profile"),
10584
},
10685

107-
Route::Relays => "Relays".to_owned(),
86+
Route::Relays => Cow::Borrowed("Relays"),
10887

10988
Route::Accounts(amr) => match amr {
110-
AccountsRoute::Accounts => "Accounts".to_owned(),
111-
AccountsRoute::AddAccount => "Add Account".to_owned(),
89+
AccountsRoute::Accounts => Cow::Borrowed("Accounts"),
90+
AccountsRoute::AddAccount => Cow::Borrowed("Add Account"),
11291
},
113-
Route::ComposeNote => "Compose Note".to_owned(),
92+
Route::ComposeNote => Cow::Borrowed("Compose Note"),
11493
Route::AddColumn(c) => match c {
115-
AddColumnRoute::Base => "Add Column".to_owned(),
116-
AddColumnRoute::UndecidedNotification => "Add Notifications Column".to_owned(),
94+
AddColumnRoute::Base => Cow::Borrowed("Add Column"),
95+
AddColumnRoute::UndecidedNotification => Cow::Borrowed("Add Notifications Column"),
11796
AddColumnRoute::ExternalNotification => {
118-
"Add External Notifications Column".to_owned()
97+
Cow::Borrowed("Add External Notifications Column")
11998
}
120-
AddColumnRoute::Hashtag => "Add Hashtag Column".to_owned(),
99+
AddColumnRoute::Hashtag => Cow::Borrowed("Add Hashtag Column"),
121100
},
122-
Route::Support => "Damus Support".to_owned(),
101+
Route::Support => Cow::Borrowed("Damus Support"),
123102
}
124103
}
125104
}

src/timeline/kind.rs

+8-35
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::ui::profile::preview::get_profile_displayname_string;
66
use enostr::{Filter, Pubkey};
77
use nostrdb::{Ndb, Transaction};
88
use serde::{Deserialize, Serialize};
9-
use std::fmt::Display;
9+
use std::{borrow::Cow, fmt::Display};
1010
use tracing::{error, warn};
1111

1212
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -194,43 +194,16 @@ impl TimelineKind {
194194
}
195195
}
196196

197-
pub fn to_title(&self, ndb: &Ndb) -> String {
197+
pub fn to_title(&self) -> Cow<'static, str> {
198198
match self {
199199
TimelineKind::List(list_kind) => match list_kind {
200-
ListKind::Contact(pubkey_source) => match pubkey_source {
201-
PubkeySource::Explicit(pubkey) => {
202-
let txn = Transaction::new(ndb).expect("txn");
203-
format!(
204-
"{}'s Contacts",
205-
get_profile_displayname_string(&txn, ndb, pubkey)
206-
)
207-
}
208-
PubkeySource::DeckAuthor => "Contacts".to_owned(),
209-
},
210-
},
211-
TimelineKind::Notifications(pubkey_source) => match pubkey_source {
212-
PubkeySource::DeckAuthor => "Notifications".to_owned(),
213-
PubkeySource::Explicit(pk) => {
214-
let txn = Transaction::new(ndb).expect("txn");
215-
format!(
216-
"{}'s Notifications",
217-
get_profile_displayname_string(&txn, ndb, pk)
218-
)
219-
}
220-
},
221-
TimelineKind::Profile(pubkey_source) => match pubkey_source {
222-
PubkeySource::DeckAuthor => "Profile".to_owned(),
223-
PubkeySource::Explicit(pk) => {
224-
let txn = Transaction::new(ndb).expect("txn");
225-
format!(
226-
"{}'s Profile",
227-
get_profile_displayname_string(&txn, ndb, pk)
228-
)
229-
}
200+
ListKind::Contact(_pubkey_source) => Cow::Borrowed("Contacts"),
230201
},
231-
TimelineKind::Universe => "Universe".to_owned(),
232-
TimelineKind::Generic => "Custom Filter".to_owned(),
233-
TimelineKind::Hashtag(hashtag) => format!("#{}", hashtag),
202+
TimelineKind::Notifications(_pubkey_source) => Cow::Borrowed("Notifications"),
203+
TimelineKind::Profile(pubkey_source) => Cow::Borrowed("Profile"),
204+
TimelineKind::Universe => Cow::Borrowed("Universe"),
205+
TimelineKind::Generic => Cow::Borrowed("Custom"),
206+
TimelineKind::Hashtag(hashtag) => Cow::Owned(format!("#{}", hashtag)),
234207
}
235208
}
236209
}

src/ui/column/header.rs

+21-68
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
},
1313
};
1414

15-
use egui::{pos2, Color32, Stroke};
15+
use egui::{pos2, Color32, RichText, Stroke};
1616
use enostr::Pubkey;
1717
use nostrdb::{Ndb, Transaction};
1818

@@ -56,7 +56,6 @@ impl<'a> NavTitle<'a> {
5656
) -> Option<RenderNavAction> {
5757
let icon_width = 32.0;
5858
let padding_external = 16.0;
59-
let padding_internal = 8.0;
6059
let has_back = prev(self.routes).is_some();
6160

6261
let (spacing_rect, titlebar_rect) = allocated_response
@@ -77,20 +76,7 @@ impl<'a> NavTitle<'a> {
7776
(allocated_response, None)
7877
};
7978

80-
self.title(
81-
ui,
82-
self.routes.last().unwrap(),
83-
titlebar_resp.rect,
84-
icon_width,
85-
if has_back {
86-
padding_internal
87-
} else {
88-
padding_external
89-
},
90-
);
91-
92-
let delete_button_resp =
93-
self.delete_column_button(ui, titlebar_resp, icon_width, padding_external);
79+
let delete_button_resp = self.title(ui, self.routes.last().unwrap());
9480

9581
if delete_button_resp.clicked() {
9682
Some(RenderNavAction::RemoveColumn)
@@ -143,7 +129,6 @@ impl<'a> NavTitle<'a> {
143129
fn delete_column_button(
144130
&self,
145131
ui: &mut egui::Ui,
146-
allocation_response: egui::Response,
147132
icon_width: f32,
148133
padding: f32,
149134
) -> egui::Response {
@@ -157,26 +142,15 @@ impl<'a> NavTitle<'a> {
157142
};
158143
let img = egui::Image::new(img_data).max_width(img_size);
159144

160-
let button_rect = {
161-
let titlebar_rect = allocation_response.rect;
162-
let titlebar_width = titlebar_rect.width();
163-
let titlebar_center = titlebar_rect.center();
164-
let button_center_y = titlebar_center.y;
165-
let button_center_x =
166-
titlebar_center.x + (titlebar_width / 2.0) - (max_size / 2.0) - padding;
167-
egui::Rect::from_center_size(
168-
pos2(button_center_x, button_center_y),
169-
egui::vec2(max_size, max_size),
170-
)
171-
};
172-
173-
let helper = AnimationHelper::new_from_rect(ui, "delete-column-button", button_rect);
145+
let helper =
146+
AnimationHelper::new(ui, "delete-column-button", egui::vec2(max_size, max_size));
174147

175148
let cur_img_size = helper.scale_1d_pos(img_size);
176149

177150
let animation_rect = helper.get_animation_rect();
178151
let animation_resp = helper.take_animation_response();
179-
if allocation_response.union(animation_resp.clone()).hovered() {
152+
153+
if animation_resp.hovered() {
180154
img.paint_at(ui, animation_rect.shrink((max_size - cur_img_size) / 2.0));
181155
}
182156

@@ -217,7 +191,7 @@ impl<'a> NavTitle<'a> {
217191
}
218192

219193
fn title_pfp(&mut self, ui: &mut egui::Ui, top: &Route) {
220-
let pfp_size = 48.0;
194+
let pfp_size = 32.0;
221195
match top {
222196
Route::Timeline(tlr) => match tlr {
223197
TimelineRoute::Timeline(tlid) => {
@@ -249,44 +223,23 @@ impl<'a> NavTitle<'a> {
249223
}
250224
}
251225

252-
fn title(
253-
&mut self,
254-
ui: &mut egui::Ui,
255-
top: &Route,
256-
titlebar_rect: egui::Rect,
257-
icon_width: f32,
258-
padding: f32,
259-
) {
260-
let painter = ui.painter_at(titlebar_rect);
261-
262-
self.title_pfp(ui, top);
263-
264-
let font = egui::FontId::new(
265-
get_font_size(ui.ctx(), &NotedeckTextStyle::Body),
266-
egui::FontFamily::Name(NamedFontFamily::Bold.as_str().into()),
267-
);
268-
269-
let max_title_width = titlebar_rect.width() - icon_width - padding * 2.;
226+
fn title(&mut self, ui: &mut egui::Ui, top: &Route) -> egui::Response {
227+
ui.horizontal(|ui| {
228+
ui.spacing_mut().item_spacing.x = 10.0;
270229

271-
let title_galley = ui.fonts(|f| {
272-
f.layout(
273-
top.to_string(),
274-
font,
275-
ui.visuals().text_color(),
276-
max_title_width,
277-
)
278-
});
279-
280-
let pos = {
281-
let titlebar_center = titlebar_rect.center();
282-
let text_height = title_galley.rect.height();
230+
self.title_pfp(ui, top);
283231

284-
let galley_pos_x = titlebar_rect.left() + padding;
285-
let galley_pos_y = titlebar_center.y - (text_height / 2.);
286-
pos2(galley_pos_x, galley_pos_y)
287-
};
232+
ui.label(
233+
RichText::new(top.title(self.columns))
234+
.text_style(NotedeckTextStyle::Body.text_style()),
235+
);
288236

289-
painter.galley(pos, title_galley, Color32::WHITE);
237+
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
238+
self.delete_column_button(ui, 32.0, 10.0)
239+
})
240+
.inner
241+
})
242+
.inner
290243
}
291244
}
292245

0 commit comments

Comments
 (0)