commit 43b98fc6ed434363e32c21c65902e1613382ef3b
parent 95ee27515371ca77d4c8fc1a72398f9aadfe4bba
Author: William Casarin <jb55@jb55.com>
Date: Tue, 2 Sep 2025 15:09:11 -0700
Merge add keys section to settings by kernel #1096
kernelkind (4):
add `AnimationHelper::scaled_rect`
add copy to clipboard img
make eye button public
add keys section to settings
Diffstat:
5 files changed, 187 insertions(+), 5 deletions(-)
diff --git a/assets/icons/copy-to-clipboard.svg b/assets/icons/copy-to-clipboard.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.33337 5.33337V3.46671C5.33337 2.71997 5.33337 2.3466 5.4787 2.06139C5.60653 1.8105 5.8105 1.60653 6.06139 1.4787C6.3466 1.33337 6.71997 1.33337 7.46671 1.33337H12.5334C13.2801 1.33337 13.6535 1.33337 13.9387 1.4787C14.1896 1.60653 14.3936 1.8105 14.5214 2.06139C14.6667 2.3466 14.6667 2.71997 14.6667 3.46671V8.53337C14.6667 9.28011 14.6667 9.65351 14.5214 9.93871C14.3936 10.1896 14.1896 10.3936 13.9387 10.5214C13.6535 10.6667 13.2801 10.6667 12.5334 10.6667H10.6667M3.46671 14.6667H8.53337C9.28011 14.6667 9.65351 14.6667 9.93871 14.5214C10.1896 14.3936 10.3936 14.1896 10.5214 13.9387C10.6667 13.6535 10.6667 13.2801 10.6667 12.5334V7.46671C10.6667 6.71997 10.6667 6.3466 10.5214 6.06139C10.3936 5.8105 10.1896 5.60653 9.93871 5.4787C9.65351 5.33337 9.28011 5.33337 8.53337 5.33337H3.46671C2.71997 5.33337 2.3466 5.33337 2.06139 5.4787C1.8105 5.60653 1.60653 5.8105 1.4787 6.06139C1.33337 6.3466 1.33337 6.71997 1.33337 7.46671V12.5334C1.33337 13.2801 1.33337 13.6535 1.4787 13.9387C1.60653 14.1896 1.8105 14.3936 2.06139 14.5214C2.3466 14.6667 2.71997 14.6667 3.46671 14.6667Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/crates/notedeck_columns/src/ui/account_login_view.rs b/crates/notedeck_columns/src/ui/account_login_view.rs
@@ -157,7 +157,7 @@ fn login_textedit<'a>(
text_edit
}
-fn eye_button(ui: &mut egui::Ui, is_visible: bool) -> egui::Response {
+pub fn eye_button(ui: &mut egui::Ui, is_visible: bool) -> egui::Response {
let is_dark_mode = ui.visuals().dark_mode;
let icon = if is_visible && is_dark_mode {
app_images::eye_dark_image()
diff --git a/crates/notedeck_columns/src/ui/settings.rs b/crates/notedeck_columns/src/ui/settings.rs
@@ -1,6 +1,8 @@
use egui::{
- vec2, Button, Color32, ComboBox, FontId, Frame, Margin, RichText, ScrollArea, ThemePreference,
+ vec2, Button, Color32, ComboBox, CornerRadius, FontId, Frame, Layout, Margin, RichText,
+ ScrollArea, TextEdit, ThemePreference,
};
+use egui_extras::{Size, StripBuilder};
use enostr::NoteId;
use nostrdb::Transaction;
use notedeck::{
@@ -9,9 +11,12 @@ use notedeck::{
Images, JobsCache, LanguageIdentifier, Localization, NoteContext, NotedeckTextStyle, Settings,
SettingsHandler, DEFAULT_NOTE_BODY_FONT_SIZE,
};
-use notedeck_ui::{NoteOptions, NoteView};
+use notedeck_ui::{
+ app_images::{copy_to_clipboard_dark_image, copy_to_clipboard_image},
+ AnimationHelper, NoteOptions, NoteView,
+};
-use crate::{nav::RouterAction, Damus, Route};
+use crate::{nav::RouterAction, ui::account_login_view::eye_button, Damus, Route};
const PREVIEW_NOTE_ID: &str = "note1edjc8ggj07hwv77g2405uh6j2jkk5aud22gktxrvc2wnre4vdwgqzlv2gw";
@@ -470,6 +475,149 @@ impl<'a> SettingsView<'a> {
action
}
+ fn keys_section(&mut self, ui: &mut egui::Ui) {
+ let title = tr!(
+ self.note_context.i18n,
+ "Keys",
+ "label for keys setting section"
+ );
+
+ settings_group(ui, title, |ui| {
+ ui.horizontal_wrapped(|ui| {
+ ui.label(
+ richtext_small(tr!(
+ self.note_context.i18n,
+ "PUBLIC ACCOUNT ID",
+ "label describing public key"
+ ))
+ .color(ui.visuals().gray_out(ui.visuals().text_color())),
+ );
+ });
+
+ let copy_img = if ui.visuals().dark_mode {
+ copy_to_clipboard_image()
+ } else {
+ copy_to_clipboard_dark_image()
+ };
+ let copy_max_size = vec2(16.0, 16.0);
+
+ if let Some(npub) = self.note_context.accounts.selected_account_pubkey().npub() {
+ item_frame(ui).show(ui, |ui| {
+ StripBuilder::new(ui)
+ .size(Size::exact(24.0))
+ .cell_layout(Layout::left_to_right(egui::Align::Center))
+ .vertical(|mut strip| {
+ strip.strip(|builder| {
+ builder
+ .size(Size::remainder())
+ .size(Size::exact(16.0))
+ .cell_layout(Layout::left_to_right(egui::Align::Center))
+ .horizontal(|mut strip| {
+ strip.cell(|ui| {
+ ui.horizontal_wrapped(|ui| {
+ ui.label(richtext_small(&npub));
+ });
+ });
+
+ strip.cell(|ui| {
+ let helper = AnimationHelper::new(
+ ui,
+ "copy-to-clipboard-npub",
+ copy_max_size,
+ );
+
+ copy_img.paint_at(ui, helper.scaled_rect());
+
+ if helper.take_animation_response().clicked() {
+ ui.ctx().copy_text(npub);
+ }
+ });
+ });
+ });
+ });
+ });
+ }
+
+ let Some(filled) = self.note_context.accounts.selected_filled() else {
+ return;
+ };
+ let Some(mut nsec) = bech32::encode::<bech32::Bech32>(
+ bech32::Hrp::parse_unchecked("nsec"),
+ &filled.secret_key.secret_bytes(),
+ )
+ .ok() else {
+ return;
+ };
+
+ ui.horizontal_wrapped(|ui| {
+ ui.label(
+ richtext_small(tr!(
+ self.note_context.i18n,
+ "SECRET ACCOUNT LOGIN KEY",
+ "label describing secret key"
+ ))
+ .color(ui.visuals().gray_out(ui.visuals().text_color())),
+ );
+ });
+
+ let is_password_id = ui.id().with("is-password");
+ let is_password = ui
+ .ctx()
+ .data_mut(|d| d.get_temp(is_password_id))
+ .unwrap_or(true);
+
+ item_frame(ui).show(ui, |ui| {
+ StripBuilder::new(ui)
+ .size(Size::exact(24.0))
+ .cell_layout(Layout::left_to_right(egui::Align::Center))
+ .vertical(|mut strip| {
+ strip.strip(|builder| {
+ builder
+ .size(Size::remainder())
+ .size(Size::exact(48.0))
+ .cell_layout(Layout::left_to_right(egui::Align::Center))
+ .horizontal(|mut strip| {
+ strip.cell(|ui| {
+ if is_password {
+ ui.add(
+ TextEdit::singleline(&mut nsec)
+ .password(is_password)
+ .interactive(false)
+ .frame(false),
+ );
+ } else {
+ ui.horizontal_wrapped(|ui| {
+ ui.label(richtext_small(&nsec));
+ });
+ }
+ });
+
+ strip.cell(|ui| {
+ let helper = AnimationHelper::new(
+ ui,
+ "copy-to-clipboard-nsec",
+ copy_max_size,
+ );
+
+ copy_img.paint_at(ui, helper.scaled_rect());
+
+ if helper.take_animation_response().clicked() {
+ ui.ctx().copy_text(nsec);
+ }
+
+ if eye_button(ui, is_password).clicked() {
+ ui.ctx().data_mut(|d| {
+ d.insert_temp(is_password_id, !is_password)
+ });
+ }
+ });
+ });
+ });
+ });
+ });
+ });
+ }
+
fn manage_relays_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> {
let mut action = None;
@@ -509,6 +657,10 @@ impl<'a> SettingsView<'a> {
ui.add_space(5.0);
+ self.keys_section(ui);
+
+ ui.add_space(5.0);
+
if let Some(new_action) = self.other_options_section(ui) {
action = Some(new_action);
}
@@ -542,3 +694,10 @@ pub fn format_size(size_bytes: u64) -> String {
format!("{:.2} GB", size / GB)
}
}
+
+fn item_frame(ui: &egui::Ui) -> egui::Frame {
+ Frame::new()
+ .inner_margin(Margin::same(8))
+ .corner_radius(CornerRadius::same(8))
+ .fill(ui.visuals().panel_fill)
+}
diff --git a/crates/notedeck_ui/src/anim.rs b/crates/notedeck_ui/src/anim.rs
@@ -1,4 +1,4 @@
-use egui::{Pos2, Rect, Response, Sense};
+use egui::{vec2, Pos2, Rect, Response, Sense};
pub fn hover_expand(
ui: &mut egui::Ui,
@@ -116,6 +116,16 @@ impl AnimationHelper {
self.rect
}
+ pub fn scaled_rect(&self) -> egui::Rect {
+ let min_height = self.rect.height() * (1.0 / self.expansion_multiple);
+ let min_width = self.rect.width() * (1.0 / self.expansion_multiple);
+
+ egui::Rect::from_center_size(
+ self.center,
+ vec2(self.scale_1d_pos(min_width), self.scale_1d_pos(min_height)),
+ )
+ }
+
pub fn center(&self) -> Pos2 {
self.rect.center()
}
diff --git a/crates/notedeck_ui/src/app_images.rs b/crates/notedeck_ui/src/app_images.rs
@@ -244,3 +244,13 @@ pub fn zap_light_image() -> Image<'static> {
pub fn like_image() -> Image<'static> {
Image::new(include_image!("../../../assets/icons/like_icon_4x.png"))
}
+
+pub fn copy_to_clipboard_image() -> Image<'static> {
+ Image::new(include_image!(
+ "../../../assets/icons/copy-to-clipboard.svg"
+ ))
+}
+
+pub fn copy_to_clipboard_dark_image() -> Image<'static> {
+ copy_to_clipboard_image().tint(Color32::BLACK)
+}