notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 7b9db55a0577bfeba44d123f8dd483ce60751e4b
parent a883ac8c349b0f396522d031fa73a445ee9b96bb
Author: kernelkind <kernelkind@gmail.com>
Date:   Sat,  5 Jul 2025 14:27:00 -0400

add UI for (un)follow

Signed-off-by: kernelkind <kernelkind@gmail.com>
Co-authored-by: Jakub Gladysz <jakub.gladysz@protonmail.com>
Co-authored-by: William Casarin <jb55@jb55.com>

Diffstat:
Mcrates/notedeck_columns/src/ui/profile/mod.rs | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 59 insertions(+), 12 deletions(-)

diff --git a/crates/notedeck_columns/src/ui/profile/mod.rs b/crates/notedeck_columns/src/ui/profile/mod.rs @@ -4,6 +4,7 @@ pub use edit::EditProfileView; use egui::{vec2, Color32, CornerRadius, Layout, Rect, RichText, ScrollArea, Sense, Stroke}; use enostr::Pubkey; use nostrdb::{ProfileRecord, Transaction}; +use notedeck_ui::profile::follow_button; use tracing::error; use crate::{ @@ -11,8 +12,8 @@ use crate::{ ui::timeline::{tabs_ui, TimelineTabView}, }; use notedeck::{ - name::get_display_name, profile::get_profile_url, Accounts, MuteFun, NoteAction, NoteContext, - NotedeckTextStyle, + name::get_display_name, profile::get_profile_url, Accounts, IsFollowing, MuteFun, NoteAction, + NoteContext, NotedeckTextStyle, }; use notedeck_ui::{ app_images, @@ -81,8 +82,8 @@ impl<'a, 'd> ProfileView<'a, 'd> { .ndb .get_profile_by_pubkey(&txn, self.pubkey.bytes()) { - if self.profile_body(ui, profile) { - action = Some(ProfileViewAction::EditProfile); + if let Some(profile_view_action) = self.profile_body(ui, profile) { + action = Some(profile_view_action); } } let profile_timeline = self @@ -133,8 +134,12 @@ impl<'a, 'd> ProfileView<'a, 'd> { output.inner } - fn profile_body(&mut self, ui: &mut egui::Ui, profile: ProfileRecord<'_>) -> bool { - let mut action = false; + fn profile_body( + &mut self, + ui: &mut egui::Ui, + profile: ProfileRecord<'_>, + ) -> Option<ProfileViewAction> { + let mut action = None; ui.vertical(|ui| { banner( ui, @@ -171,13 +176,49 @@ impl<'a, 'd> ProfileView<'a, 'd> { ui.ctx().copy_text(to_copy) } - if self.accounts.contains_full_kp(self.pubkey) { - ui.with_layout(Layout::right_to_left(egui::Align::Max), |ui| { - if ui.add(edit_profile_button()).clicked() { - action = true; + ui.with_layout(Layout::right_to_left(egui::Align::RIGHT), |ui| { + ui.add_space(24.0); + + let target_key = self.pubkey; + let selected = self.accounts.get_selected_account(); + + let profile_type = if selected.key.secret_key.is_none() { + ProfileType::ReadOnly + } else if &selected.key.pubkey == self.pubkey { + ProfileType::MyProfile + } else { + ProfileType::Followable(selected.is_following(target_key)) + }; + + match profile_type { + ProfileType::MyProfile => { + if ui.add(edit_profile_button()).clicked() { + action = Some(ProfileViewAction::EditProfile); + } } - }); - } + ProfileType::Followable(is_following) => { + let follow_button = ui.add(follow_button(is_following)); + + if follow_button.clicked() { + action = match is_following { + IsFollowing::Unknown => { + // don't do anything, we don't have contact list + None + } + + IsFollowing::Yes => { + Some(ProfileViewAction::Unfollow(target_key.to_owned())) + } + + IsFollowing::No => { + Some(ProfileViewAction::Follow(target_key.to_owned())) + } + }; + } + } + ProfileType::ReadOnly => {} + } + }); }); ui.add_space(18.0); @@ -217,6 +258,12 @@ impl<'a, 'd> ProfileView<'a, 'd> { } } +enum ProfileType { + MyProfile, + ReadOnly, + Followable(IsFollowing), +} + fn handle_link(ui: &mut egui::Ui, website_url: &str) { let img = if ui.visuals().dark_mode { app_images::link_image()