integrate EditProfileView

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-01-03 17:50:48 -05:00
parent 3384d2af14
commit 6645d4880f
7 changed files with 137 additions and 15 deletions

View File

@@ -6,7 +6,8 @@ use crate::{
deck_state::DeckState, deck_state::DeckState,
decks::{Deck, DecksAction, DecksCache}, decks::{Deck, DecksAction, DecksCache},
notes_holder::NotesHolder, notes_holder::NotesHolder,
profile::Profile, profile::{Profile, ProfileAction, SaveProfileChanges},
profile_state::ProfileState,
relay_pool_manager::RelayPoolManager, relay_pool_manager::RelayPoolManager,
route::Route, route::Route,
thread::Thread, thread::Thread,
@@ -21,6 +22,7 @@ use crate::{
configure_deck::ConfigureDeckView, configure_deck::ConfigureDeckView,
edit_deck::{EditDeckResponse, EditDeckView}, edit_deck::{EditDeckResponse, EditDeckView},
note::{PostAction, PostType}, note::{PostAction, PostType},
profile::EditProfileView,
support::SupportView, support::SupportView,
RelayView, View, RelayView, View,
}, },
@@ -39,6 +41,7 @@ pub enum RenderNavAction {
RemoveColumn, RemoveColumn,
PostAction(PostAction), PostAction(PostAction),
NoteAction(NoteAction), NoteAction(NoteAction),
ProfileAction(ProfileAction),
SwitchingAction(SwitchingAction), SwitchingAction(SwitchingAction),
} }
@@ -168,6 +171,15 @@ impl RenderNavResponse {
RenderNavAction::SwitchingAction(switching_action) => { RenderNavAction::SwitchingAction(switching_action) => {
switching_occured = switching_action.process(&mut app.decks_cache, ctx); switching_occured = switching_action.process(&mut app.decks_cache, ctx);
} }
RenderNavAction::ProfileAction(profile_action) => {
profile_action.process(
ctx.ndb,
ctx.pool,
get_active_columns_mut(ctx.accounts, &mut app.decks_cache)
.column_mut(col)
.router_mut(),
);
}
} }
} }
@@ -368,6 +380,35 @@ fn render_nav_body(
action action
} }
Route::EditProfile(pubkey) => {
let mut action = None;
if let Some(kp) = ctx.accounts.get_full(pubkey.bytes()) {
let state = app
.view_state
.pubkey_to_profile_state
.entry(*kp.pubkey)
.or_insert_with(|| {
let txn = Transaction::new(ctx.ndb).expect("txn");
if let Ok(record) = ctx.ndb.get_profile_by_pubkey(&txn, kp.pubkey.bytes()) {
ProfileState::from_profile(&record)
} else {
ProfileState::default()
}
});
if EditProfileView::new(state, ctx.img_cache).ui(ui) {
if let Some(taken_state) =
app.view_state.pubkey_to_profile_state.remove(kp.pubkey)
{
action = Some(RenderNavAction::ProfileAction(ProfileAction::SaveChanges(
SaveProfileChanges::new(kp.to_full(), taken_state),
)))
}
}
} else {
error!("Pubkey in EditProfile route did not have an nsec attached in Accounts");
}
action
}
} }
} }

View File

