mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-19 09:34:19 +01:00
ui/profile: fix dubious profile editing
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -14,7 +14,7 @@ pub use filter::Filter;
|
|||||||
pub use keypair::{FilledKeypair, FullKeypair, Keypair, KeypairUnowned, SerializableKeypair};
|
pub use keypair::{FilledKeypair, FullKeypair, Keypair, KeypairUnowned, SerializableKeypair};
|
||||||
pub use nostr::SecretKey;
|
pub use nostr::SecretKey;
|
||||||
pub use note::{Note, NoteId};
|
pub use note::{Note, NoteId};
|
||||||
pub use profile::Profile;
|
pub use profile::ProfileState;
|
||||||
pub use pubkey::{Pubkey, PubkeyRef};
|
pub use pubkey::{Pubkey, PubkeyRef};
|
||||||
pub use relay::message::{RelayEvent, RelayMessage};
|
pub use relay::message::{RelayEvent, RelayMessage};
|
||||||
pub use relay::pool::{PoolEvent, PoolRelay, RelayPool};
|
pub use relay::pool::{PoolEvent, PoolRelay, RelayPool};
|
||||||
|
|||||||
@@ -1,38 +1,104 @@
|
|||||||
use serde_json::Value;
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Profile(Value);
|
pub struct ProfileState(Value);
|
||||||
|
|
||||||
impl Profile {
|
impl ProfileState {
|
||||||
pub fn new(value: Value) -> Profile {
|
pub fn new(value: Map<String, Value>) -> Self {
|
||||||
Profile(value)
|
Self(Value::Object(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_str(&self, name: &str) -> Option<&str> {
|
||||||
|
self.0.get(name).and_then(|v| v.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn values_mut(&mut self) -> &mut Map<String, Value> {
|
||||||
|
self.0.as_object_mut().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert or overwrite an existing value with a string
|
||||||
|
pub fn str_mut(&mut self, name: &str) -> &mut String {
|
||||||
|
let val = self
|
||||||
|
.values_mut()
|
||||||
|
.entry(name)
|
||||||
|
.or_insert(Value::String("".to_string()));
|
||||||
|
|
||||||
|
// if its not a string, make it one. this will overrwrite
|
||||||
|
// the old value, so be careful
|
||||||
|
if !val.is_string() {
|
||||||
|
*val = Value::String("".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
match val {
|
||||||
|
Value::String(s) => s,
|
||||||
|
// SAFETY: we replace it above, so its impossible to be something
|
||||||
|
// other than a string
|
||||||
|
_ => panic!("impossible"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> &Value {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_json(&self) -> String {
|
||||||
|
// SAFETY: serializing a value should be irrefutable
|
||||||
|
serde_json::to_string(self.value()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn name(&self) -> Option<&str> {
|
pub fn name(&self) -> Option<&str> {
|
||||||
self.0["name"].as_str()
|
self.get_str("name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn banner(&self) -> Option<&str> {
|
||||||
|
self.get_str("name")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn display_name(&self) -> Option<&str> {
|
pub fn display_name(&self) -> Option<&str> {
|
||||||
self.0["display_name"].as_str()
|
self.get_str("display_name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn lud06(&self) -> Option<&str> {
|
pub fn lud06(&self) -> Option<&str> {
|
||||||
self.0["lud06"].as_str()
|
self.get_str("lud06")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn nip05(&self) -> Option<&str> {
|
||||||
|
self.get_str("nip05")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn lud16(&self) -> Option<&str> {
|
pub fn lud16(&self) -> Option<&str> {
|
||||||
self.0["lud16"].as_str()
|
self.get_str("lud16")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn about(&self) -> Option<&str> {
|
pub fn about(&self) -> Option<&str> {
|
||||||
self.0["about"].as_str()
|
self.get_str("about")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn picture(&self) -> Option<&str> {
|
pub fn picture(&self) -> Option<&str> {
|
||||||
self.0["picture"].as_str()
|
self.get_str("picture")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn website(&self) -> Option<&str> {
|
pub fn website(&self) -> Option<&str> {
|
||||||
self.0["website"].as_str()
|
self.get_str("website")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_note_contents(contents: &str) -> Self {
|
||||||
|
let json = serde_json::from_str(contents);
|
||||||
|
let data = if let Ok(Value::Object(data)) = json {
|
||||||
|
data
|
||||||
|
} else {
|
||||||
|
Map::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::new(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ mod multi_subscriber;
|
|||||||
mod nav;
|
mod nav;
|
||||||
mod post;
|
mod post;
|
||||||
mod profile;
|
mod profile;
|
||||||
mod profile_state;
|
|
||||||
mod route;
|
mod route;
|
||||||
mod search;
|
mod search;
|
||||||
mod subscriptions;
|
mod subscriptions;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::{
|
|||||||
deck_state::DeckState,
|
deck_state::DeckState,
|
||||||
decks::{Deck, DecksAction, DecksCache},
|
decks::{Deck, DecksAction, DecksCache},
|
||||||
profile::{ProfileAction, SaveProfileChanges},
|
profile::{ProfileAction, SaveProfileChanges},
|
||||||
profile_state::ProfileState,
|
|
||||||
route::{Route, Router, SingletonRouter},
|
route::{Route, Router, SingletonRouter},
|
||||||
timeline::{
|
timeline::{
|
||||||
route::{render_thread_route, render_timeline_route},
|
route::{render_thread_route, render_timeline_route},
|
||||||
@@ -28,9 +27,11 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use egui_nav::{Nav, NavAction, NavResponse, NavUiType, Percent, PopupResponse, PopupSheet};
|
use egui_nav::{Nav, NavAction, NavResponse, NavUiType, Percent, PopupResponse, PopupSheet};
|
||||||
use nostrdb::Transaction;
|
use enostr::ProfileState;
|
||||||
|
use nostrdb::{Filter, Transaction};
|
||||||
use notedeck::{
|
use notedeck::{
|
||||||
get_current_default_msats, get_current_wallet, AppContext, NoteAction, NoteContext, RelayAction,
|
get_current_default_msats, get_current_wallet, ui::is_narrow, AppContext, NoteAction,
|
||||||
|
NoteContext, RelayAction,
|
||||||
};
|
};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
@@ -674,8 +675,17 @@ fn render_nav_body(
|
|||||||
.entry(*kp.pubkey)
|
.entry(*kp.pubkey)
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
let txn = Transaction::new(ctx.ndb).expect("txn");
|
let txn = Transaction::new(ctx.ndb).expect("txn");
|
||||||
if let Ok(record) = ctx.ndb.get_profile_by_pubkey(&txn, kp.pubkey.bytes()) {
|
let filter = Filter::new_with_capacity(1)
|
||||||
ProfileState::from_profile(&record)
|
.kinds([0])
|
||||||
|
.authors([kp.pubkey.bytes()])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let Ok(results) = ctx.ndb.query(&txn, &[filter], 1) else {
|
||||||
|
return ProfileState::default();
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(result) = results.first() {
|
||||||
|
ProfileState::from_note_contents(result.note.content())
|
||||||
} else {
|
} else {
|
||||||
ProfileState::default()
|
ProfileState::default()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use enostr::{FilledKeypair, FullKeypair, Pubkey, RelayPool};
|
use enostr::{FilledKeypair, FullKeypair, ProfileState, Pubkey, RelayPool};
|
||||||
use nostrdb::{Ndb, Note, NoteBuildOptions, NoteBuilder, Transaction};
|
use nostrdb::{Ndb, Note, NoteBuildOptions, NoteBuilder, Transaction};
|
||||||
|
|
||||||
use notedeck::{Accounts, ContactState};
|
use notedeck::{Accounts, ContactState};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{nav::RouterAction, profile_state::ProfileState, route::Route};
|
use crate::{nav::RouterAction, route::Route};
|
||||||
|
|
||||||
pub struct SaveProfileChanges {
|
pub struct SaveProfileChanges {
|
||||||
pub kp: FullKeypair,
|
pub kp: FullKeypair,
|
||||||
@@ -149,13 +149,17 @@ fn send_kind_3_event(ndb: &Ndb, pool: &mut RelayPool, accounts: &Accounts, actio
|
|||||||
let contact_note = match ndb.get_note_by_key(&txn, *note_key).ok() {
|
let contact_note = match ndb.get_note_by_key(&txn, *note_key).ok() {
|
||||||
Some(n) => n,
|
Some(n) => n,
|
||||||
None => {
|
None => {
|
||||||
tracing::error!("Somehow we are in state ContactState::Received but the contact note key doesn't exist");
|
tracing::error!(
|
||||||
|
"Somehow we are in state ContactState::Received but the contact note key doesn't exist"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if contact_note.kind() != 3 {
|
if contact_note.kind() != 3 {
|
||||||
tracing::error!("Something very wrong just occured. The key for the supposed contact note yielded a note which was not a contact...");
|
tracing::error!(
|
||||||
|
"Something very wrong just occured. The key for the supposed contact note yielded a note which was not a contact..."
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
use nostrdb::{NdbProfile, ProfileRecord};
|
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
|
||||||
pub struct ProfileState {
|
|
||||||
pub display_name: String,
|
|
||||||
pub name: String,
|
|
||||||
pub picture: String,
|
|
||||||
pub banner: String,
|
|
||||||
pub about: String,
|
|
||||||
pub website: String,
|
|
||||||
pub lud16: String,
|
|
||||||
pub nip05: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProfileState {
|
|
||||||
pub fn from_profile(record: &ProfileRecord<'_>) -> Self {
|
|
||||||
let display_name = get_item(record, |p| p.display_name());
|
|
||||||
let username = get_item(record, |p| p.name());
|
|
||||||
let profile_picture = get_item(record, |p| p.picture());
|
|
||||||
let cover_image = get_item(record, |p| p.banner());
|
|
||||||
let about = get_item(record, |p| p.about());
|
|
||||||
let website = get_item(record, |p| p.website());
|
|
||||||
let lud16 = get_item(record, |p| p.lud16());
|
|
||||||
let nip05 = get_item(record, |p| p.nip05());
|
|
||||||
|
|
||||||
Self {
|
|
||||||
display_name,
|
|
||||||
name: username,
|
|
||||||
picture: profile_picture,
|
|
||||||
banner: cover_image,
|
|
||||||
about,
|
|
||||||
website,
|
|
||||||
lud16,
|
|
||||||
nip05,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_json(&self) -> String {
|
|
||||||
let mut fields = Vec::new();
|
|
||||||
|
|
||||||
if !self.display_name.is_empty() {
|
|
||||||
fields.push(format!(r#""display_name":"{}""#, self.display_name));
|
|
||||||
}
|
|
||||||
if !self.name.is_empty() {
|
|
||||||
fields.push(format!(r#""name":"{}""#, self.name));
|
|
||||||
}
|
|
||||||
if !self.picture.is_empty() {
|
|
||||||
fields.push(format!(r#""picture":"{}""#, self.picture));
|
|
||||||
}
|
|
||||||
if !self.banner.is_empty() {
|
|
||||||
fields.push(format!(r#""banner":"{}""#, self.banner));
|
|
||||||
}
|
|
||||||
if !self.about.is_empty() {
|
|
||||||
fields.push(format!(r#""about":"{}""#, self.about));
|
|
||||||
}
|
|
||||||
if !self.website.is_empty() {
|
|
||||||
fields.push(format!(r#""website":"{}""#, self.website));
|
|
||||||
}
|
|
||||||
if !self.lud16.is_empty() {
|
|
||||||
fields.push(format!(r#""lud16":"{}""#, self.lud16));
|
|
||||||
}
|
|
||||||
if !self.nip05.is_empty() {
|
|
||||||
fields.push(format!(r#""nip05":"{}""#, self.nip05));
|
|
||||||
}
|
|
||||||
|
|
||||||
format!("{{{}}}", fields.join(","))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_item<'a>(
|
|
||||||
record: &ProfileRecord<'a>,
|
|
||||||
item_retriever: fn(NdbProfile<'a>) -> Option<&'a str>,
|
|
||||||
) -> String {
|
|
||||||
record
|
|
||||||
.record()
|
|
||||||
.profile()
|
|
||||||
.and_then(item_retriever)
|
|
||||||
.map_or_else(String::new, ToString::to_string)
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,7 @@ pub fn sample_pool() -> RelayPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// my (jb55) profile
|
// my (jb55) profile
|
||||||
const TEST_PROFILE_DATA: [u8; 448] = [
|
const _TEST_PROFILE_DATA: [u8; 448] = [
|
||||||
0x04, 0x00, 0x00, 0x00, 0x54, 0xfe, 0xff, 0xff, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x04, 0x00, 0x00, 0x00, 0x54, 0xfe, 0xff, 0xff, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xd6, 0xd9, 0xc6, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0xd6, 0xd9, 0xc6, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x66, 0x69, 0x78, 0x6d,
|
0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x66, 0x69, 0x78, 0x6d,
|
||||||
@@ -62,8 +62,8 @@ pub fn test_pubkey() -> &'static [u8; 32] {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn test_profile_record() -> ProfileRecord<'static> {
|
pub fn _test_profile_record() -> ProfileRecord<'static> {
|
||||||
ProfileRecord::new_owned(&TEST_PROFILE_DATA).unwrap()
|
ProfileRecord::new_owned(&_TEST_PROFILE_DATA).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use core::f32;
|
use core::f32;
|
||||||
|
|
||||||
use crate::profile_state::ProfileState;
|
|
||||||
use egui::{vec2, Button, CornerRadius, Layout, Margin, RichText, ScrollArea, TextEdit};
|
use egui::{vec2, Button, CornerRadius, Layout, Margin, RichText, ScrollArea, TextEdit};
|
||||||
|
use enostr::ProfileState;
|
||||||
use notedeck::{profile::unwrap_profile_url, Images, NotedeckTextStyle};
|
use notedeck::{profile::unwrap_profile_url, Images, NotedeckTextStyle};
|
||||||
use notedeck_ui::{profile::banner, ProfilePic};
|
use notedeck_ui::{profile::banner, ProfilePic};
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ impl<'a> EditProfileView<'a> {
|
|||||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> bool {
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> bool {
|
||||||
ScrollArea::vertical()
|
ScrollArea::vertical()
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
banner(ui, Some(&self.state.banner), 188.0);
|
banner(ui, self.state.banner(), 188.0);
|
||||||
|
|
||||||
let padding = 24.0;
|
let padding = 24.0;
|
||||||
notedeck_ui::padding(padding, ui, |ui| {
|
notedeck_ui::padding(padding, ui, |ui| {
|
||||||
@@ -53,11 +53,7 @@ impl<'a> EditProfileView<'a> {
|
|||||||
pfp_rect.set_height(size);
|
pfp_rect.set_height(size);
|
||||||
let pfp_rect = pfp_rect.translate(egui::vec2(0.0, -(padding + 2.0 + (size / 2.0))));
|
let pfp_rect = pfp_rect.translate(egui::vec2(0.0, -(padding + 2.0 + (size / 2.0))));
|
||||||
|
|
||||||
let pfp_url = unwrap_profile_url(if self.state.picture.is_empty() {
|
let pfp_url = unwrap_profile_url(self.state.picture());
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(&self.state.picture)
|
|
||||||
});
|
|
||||||
ui.put(
|
ui.put(
|
||||||
pfp_rect,
|
pfp_rect,
|
||||||
&mut ProfilePic::new(self.img_cache, pfp_url)
|
&mut ProfilePic::new(self.img_cache, pfp_url)
|
||||||
@@ -67,65 +63,72 @@ impl<'a> EditProfileView<'a> {
|
|||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Display name"));
|
ui.add(label("Display name"));
|
||||||
ui.add(singleline_textedit(&mut self.state.display_name));
|
ui.add(singleline_textedit(self.state.str_mut("display_name")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Username"));
|
ui.add(label("Username"));
|
||||||
ui.add(singleline_textedit(&mut self.state.name));
|
ui.add(singleline_textedit(self.state.str_mut("name")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Profile picture"));
|
ui.add(label("Profile picture"));
|
||||||
ui.add(multiline_textedit(&mut self.state.picture));
|
ui.add(multiline_textedit(self.state.str_mut("picture")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Banner"));
|
ui.add(label("Banner"));
|
||||||
ui.add(multiline_textedit(&mut self.state.banner));
|
ui.add(multiline_textedit(self.state.str_mut("banner")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("About"));
|
ui.add(label("About"));
|
||||||
ui.add(multiline_textedit(&mut self.state.about));
|
ui.add(multiline_textedit(self.state.str_mut("about")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Website"));
|
ui.add(label("Website"));
|
||||||
ui.add(singleline_textedit(&mut self.state.website));
|
ui.add(singleline_textedit(self.state.str_mut("website")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Lightning network address (lud16)"));
|
ui.add(label("Lightning network address (lud16)"));
|
||||||
ui.add(multiline_textedit(&mut self.state.lud16));
|
ui.add(multiline_textedit(self.state.str_mut("lud16")));
|
||||||
});
|
});
|
||||||
|
|
||||||
in_frame(ui, |ui| {
|
in_frame(ui, |ui| {
|
||||||
ui.add(label("Nostr address (NIP-05 identity)"));
|
ui.add(label("Nostr address (NIP-05 identity)"));
|
||||||
ui.add(singleline_textedit(&mut self.state.nip05));
|
ui.add(singleline_textedit(self.state.str_mut("nip05")));
|
||||||
let split = &mut self.state.nip05.split('@');
|
|
||||||
let prefix = split.next();
|
let Some(nip05) = self.state.nip05() else {
|
||||||
let suffix = split.next();
|
return;
|
||||||
if let Some(prefix) = prefix {
|
};
|
||||||
if let Some(suffix) = suffix {
|
|
||||||
let use_domain = if let Some(f) = prefix.chars().next() {
|
let mut split = nip05.split('@');
|
||||||
f == '_'
|
|
||||||
} else {
|
let Some(prefix) = split.next() else {
|
||||||
false
|
return;
|
||||||
};
|
};
|
||||||
ui.colored_label(
|
let Some(suffix) = split.next() else {
|
||||||
ui.visuals().noninteractive().fg_stroke.color,
|
return;
|
||||||
RichText::new(if use_domain {
|
};
|
||||||
format!("\"{}\" will be used for identification", suffix)
|
|
||||||
} else {
|
let use_domain = if let Some(f) = prefix.chars().next() {
|
||||||
format!(
|
f == '_'
|
||||||
"\"{}\" at \"{}\" will be used for identification",
|
} else {
|
||||||
prefix, suffix
|
false
|
||||||
)
|
};
|
||||||
}),
|
ui.colored_label(
|
||||||
);
|
ui.visuals().noninteractive().fg_stroke.color,
|
||||||
}
|
RichText::new(if use_domain {
|
||||||
}
|
format!("\"{}\" will be used for identification", suffix)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"\"{}\" at \"{}\" will be used for identification",
|
||||||
|
prefix, suffix
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,46 +168,3 @@ fn button(text: &str, width: f32) -> egui::Button<'static> {
|
|||||||
.corner_radius(CornerRadius::same(8))
|
.corner_radius(CornerRadius::same(8))
|
||||||
.min_size(vec2(width, 40.0))
|
.min_size(vec2(width, 40.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
mod preview {
|
|
||||||
use notedeck::{App, AppAction};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
profile_state::ProfileState,
|
|
||||||
test_data,
|
|
||||||
ui::{Preview, PreviewConfig},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::EditProfileView;
|
|
||||||
|
|
||||||
pub struct EditProfilePreivew {
|
|
||||||
state: ProfileState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for EditProfilePreivew {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
state: ProfileState::from_profile(&test_data::test_profile_record()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl App for EditProfilePreivew {
|
|
||||||
fn update(
|
|
||||||
&mut self,
|
|
||||||
ctx: &mut notedeck::AppContext<'_>,
|
|
||||||
ui: &mut egui::Ui,
|
|
||||||
) -> Option<AppAction> {
|
|
||||||
EditProfileView::new(&mut self.state, ctx.img_cache).ui(ui);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Preview for EditProfileView<'_> {
|
|
||||||
type Prev = EditProfilePreivew;
|
|
||||||
|
|
||||||
fn preview(_cfg: PreviewConfig) -> Self::Prev {
|
|
||||||
EditProfilePreivew::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use enostr::Pubkey;
|
|||||||
|
|
||||||
use crate::deck_state::DeckState;
|
use crate::deck_state::DeckState;
|
||||||
use crate::login_manager::AcquireKeyState;
|
use crate::login_manager::AcquireKeyState;
|
||||||
use crate::profile_state::ProfileState;
|
|
||||||
use crate::ui::search::SearchQueryState;
|
use crate::ui::search::SearchQueryState;
|
||||||
|
use enostr::ProfileState;
|
||||||
|
|
||||||
/// Various state for views
|
/// Various state for views
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|||||||
Reference in New Issue
Block a user