@@ -1,12 +1,16 @@
use enostr::{Filter, FullKeypair, Pubkey}; use enostr::{Filter, FullKeypair, Pubkey, RelayPool};
use nostrdb::{FilterBuilder, Ndb, Note, NoteBuilder, ProfileRecord, Transaction}; use nostrdb::{
FilterBuilder, Ndb, Note, NoteBuildOptions, NoteBuilder, ProfileRecord, Transaction,
};
use notedeck::{filter::default_limit, FilterState, MuteFun, NoteCache, NoteRef}; use notedeck::{filter::default_limit, FilterState, MuteFun, NoteCache, NoteRef};
use tracing::info;
use crate::{ use crate::{
multi_subscriber::MultiSubscriber, multi_subscriber::MultiSubscriber,
notes_holder::NotesHolder, notes_holder::NotesHolder,
profile_state::ProfileState, profile_state::ProfileState,
route::{Route, Router},
timeline::{copy_notes_into_timeline, PubkeySource, Timeline, TimelineKind, TimelineTab}, timeline::{copy_notes_into_timeline, PubkeySource, Timeline, TimelineKind, TimelineTab},
}; };
@@ -171,7 +175,7 @@ impl SaveProfileChanges {
add_client_tag(NoteBuilder::new()) add_client_tag(NoteBuilder::new())
.kind(0) .kind(0)
.content(&self.state.to_json()) .content(&self.state.to_json())
.sign(sec) .options(NoteBuildOptions::default().created_at(true).sign(sec))
.build() .build()
.expect("should build") .expect("should build")
} }
@@ -188,3 +192,23 @@ pub enum ProfileAction {
Edit(FullKeypair), Edit(FullKeypair),
SaveChanges(SaveProfileChanges), SaveChanges(SaveProfileChanges),
} }
impl ProfileAction {
pub fn process(&self, ndb: &Ndb, pool: &mut RelayPool, router: &mut Router<Route>) {
match self {
ProfileAction::Edit(kp) => {
router.route_to(Route::EditProfile(kp.pubkey));
}
ProfileAction::SaveChanges(changes) => {
let raw_msg = format!("[\"EVENT\",{}]", changes.to_note().json().unwrap());
let _ = ndb.process_client_event(raw_msg.as_str());
info!("sending {}", raw_msg);
pool.send(&enostr::ClientMessage::raw(raw_msg));
router.go_back();
}
}
}
}

View File

@@ -16,6 +16,7 @@ pub enum Route {
Relays, Relays,
ComposeNote, ComposeNote,
AddColumn(AddColumnRoute), AddColumn(AddColumnRoute),
EditProfile(Pubkey),
Support, Support,
NewDeck, NewDeck,
EditDeck(usize), EditDeck(usize),
@@ -104,6 +105,7 @@ impl Route {
Route::Support => ColumnTitle::simple("Damus Support"), Route::Support => ColumnTitle::simple("Damus Support"),
Route::NewDeck => ColumnTitle::simple("Add Deck"), Route::NewDeck => ColumnTitle::simple("Add Deck"),
Route::EditDeck(_) => ColumnTitle::simple("Edit Deck"), Route::EditDeck(_) => ColumnTitle::simple("Edit Deck"),
Route::EditProfile(_) => ColumnTitle::simple("Edit Profile"),
} }
} }
} }
@@ -215,6 +217,7 @@ impl fmt::Display for Route {
Route::Support => write!(f, "Support"), Route::Support => write!(f, "Support"),
Route::NewDeck => write!(f, "Add Deck"), Route::NewDeck => write!(f, "Add Deck"),
Route::EditDeck(_) => write!(f, "Edit Deck"), Route::EditDeck(_) => write!(f, "Edit Deck"),
Route::EditProfile(_) => write!(f, "Edit Profile"),
} }
} }
} }

View File

@@ -541,6 +541,11 @@ fn serialize_route(route: &Route, columns: &Columns) -> Option<String> {
selections.push(Selection::Keyword(Keyword::Edit)); selections.push(Selection::Keyword(Keyword::Edit));
selections.push(Selection::Payload(index.to_string())); selections.push(Selection::Payload(index.to_string()));
} }
Route::EditProfile(pubkey) => {
selections.push(Selection::Keyword(Keyword::Profile));
selections.push(Selection::Keyword(Keyword::Edit));
selections.push(Selection::Payload(pubkey.hex()));
}
} }
if selections.is_empty() { if selections.is_empty() {
@@ -649,6 +654,15 @@ fn selections_to_route(selections: Vec<Selection>) -> Option<CleanIntermediaryRo
Selection::Keyword(Keyword::DeckAuthor) => Some(CleanIntermediaryRoute::ToTimeline( Selection::Keyword(Keyword::DeckAuthor) => Some(CleanIntermediaryRoute::ToTimeline(
TimelineKind::profile(PubkeySource::DeckAuthor), TimelineKind::profile(PubkeySource::DeckAuthor),
)), )),
Selection::Keyword(Keyword::Edit) => {
if let Selection::Payload(hex) = selections.get(2)? {
Some(CleanIntermediaryRoute::ToRoute(Route::EditProfile(
Pubkey::from_hex(hex.as_str()).ok()?,
)))
} else {
None
}
}
_ => None, _ => None,
}, },
Selection::Keyword(Keyword::Universe) => { Selection::Keyword(Keyword::Universe) => {

View File

@@ -3,7 +3,7 @@ use crate::{
draft::Drafts, draft::Drafts,
nav::RenderNavAction, nav::RenderNavAction,
notes_holder::NotesHolderStorage, notes_holder::NotesHolderStorage,
profile::Profile, profile::{Profile, ProfileAction},
thread::Thread, thread::Thread,
timeline::{TimelineId, TimelineKind}, timeline::{TimelineId, TimelineKind},
ui::{ ui::{
@@ -117,6 +117,7 @@ pub fn render_timeline_route(
TimelineRoute::Profile(pubkey) => render_profile_route( TimelineRoute::Profile(pubkey) => render_profile_route(
&pubkey, &pubkey,
accounts,
ndb, ndb,
profiles, profiles,
img_cache, img_cache,
@@ -155,6 +156,7 @@ pub fn render_timeline_route(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn render_profile_route( pub fn render_profile_route(
pubkey: &Pubkey, pubkey: &Pubkey,
accounts: &Accounts,
ndb: &Ndb, ndb: &Ndb,
profiles: &mut NotesHolderStorage<Profile>, profiles: &mut NotesHolderStorage<Profile>,
img_cache: &mut ImageCache, img_cache: &mut ImageCache,
@@ -163,8 +165,9 @@ pub fn render_profile_route(
ui: &mut egui::Ui, ui: &mut egui::Ui,
is_muted: &MuteFun, is_muted: &MuteFun,
) -> Option<RenderNavAction> { ) -> Option<RenderNavAction> {
let note_action = ProfileView::new( let action = ProfileView::new(
pubkey, pubkey,
accounts,
col, col,
profiles, profiles,
ndb, ndb,
@@ -174,5 +177,16 @@ pub fn render_profile_route(
) )
.ui(ui, is_muted); .ui(ui, is_muted);
note_action.map(RenderNavAction::NoteAction) if let Some(action) = action {
match action {
ui::profile::ProfileViewAction::EditProfile => accounts
.get_full(pubkey.bytes())
.map(|kp| RenderNavAction::ProfileAction(ProfileAction::Edit(kp.to_full()))),
ui::profile::ProfileViewAction::Note(note_action) => {
Some(RenderNavAction::NoteAction(note_action))
}
}
} else {
None
}
} }

View File

@@ -256,6 +256,9 @@ impl<'a> NavTitle<'a> {
Route::Relays => {} Route::Relays => {}
Route::NewDeck => {} Route::NewDeck => {}
Route::EditDeck(_) => {} Route::EditDeck(_) => {}
Route::EditProfile(pubkey) => {
self.show_profile(ui, pubkey, pfp_size);
}
} }
} }

View File

@@ -18,10 +18,11 @@ use tracing::error;
use crate::{actionbar::NoteAction, notes_holder::NotesHolderStorage, profile::Profile}; use crate::{actionbar::NoteAction, notes_holder::NotesHolderStorage, profile::Profile};
use super::timeline::{tabs_ui, TimelineTabView}; use super::timeline::{tabs_ui, TimelineTabView};
use notedeck::{ImageCache, MuteFun, NoteCache, NotedeckTextStyle}; use notedeck::{Accounts, ImageCache, MuteFun, NoteCache, NotedeckTextStyle};
pub struct ProfileView<'a> { pub struct ProfileView<'a> {
pubkey: &'a Pubkey, pubkey: &'a Pubkey,
accounts: &'a Accounts,
col_id: usize, col_id: usize,
profiles: &'a mut NotesHolderStorage<Profile>, profiles: &'a mut NotesHolderStorage<Profile>,
note_options: NoteOptions, note_options: NoteOptions,
@@ -30,9 +31,16 @@ pub struct ProfileView<'a> {
img_cache: &'a mut ImageCache, img_cache: &'a mut ImageCache,
} }
pub enum ProfileViewAction {
EditProfile,
Note(NoteAction),
}
impl<'a> ProfileView<'a> { impl<'a> ProfileView<'a> {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
pubkey: &'a Pubkey, pubkey: &'a Pubkey,
accounts: &'a Accounts,
col_id: usize, col_id: usize,
profiles: &'a mut NotesHolderStorage<Profile>, profiles: &'a mut NotesHolderStorage<Profile>,
ndb: &'a Ndb, ndb: &'a Ndb,
@@ -42,6 +50,7 @@ impl<'a> ProfileView<'a> {
) -> Self { ) -> Self {
ProfileView { ProfileView {
pubkey, pubkey,
accounts,
col_id, col_id,
profiles, profiles,
ndb, ndb,
@@ -51,15 +60,18 @@ impl<'a> ProfileView<'a> {
} }
} }
pub fn ui(&mut self, ui: &mut egui::Ui, is_muted: &MuteFun) -> Option<NoteAction> { pub fn ui(&mut self, ui: &mut egui::Ui, is_muted: &MuteFun) -> Option<ProfileViewAction> {
let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey)); let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey));
ScrollArea::vertical() ScrollArea::vertical()
.id_salt(scroll_id) .id_salt(scroll_id)
.show(ui, |ui| { .show(ui, |ui| {
let mut action = None;
let txn = Transaction::new(self.ndb).expect("txn"); let txn = Transaction::new(self.ndb).expect("txn");
if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, self.pubkey.bytes()) { if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, self.pubkey.bytes()) {
self.profile_body(ui, profile); if self.profile_body(ui, profile) {
action = Some(ProfileViewAction::EditProfile);
}
} }
let profile = self let profile = self
.profiles .profiles
@@ -82,7 +94,7 @@ impl<'a> ProfileView<'a> {
let reversed = false; let reversed = false;
TimelineTabView::new( if let Some(note_action) = TimelineTabView::new(
profile.timeline.current_view(), profile.timeline.current_view(),
reversed, reversed,
self.note_options, self.note_options,
@@ -92,11 +104,16 @@ impl<'a> ProfileView<'a> {
self.img_cache, self.img_cache,
) )
.show(ui) .show(ui)
{
action = Some(ProfileViewAction::Note(note_action));
}
action
}) })
.inner .inner
} }
fn profile_body(&mut self, ui: &mut egui::Ui, profile: ProfileRecord<'_>) { fn profile_body(&mut self, ui: &mut egui::Ui, profile: ProfileRecord<'_>) -> bool {
let mut action = false;
ui.vertical(|ui| { ui.vertical(|ui| {
banner( banner(
ui, ui,
@@ -129,9 +146,13 @@ impl<'a> ProfileView<'a> {
}); });
} }
ui.with_layout(Layout::right_to_left(egui::Align::Max), |ui| { if self.accounts.contains_full_kp(self.pubkey) {
ui.add(edit_profile_button()) ui.with_layout(Layout::right_to_left(egui::Align::Max), |ui| {
}); if ui.add(edit_profile_button()).clicked() {
action = true;
}
});
}
}); });
ui.add_space(18.0); ui.add_space(18.0);
@@ -163,6 +184,8 @@ impl<'a> ProfileView<'a> {
}); });
}); });
}); });
action
} }
} }