i18n: make localization context non-global
- Simplify Localization{Context,Manager} to just Localization
- Fixed a bunch of lifetime issueo
- Removed all Arcs and Locks
- Removed globals
* widgets now need access to &mut Localization for i18n
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
use crate::login_manager::AcquireKeyState;
|
||||
use crate::ui::{Preview, PreviewConfig};
|
||||
use egui::{
|
||||
Align, Button, Color32, Frame, InnerResponse, Layout, Margin, RichText, TextBuffer, TextEdit,
|
||||
Vec2,
|
||||
Align, Button, Color32, Frame, InnerResponse, Layout, Margin, RichText, TextEdit, Vec2,
|
||||
};
|
||||
use egui_winit::clipboard::Clipboard;
|
||||
use enostr::Keypair;
|
||||
use notedeck::{fonts::get_font_size, tr, AppAction, NotedeckTextStyle};
|
||||
use notedeck::{fonts::get_font_size, tr, AppAction, Localization, NotedeckTextStyle};
|
||||
use notedeck_ui::{
|
||||
app_images,
|
||||
context_menu::{input_context, PasteBehavior},
|
||||
@@ -15,6 +14,7 @@ use notedeck_ui::{
|
||||
pub struct AccountLoginView<'a> {
|
||||
manager: &'a mut AcquireKeyState,
|
||||
clipboard: &'a mut Clipboard,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
pub enum AccountLoginResponse {
|
||||
@@ -23,8 +23,16 @@ pub enum AccountLoginResponse {
|
||||
}
|
||||
|
||||
impl<'a> AccountLoginView<'a> {
|
||||
pub fn new(manager: &'a mut AcquireKeyState, clipboard: &'a mut Clipboard) -> Self {
|
||||
AccountLoginView { manager, clipboard }
|
||||
pub fn new(
|
||||
manager: &'a mut AcquireKeyState,
|
||||
clipboard: &'a mut Clipboard,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
AccountLoginView {
|
||||
manager,
|
||||
clipboard,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> InnerResponse<Option<AccountLoginResponse>> {
|
||||
@@ -35,11 +43,11 @@ impl<'a> AccountLoginView<'a> {
|
||||
ui.vertical(|ui| {
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.add_space(32.0);
|
||||
ui.label(login_title_text());
|
||||
ui.label(login_title_text(self.i18n));
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(login_textedit_info_text());
|
||||
ui.label(login_textedit_info_text(self.i18n));
|
||||
});
|
||||
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
@@ -48,7 +56,7 @@ impl<'a> AccountLoginView<'a> {
|
||||
let button_width = 32.0;
|
||||
let text_edit_width = available_width - button_width;
|
||||
|
||||
let textedit_resp = ui.add_sized([text_edit_width, 40.0], login_textedit(self.manager));
|
||||
let textedit_resp = ui.add_sized([text_edit_width, 40.0], login_textedit(self.manager, self.i18n));
|
||||
input_context(&textedit_resp, self.clipboard, self.manager.input_buffer(), PasteBehavior::Clear);
|
||||
|
||||
if eye_button(ui, self.manager.password_visible()).clicked() {
|
||||
@@ -58,28 +66,28 @@ impl<'a> AccountLoginView<'a> {
|
||||
ui.with_layout(Layout::left_to_right(Align::TOP), |ui| {
|
||||
let help_text_style = NotedeckTextStyle::Small;
|
||||
ui.add(egui::Label::new(
|
||||
RichText::new(tr!("Enter your public key (npub), nostr address (e.g. {address}), or private key (nsec). You must enter your private key to be able to post, reply, etc.", "Instructions for entering Nostr credentials", address="vrod@damus.io"))
|
||||
RichText::new(tr!(self.i18n, "Enter your public key (npub), nostr address (e.g. {address}), or private key (nsec). You must enter your private key to be able to post, reply, etc.", "Instructions for entering Nostr credentials", address="vrod@damus.io"))
|
||||
.text_style(help_text_style.text_style())
|
||||
.size(get_font_size(ui.ctx(), &help_text_style)).color(ui.visuals().weak_text_color()),
|
||||
).wrap())
|
||||
});
|
||||
|
||||
self.manager.loading_and_error_ui(ui);
|
||||
self.manager.loading_and_error_ui(ui, self.i18n);
|
||||
|
||||
if ui.add(login_button()).clicked() {
|
||||
if ui.add(login_button(self.i18n)).clicked() {
|
||||
self.manager.apply_acquire();
|
||||
}
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!("New to Nostr?", "Label asking if the user is new to Nostr. Underneath this label is a button to create an account."))
|
||||
RichText::new(tr!(self.i18n,"New to Nostr?", "Label asking if the user is new to Nostr. Underneath this label is a button to create an account."))
|
||||
.color(ui.style().visuals.noninteractive().fg_stroke.color)
|
||||
.text_style(NotedeckTextStyle::Body.text_style()),
|
||||
);
|
||||
|
||||
if ui
|
||||
.add(Button::new(RichText::new(tr!("Create Account", "Button to create a new account"))).frame(false))
|
||||
.add(Button::new(RichText::new(tr!(self.i18n,"Create Account", "Button to create a new account"))).frame(false))
|
||||
.clicked()
|
||||
{
|
||||
self.manager.should_create_new();
|
||||
@@ -98,21 +106,21 @@ impl<'a> AccountLoginView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn login_title_text() -> RichText {
|
||||
RichText::new(tr!("Login", "Login page title"))
|
||||
fn login_title_text(i18n: &mut Localization) -> RichText {
|
||||
RichText::new(tr!(i18n, "Login", "Login page title"))
|
||||
.text_style(NotedeckTextStyle::Heading2.text_style())
|
||||
.strong()
|
||||
}
|
||||
|
||||
fn login_textedit_info_text() -> RichText {
|
||||
RichText::new(tr!("Enter your key", "Label for key input field. Key can be public key (npub), private key (nsec), or Nostr address (NIP-05)."))
|
||||
fn login_textedit_info_text(i18n: &mut Localization) -> RichText {
|
||||
RichText::new(tr!(i18n, "Enter your key", "Label for key input field. Key can be public key (npub), private key (nsec), or Nostr address (NIP-05)."))
|
||||
.strong()
|
||||
.text_style(NotedeckTextStyle::Body.text_style())
|
||||
}
|
||||
|
||||
fn login_button() -> Button<'static> {
|
||||
fn login_button(i18n: &mut Localization) -> Button<'static> {
|
||||
Button::new(
|
||||
RichText::new(tr!("Login now — let's do this!", "Login button text"))
|
||||
RichText::new(tr!(i18n, "Login now — let's do this!", "Login button text"))
|
||||
.text_style(NotedeckTextStyle::Body.text_style())
|
||||
.strong(),
|
||||
)
|
||||
@@ -120,11 +128,15 @@ fn login_button() -> Button<'static> {
|
||||
.min_size(Vec2::new(0.0, 40.0))
|
||||
}
|
||||
|
||||
fn login_textedit(manager: &mut AcquireKeyState) -> TextEdit {
|
||||
let create_textedit: fn(&mut dyn TextBuffer) -> TextEdit = |text| {
|
||||
fn login_textedit<'a>(
|
||||
manager: &'a mut AcquireKeyState,
|
||||
i18n: &'a mut Localization,
|
||||
) -> TextEdit<'a> {
|
||||
let create_textedit = |text| {
|
||||
egui::TextEdit::singleline(text)
|
||||
.hint_text(
|
||||
RichText::new(tr!(
|
||||
i18n,
|
||||
"Your key here...",
|
||||
"Placeholder text for key input field"
|
||||
))
|
||||
@@ -167,7 +179,7 @@ mod preview {
|
||||
|
||||
impl App for AccountLoginPreview {
|
||||
fn update(&mut self, ctx: &mut AppContext<'_>, ui: &mut egui::Ui) -> Option<AppAction> {
|
||||
AccountLoginView::new(&mut self.manager, ctx.clipboard).ui(ui);
|
||||
AccountLoginView::new(&mut self.manager, ctx.clipboard, ctx.i18n).ui(ui);
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@@ -3,16 +3,17 @@ use egui::{
|
||||
};
|
||||
use enostr::Pubkey;
|
||||
use nostrdb::{Ndb, Transaction};
|
||||
use notedeck::{tr, Accounts, Images};
|
||||
use notedeck::{tr, Accounts, Images, Localization};
|
||||
use notedeck_ui::colors::PINK;
|
||||
use notedeck_ui::profile::preview::SimpleProfilePreview;
|
||||
|
||||
use notedeck_ui::app_images;
|
||||
use notedeck_ui::profile::preview::SimpleProfilePreview;
|
||||
|
||||
pub struct AccountsView<'a> {
|
||||
ndb: &'a Ndb,
|
||||
accounts: &'a Accounts,
|
||||
img_cache: &'a mut Images,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -29,24 +30,30 @@ enum ProfilePreviewAction {
|
||||
}
|
||||
|
||||
impl<'a> AccountsView<'a> {
|
||||
pub fn new(ndb: &'a Ndb, accounts: &'a Accounts, img_cache: &'a mut Images) -> Self {
|
||||
pub fn new(
|
||||
ndb: &'a Ndb,
|
||||
accounts: &'a Accounts,
|
||||
img_cache: &'a mut Images,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
AccountsView {
|
||||
ndb,
|
||||
accounts,
|
||||
img_cache,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui) -> InnerResponse<Option<AccountsViewResponse>> {
|
||||
Frame::new().outer_margin(12.0).show(ui, |ui| {
|
||||
if let Some(resp) = Self::top_section_buttons_widget(ui).inner {
|
||||
if let Some(resp) = Self::top_section_buttons_widget(ui, self.i18n).inner {
|
||||
return Some(resp);
|
||||
}
|
||||
|
||||
ui.add_space(8.0);
|
||||
scroll_area()
|
||||
.show(ui, |ui| {
|
||||
Self::show_accounts(ui, self.accounts, self.ndb, self.img_cache)
|
||||
Self::show_accounts(ui, self.accounts, self.ndb, self.img_cache, self.i18n)
|
||||
})
|
||||
.inner
|
||||
})
|
||||
@@ -57,6 +64,7 @@ impl<'a> AccountsView<'a> {
|
||||
accounts: &Accounts,
|
||||
ndb: &Ndb,
|
||||
img_cache: &mut Images,
|
||||
i18n: &mut Localization,
|
||||
) -> Option<AccountsViewResponse> {
|
||||
let mut return_op: Option<AccountsViewResponse> = None;
|
||||
ui.allocate_ui_with_layout(
|
||||
@@ -79,8 +87,12 @@ impl<'a> AccountsView<'a> {
|
||||
let max_size = egui::vec2(ui.available_width(), 77.0);
|
||||
let resp = ui.allocate_response(max_size, egui::Sense::click());
|
||||
ui.allocate_new_ui(UiBuilder::new().max_rect(resp.rect), |ui| {
|
||||
let preview =
|
||||
SimpleProfilePreview::new(profile.as_ref(), img_cache, has_nsec);
|
||||
let preview = SimpleProfilePreview::new(
|
||||
profile.as_ref(),
|
||||
img_cache,
|
||||
i18n,
|
||||
has_nsec,
|
||||
);
|
||||
show_profile_card(ui, preview, max_size, is_selected, resp)
|
||||
})
|
||||
.inner
|
||||
@@ -104,12 +116,13 @@ impl<'a> AccountsView<'a> {
|
||||
|
||||
fn top_section_buttons_widget(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
) -> InnerResponse<Option<AccountsViewResponse>> {
|
||||
ui.allocate_ui_with_layout(
|
||||
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
||||
Layout::left_to_right(egui::Align::Center),
|
||||
|ui| {
|
||||
if ui.add(add_account_button()).clicked() {
|
||||
if ui.add(add_account_button(i18n)).clicked() {
|
||||
Some(AccountsViewResponse::RouteToLogin)
|
||||
} else {
|
||||
None
|
||||
@@ -141,16 +154,14 @@ fn show_profile_card(
|
||||
.inner_margin(8.0)
|
||||
.show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
let btn = sign_out_button(preview.i18n);
|
||||
ui.add(preview);
|
||||
|
||||
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
|
||||
if card_resp.clicked() {
|
||||
op = Some(ProfilePreviewAction::SwitchTo);
|
||||
}
|
||||
if ui
|
||||
.add_sized(egui::Vec2::new(84.0, 32.0), sign_out_button())
|
||||
.clicked()
|
||||
{
|
||||
if ui.add_sized(egui::Vec2::new(84.0, 32.0), btn).clicked() {
|
||||
op = Some(ProfilePreviewAction::RemoveAccount)
|
||||
}
|
||||
});
|
||||
@@ -168,19 +179,24 @@ fn scroll_area() -> ScrollArea {
|
||||
.auto_shrink([false; 2])
|
||||
}
|
||||
|
||||
fn add_account_button() -> Button<'static> {
|
||||
fn add_account_button(i18n: &mut Localization) -> Button<'static> {
|
||||
Button::image_and_text(
|
||||
app_images::add_account_image().fit_to_exact_size(Vec2::new(48.0, 48.0)),
|
||||
RichText::new(tr!("Add account", "Button label to add a new account"))
|
||||
.size(16.0)
|
||||
// TODO: this color should not be hard coded. Find some way to add it to the visuals
|
||||
.color(PINK),
|
||||
RichText::new(tr!(
|
||||
i18n,
|
||||
"Add account",
|
||||
"Button label to add a new account"
|
||||
))
|
||||
.size(16.0)
|
||||
// TODO: this color should not be hard coded. Find some way to add it to the visuals
|
||||
.color(PINK),
|
||||
)
|
||||
.frame(false)
|
||||
}
|
||||
|
||||
fn sign_out_button() -> egui::Button<'static> {
|
||||
fn sign_out_button(i18n: &mut Localization) -> egui::Button<'static> {
|
||||
egui::Button::new(RichText::new(tr!(
|
||||
i18n,
|
||||
"Sign out",
|
||||
"Button label to sign out of account"
|
||||
)))
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::{
|
||||
Damus,
|
||||
};
|
||||
|
||||
use notedeck::{tr, AppContext, Images, NotedeckTextStyle, UserAccount};
|
||||
use notedeck::{tr, AppContext, Images, Localization, NotedeckTextStyle, UserAccount};
|
||||
use notedeck_ui::{anim::ICON_EXPANSION_MULTIPLE, app_images};
|
||||
use tokenator::{ParseError, TokenParser, TokenSerializable, TokenWriter};
|
||||
|
||||
@@ -167,6 +167,7 @@ pub struct AddColumnView<'a> {
|
||||
ndb: &'a Ndb,
|
||||
img_cache: &'a mut Images,
|
||||
cur_account: &'a UserAccount,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl<'a> AddColumnView<'a> {
|
||||
@@ -175,12 +176,14 @@ impl<'a> AddColumnView<'a> {
|
||||
ndb: &'a Ndb,
|
||||
img_cache: &'a mut Images,
|
||||
cur_account: &'a UserAccount,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
Self {
|
||||
key_state_map,
|
||||
ndb,
|
||||
img_cache,
|
||||
cur_account,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,8 +232,9 @@ impl<'a> AddColumnView<'a> {
|
||||
deck_author: Pubkey,
|
||||
) -> Option<AddColumnResponse> {
|
||||
let algo_option = ColumnOptionData {
|
||||
title: tr!("Contact List", "Title for contact list column"),
|
||||
title: tr!(self.i18n, "Contact List", "Title for contact list column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Source the last note for each user in your contact list",
|
||||
"Description for contact list column"
|
||||
),
|
||||
@@ -248,8 +252,13 @@ impl<'a> AddColumnView<'a> {
|
||||
|
||||
fn algo_ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
|
||||
let algo_option = ColumnOptionData {
|
||||
title: tr!("Last Note per User", "Title for last note per user column"),
|
||||
title: tr!(
|
||||
self.i18n,
|
||||
"Last Note per User",
|
||||
"Title for last note per user column"
|
||||
),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Show the last note for each user from a list",
|
||||
"Description for last note per user column"
|
||||
),
|
||||
@@ -298,6 +307,7 @@ impl<'a> AddColumnView<'a> {
|
||||
egui::TextEdit::singleline(text)
|
||||
.hint_text(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Enter the user's key (npub, hex, nip05) here...",
|
||||
"Hint text to prompt entering the user's public key."
|
||||
))
|
||||
@@ -312,9 +322,11 @@ impl<'a> AddColumnView<'a> {
|
||||
ui.add(text_edit);
|
||||
|
||||
key_state.handle_input_change_after_acquire();
|
||||
key_state.loading_and_error_ui(ui);
|
||||
key_state.loading_and_error_ui(ui, self.i18n);
|
||||
|
||||
if key_state.get_login_keypair().is_none() && ui.add(find_user_button()).clicked() {
|
||||
if key_state.get_login_keypair().is_none()
|
||||
&& ui.add(find_user_button(self.i18n)).clicked()
|
||||
{
|
||||
key_state.apply_acquire();
|
||||
}
|
||||
|
||||
@@ -337,7 +349,7 @@ impl<'a> AddColumnView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
ui.add(add_column_button())
|
||||
ui.add(add_column_button(self.i18n))
|
||||
.clicked()
|
||||
.then(|| to_option(keypair.pubkey).take_as_response(self.cur_account))
|
||||
} else {
|
||||
@@ -452,11 +464,12 @@ impl<'a> AddColumnView<'a> {
|
||||
helper.take_animation_response()
|
||||
}
|
||||
|
||||
fn get_base_options(&self, ui: &mut Ui) -> Vec<ColumnOptionData> {
|
||||
fn get_base_options(&mut self, ui: &mut Ui) -> Vec<ColumnOptionData> {
|
||||
let mut vec = Vec::new();
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Home", "Title for Home column"),
|
||||
title: tr!(self.i18n, "Home", "Title for Home column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"See notes from your contacts",
|
||||
"Description for Home column"
|
||||
),
|
||||
@@ -468,8 +481,9 @@ impl<'a> AddColumnView<'a> {
|
||||
}),
|
||||
});
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Notifications", "Title for notifications column"),
|
||||
title: tr!(self.i18n, "Notifications", "Title for notifications column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Stay up to date with notifications and mentions",
|
||||
"Description for notifications column"
|
||||
),
|
||||
@@ -477,8 +491,9 @@ impl<'a> AddColumnView<'a> {
|
||||
option: AddColumnOption::UndecidedNotification,
|
||||
});
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Universe", "Title for universe column"),
|
||||
title: tr!(self.i18n, "Universe", "Title for universe column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"See the whole nostr universe",
|
||||
"Description for universe column"
|
||||
),
|
||||
@@ -486,8 +501,9 @@ impl<'a> AddColumnView<'a> {
|
||||
option: AddColumnOption::Universe,
|
||||
});
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Hashtags", "Title for hashtags column"),
|
||||
title: tr!(self.i18n, "Hashtags", "Title for hashtags column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Stay up to date with a certain hashtag",
|
||||
"Description for hashtags column"
|
||||
),
|
||||
@@ -495,8 +511,9 @@ impl<'a> AddColumnView<'a> {
|
||||
option: AddColumnOption::UndecidedHashtag,
|
||||
});
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Individual", "Title for individual user column"),
|
||||
title: tr!(self.i18n, "Individual", "Title for individual user column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Stay up to date with someone's notes & replies",
|
||||
"Description for individual user column"
|
||||
),
|
||||
@@ -504,8 +521,9 @@ impl<'a> AddColumnView<'a> {
|
||||
option: AddColumnOption::UndecidedIndividual,
|
||||
});
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Algo", "Title for algorithmic feeds column"),
|
||||
title: tr!(self.i18n, "Algo", "Title for algorithmic feeds column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Algorithmic feeds to aid in note discovery",
|
||||
"Description for algorithmic feeds column"
|
||||
),
|
||||
@@ -516,7 +534,7 @@ impl<'a> AddColumnView<'a> {
|
||||
vec
|
||||
}
|
||||
|
||||
fn get_notifications_options(&self, ui: &mut Ui) -> Vec<ColumnOptionData> {
|
||||
fn get_notifications_options(&mut self, ui: &mut Ui) -> Vec<ColumnOptionData> {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
let source = if self.cur_account.key.secret_key.is_some() {
|
||||
@@ -526,8 +544,13 @@ impl<'a> AddColumnView<'a> {
|
||||
};
|
||||
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Your Notifications", "Title for your notifications column"),
|
||||
title: tr!(
|
||||
self.i18n,
|
||||
"Your Notifications",
|
||||
"Title for your notifications column"
|
||||
),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Stay up to date with your notifications and mentions",
|
||||
"Description for your notifications column"
|
||||
),
|
||||
@@ -537,10 +560,12 @@ impl<'a> AddColumnView<'a> {
|
||||
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!(
|
||||
self.i18n,
|
||||
"Someone else's Notifications",
|
||||
"Title for someone else's notifications column"
|
||||
),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Stay up to date with someone else's notifications and mentions",
|
||||
"Description for someone else's notifications column"
|
||||
),
|
||||
@@ -551,7 +576,7 @@ impl<'a> AddColumnView<'a> {
|
||||
vec
|
||||
}
|
||||
|
||||
fn get_individual_options(&self) -> Vec<ColumnOptionData> {
|
||||
fn get_individual_options(&mut self) -> Vec<ColumnOptionData> {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
let source = if self.cur_account.key.secret_key.is_some() {
|
||||
@@ -561,8 +586,9 @@ impl<'a> AddColumnView<'a> {
|
||||
};
|
||||
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!("Your Notes", "Title for your notes column"),
|
||||
title: tr!(self.i18n, "Your Notes", "Title for your notes column"),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Keep track of your notes & replies",
|
||||
"Description for your notes column"
|
||||
),
|
||||
@@ -572,10 +598,12 @@ impl<'a> AddColumnView<'a> {
|
||||
|
||||
vec.push(ColumnOptionData {
|
||||
title: tr!(
|
||||
self.i18n,
|
||||
"Someone else's Notes",
|
||||
"Title for someone else's notes column"
|
||||
),
|
||||
description: tr!(
|
||||
self.i18n,
|
||||
"Stay up to date with someone else's notes & replies",
|
||||
"Description for someone else's notes column"
|
||||
),
|
||||
@@ -587,14 +615,14 @@ impl<'a> AddColumnView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_user_button() -> impl Widget {
|
||||
let label = tr!("Find User", "Label for find user button");
|
||||
fn find_user_button(i18n: &mut Localization) -> impl Widget {
|
||||
let label = tr!(i18n, "Find User", "Label for find user button");
|
||||
let color = notedeck_ui::colors::PINK;
|
||||
move |ui: &mut egui::Ui| styled_button(label.as_str(), color).ui(ui)
|
||||
}
|
||||
|
||||
fn add_column_button() -> impl Widget {
|
||||
let label = tr!("Add", "Label for add column button");
|
||||
fn add_column_button(i18n: &mut Localization) -> impl Widget {
|
||||
let label = tr!(i18n, "Add", "Label for add column button");
|
||||
let color = notedeck_ui::colors::PINK;
|
||||
move |ui: &mut egui::Ui| styled_button(label.as_str(), color).ui(ui)
|
||||
}
|
||||
@@ -639,6 +667,7 @@ pub fn render_add_column_routes(
|
||||
ctx.ndb,
|
||||
ctx.img_cache,
|
||||
ctx.accounts.get_selected_account(),
|
||||
ctx.i18n,
|
||||
);
|
||||
let resp = match route {
|
||||
AddColumnRoute::Base => add_column_view.ui(ui),
|
||||
@@ -649,7 +678,7 @@ pub fn render_add_column_routes(
|
||||
},
|
||||
AddColumnRoute::UndecidedNotification => add_column_view.notifications_ui(ui),
|
||||
AddColumnRoute::ExternalNotification => add_column_view.external_notification_ui(ui),
|
||||
AddColumnRoute::Hashtag => hashtag_ui(ui, &mut app.view_state.id_string_map),
|
||||
AddColumnRoute::Hashtag => hashtag_ui(ui, ctx.i18n, &mut app.view_state.id_string_map),
|
||||
AddColumnRoute::UndecidedIndividual => add_column_view.individual_ui(ui),
|
||||
AddColumnRoute::ExternalIndividual => add_column_view.external_individual_ui(ui),
|
||||
};
|
||||
@@ -677,7 +706,7 @@ pub fn render_add_column_routes(
|
||||
ctx.accounts,
|
||||
);
|
||||
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to_replaced(Route::timeline(timeline.kind.clone()));
|
||||
@@ -689,7 +718,7 @@ pub fn render_add_column_routes(
|
||||
// If we are undecided, we simply route to the LastPerPubkey
|
||||
// algo route selection
|
||||
AlgoOption::LastPerPubkey(Decision::Undecided) => {
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(Route::AddColumn(AddColumnRoute::Algo(
|
||||
@@ -717,7 +746,7 @@ pub fn render_add_column_routes(
|
||||
ctx.accounts,
|
||||
);
|
||||
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to_replaced(Route::timeline(timeline.kind.clone()));
|
||||
@@ -735,13 +764,13 @@ pub fn render_add_column_routes(
|
||||
},
|
||||
|
||||
AddColumnResponse::UndecidedNotification => {
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(Route::AddColumn(AddColumnRoute::UndecidedNotification));
|
||||
}
|
||||
AddColumnResponse::ExternalNotification => {
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(crate::route::Route::AddColumn(
|
||||
@@ -749,13 +778,13 @@ pub fn render_add_column_routes(
|
||||
));
|
||||
}
|
||||
AddColumnResponse::Hashtag => {
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(crate::route::Route::AddColumn(AddColumnRoute::Hashtag));
|
||||
}
|
||||
AddColumnResponse::UndecidedIndividual => {
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(crate::route::Route::AddColumn(
|
||||
@@ -763,7 +792,7 @@ pub fn render_add_column_routes(
|
||||
));
|
||||
}
|
||||
AddColumnResponse::ExternalIndividual => {
|
||||
app.columns_mut(ctx.accounts)
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.route_to(crate::route::Route::AddColumn(
|
||||
@@ -776,6 +805,7 @@ pub fn render_add_column_routes(
|
||||
|
||||
pub fn hashtag_ui(
|
||||
ui: &mut Ui,
|
||||
i18n: &mut Localization,
|
||||
id_string_map: &mut HashMap<Id, String>,
|
||||
) -> Option<AddColumnResponse> {
|
||||
padding(16.0, ui, |ui| {
|
||||
@@ -785,6 +815,7 @@ pub fn hashtag_ui(
|
||||
let text_edit = egui::TextEdit::singleline(text_buffer)
|
||||
.hint_text(
|
||||
RichText::new(tr!(
|
||||
i18n,
|
||||
"Enter the desired hashtags here (for multiple space-separated)",
|
||||
"Placeholder for hashtag input field"
|
||||
))
|
||||
@@ -801,7 +832,7 @@ pub fn hashtag_ui(
|
||||
let mut handle_user_input = false;
|
||||
if ui.input(|i| i.key_released(egui::Key::Enter))
|
||||
|| ui
|
||||
.add_sized(egui::vec2(50.0, 40.0), add_column_button())
|
||||
.add_sized(egui::vec2(50.0, 40.0), add_column_button(i18n))
|
||||
.clicked()
|
||||
{
|
||||
handle_user_input = true;
|
||||
|
||||
@@ -13,7 +13,7 @@ use egui::{Margin, Response, RichText, Sense, Stroke, UiBuilder};
|
||||
use enostr::Pubkey;
|
||||
use nostrdb::{Ndb, Transaction};
|
||||
use notedeck::tr;
|
||||
use notedeck::{Images, NotedeckTextStyle};
|
||||
use notedeck::{Images, Localization, NotedeckTextStyle};
|
||||
use notedeck_ui::app_images;
|
||||
use notedeck_ui::{
|
||||
anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE},
|
||||
@@ -27,6 +27,7 @@ pub struct NavTitle<'a> {
|
||||
routes: &'a [Route],
|
||||
col_id: usize,
|
||||
options: u32,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl<'a> NavTitle<'a> {
|
||||
@@ -40,6 +41,7 @@ impl<'a> NavTitle<'a> {
|
||||
columns: &'a Columns,
|
||||
routes: &'a [Route],
|
||||
col_id: usize,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
let options = Self::SHOW_MOVE | Self::SHOW_DELETE;
|
||||
NavTitle {
|
||||
@@ -49,6 +51,7 @@ impl<'a> NavTitle<'a> {
|
||||
routes,
|
||||
col_id,
|
||||
options,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +132,7 @@ impl<'a> NavTitle<'a> {
|
||||
// NOTE(jb55): include graphic in back label as well because why
|
||||
// not it looks cool
|
||||
let pfp_resp = self.title_pfp(ui, prev, 32.0);
|
||||
let column_title = prev.title();
|
||||
let column_title = prev.title(self.i18n);
|
||||
|
||||
let back_resp = match &column_title {
|
||||
ColumnTitle::Simple(title) => ui.add(Self::back_label(title, color)),
|
||||
@@ -182,7 +185,7 @@ impl<'a> NavTitle<'a> {
|
||||
animation_resp
|
||||
}
|
||||
|
||||
fn delete_button_section(&self, ui: &mut egui::Ui) -> bool {
|
||||
fn delete_button_section(&mut self, ui: &mut egui::Ui) -> bool {
|
||||
let id = ui.id().with("title");
|
||||
|
||||
let delete_button_resp = self.delete_column_button(ui, 32.0);
|
||||
@@ -193,14 +196,18 @@ impl<'a> NavTitle<'a> {
|
||||
if ui.data_mut(|d| *d.get_temp_mut_or_default(id)) {
|
||||
let mut confirm_pressed = false;
|
||||
delete_button_resp.show_tooltip_ui(|ui| {
|
||||
let confirm_resp = ui.button(tr!("Confirm", "Button label to confirm an action"));
|
||||
let confirm_resp = ui.button(tr!(
|
||||
self.i18n,
|
||||
"Confirm",
|
||||
"Button label to confirm an action"
|
||||
));
|
||||
if confirm_resp.clicked() {
|
||||
confirm_pressed = true;
|
||||
}
|
||||
|
||||
if confirm_resp.clicked()
|
||||
|| ui
|
||||
.button(tr!("Cancel", "Button label to cancel an action"))
|
||||
.button(tr!(self.i18n, "Cancel", "Button label to cancel an action"))
|
||||
.clicked()
|
||||
{
|
||||
ui.data_mut(|d| d.insert_temp(id, false));
|
||||
@@ -211,8 +218,11 @@ impl<'a> NavTitle<'a> {
|
||||
}
|
||||
confirm_pressed
|
||||
} else {
|
||||
delete_button_resp
|
||||
.on_hover_text(tr!("Delete this column", "Tooltip for deleting a column"));
|
||||
delete_button_resp.on_hover_text(tr!(
|
||||
self.i18n,
|
||||
"Delete this column",
|
||||
"Tooltip for deleting a column"
|
||||
));
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -227,6 +237,7 @@ impl<'a> NavTitle<'a> {
|
||||
// showing the hover text while showing the move tooltip causes some weird visuals
|
||||
if ui.data(|d| d.get_temp::<bool>(cur_id).is_none()) {
|
||||
move_resp = move_resp.on_hover_text(tr!(
|
||||
self.i18n,
|
||||
"Moves this column to another position",
|
||||
"Tooltip for moving a column"
|
||||
));
|
||||
@@ -522,8 +533,8 @@ impl<'a> NavTitle<'a> {
|
||||
.selectable(false)
|
||||
}
|
||||
|
||||
fn title_label(&self, ui: &mut egui::Ui, top: &Route) {
|
||||
let column_title = top.title();
|
||||
fn title_label(&mut self, ui: &mut egui::Ui, top: &Route) {
|
||||
let column_title = top.title(self.i18n);
|
||||
|
||||
match &column_title {
|
||||
ColumnTitle::Simple(title) => ui.add(Self::title_label_value(title)),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{app_style::deck_icon_font_sized, deck_state::DeckState};
|
||||
use egui::{vec2, Button, Color32, Label, RichText, Stroke, Ui, Widget};
|
||||
use notedeck::tr;
|
||||
use notedeck::{tr, Localization};
|
||||
use notedeck::{NamedFontFamily, NotedeckTextStyle};
|
||||
use notedeck_ui::{
|
||||
anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE},
|
||||
@@ -11,6 +11,7 @@ use notedeck_ui::{
|
||||
pub struct ConfigureDeckView<'a> {
|
||||
state: &'a mut DeckState,
|
||||
create_button_text: String,
|
||||
pub i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
pub struct ConfigureDeckResponse {
|
||||
@@ -19,10 +20,11 @@ pub struct ConfigureDeckResponse {
|
||||
}
|
||||
|
||||
impl<'a> ConfigureDeckView<'a> {
|
||||
pub fn new(state: &'a mut DeckState) -> Self {
|
||||
pub fn new(state: &'a mut DeckState, i18n: &'a mut Localization) -> Self {
|
||||
Self {
|
||||
state,
|
||||
create_button_text: tr!("Create Deck", "Button label to create a new deck"),
|
||||
create_button_text: tr!(i18n, "Create Deck", "Button label to create a new deck"),
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,14 +40,19 @@ impl<'a> ConfigureDeckView<'a> {
|
||||
);
|
||||
padding(16.0, ui, |ui| {
|
||||
ui.add(Label::new(
|
||||
RichText::new(tr!("Deck name", "Label for deck name input field"))
|
||||
.font(title_font.clone()),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Deck name",
|
||||
"Label for deck name input field"
|
||||
))
|
||||
.font(title_font.clone()),
|
||||
));
|
||||
ui.add_space(8.0);
|
||||
ui.text_edit_singleline(&mut self.state.deck_name);
|
||||
ui.add_space(8.0);
|
||||
ui.add(Label::new(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"We recommend short names",
|
||||
"Hint for deck name input field"
|
||||
))
|
||||
@@ -58,7 +65,8 @@ impl<'a> ConfigureDeckView<'a> {
|
||||
|
||||
ui.add_space(32.0);
|
||||
ui.add(Label::new(
|
||||
RichText::new(tr!("Icon", "Label for deck icon selection")).font(title_font),
|
||||
RichText::new(tr!(self.i18n, "Icon", "Label for deck icon selection"))
|
||||
.font(title_font),
|
||||
));
|
||||
|
||||
if ui
|
||||
@@ -97,7 +105,12 @@ impl<'a> ConfigureDeckView<'a> {
|
||||
self.state.warn_no_title = false;
|
||||
}
|
||||
|
||||
show_warnings(ui, self.state.warn_no_icon, self.state.warn_no_title);
|
||||
show_warnings(
|
||||
ui,
|
||||
self.i18n,
|
||||
self.state.warn_no_icon,
|
||||
self.state.warn_no_title,
|
||||
);
|
||||
|
||||
let mut resp = None;
|
||||
if ui
|
||||
@@ -125,19 +138,22 @@ impl<'a> ConfigureDeckView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn show_warnings(ui: &mut Ui, warn_no_icon: bool, warn_no_title: bool) {
|
||||
fn show_warnings(ui: &mut Ui, i18n: &mut Localization, warn_no_icon: bool, warn_no_title: bool) {
|
||||
let warning = if warn_no_title && warn_no_icon {
|
||||
tr!(
|
||||
i18n,
|
||||
"Please create a name for the deck and select an icon.",
|
||||
"Error message for missing deck name and icon"
|
||||
)
|
||||
} else if warn_no_title {
|
||||
tr!(
|
||||
i18n,
|
||||
"Please create a name for the deck.",
|
||||
"Error message for missing deck name"
|
||||
)
|
||||
} else if warn_no_icon {
|
||||
tr!(
|
||||
i18n,
|
||||
"Please select an icon.",
|
||||
"Error message for missing deck icon"
|
||||
)
|
||||
@@ -320,12 +336,8 @@ mod preview {
|
||||
}
|
||||
|
||||
impl App for ConfigureDeckPreview {
|
||||
fn update(
|
||||
&mut self,
|
||||
_app_ctx: &mut AppContext<'_>,
|
||||
ui: &mut egui::Ui,
|
||||
) -> Option<AppAction> {
|
||||
ConfigureDeckView::new(&mut self.state).ui(ui);
|
||||
fn update(&mut self, ctx: &mut AppContext<'_>, ui: &mut egui::Ui) -> Option<AppAction> {
|
||||
ConfigureDeckView::new(&mut self.state, ctx.i18n).ui(ui);
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use egui::Widget;
|
||||
use crate::deck_state::DeckState;
|
||||
|
||||
use super::configure_deck::{ConfigureDeckResponse, ConfigureDeckView};
|
||||
use notedeck::tr;
|
||||
use notedeck::{tr, Localization};
|
||||
use notedeck_ui::padding;
|
||||
|
||||
pub struct EditDeckView<'a> {
|
||||
@@ -16,9 +16,9 @@ pub enum EditDeckResponse {
|
||||
}
|
||||
|
||||
impl<'a> EditDeckView<'a> {
|
||||
pub fn new(state: &'a mut DeckState) -> Self {
|
||||
let config_view = ConfigureDeckView::new(state)
|
||||
.with_create_text(tr!("Edit Deck", "Button label to edit a deck"));
|
||||
pub fn new(state: &'a mut DeckState, i18n: &'a mut Localization) -> Self {
|
||||
let txt = tr!(i18n, "Edit Deck", "Button label to edit a deck");
|
||||
let config_view = ConfigureDeckView::new(state, i18n).with_create_text(txt);
|
||||
Self { config_view }
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ impl<'a> EditDeckView<'a> {
|
||||
let mut edit_deck_resp = None;
|
||||
|
||||
padding(egui::Margin::symmetric(16, 4), ui, |ui| {
|
||||
if ui.add(delete_button()).clicked() {
|
||||
if ui.add(delete_button(self.config_view.i18n)).clicked() {
|
||||
edit_deck_resp = Some(EditDeckResponse::Delete);
|
||||
}
|
||||
});
|
||||
@@ -39,12 +39,12 @@ impl<'a> EditDeckView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_button() -> impl Widget {
|
||||
fn delete_button<'a>(i18n: &'a mut Localization) -> impl Widget + 'a {
|
||||
|ui: &mut egui::Ui| {
|
||||
let size = egui::vec2(108.0, 40.0);
|
||||
ui.allocate_ui_with_layout(size, egui::Layout::top_down(egui::Align::Center), |ui| {
|
||||
ui.add(
|
||||
egui::Button::new(tr!("Delete Deck", "Button label to delete a deck"))
|
||||
egui::Button::new(tr!(i18n, "Delete Deck", "Button label to delete a deck"))
|
||||
.fill(ui.visuals().error_fg_color)
|
||||
.min_size(size),
|
||||
)
|
||||
@@ -75,12 +75,8 @@ mod preview {
|
||||
}
|
||||
|
||||
impl App for EditDeckPreview {
|
||||
fn update(
|
||||
&mut self,
|
||||
_app_ctx: &mut AppContext<'_>,
|
||||
ui: &mut egui::Ui,
|
||||
) -> Option<AppAction> {
|
||||
EditDeckView::new(&mut self.state).ui(ui);
|
||||
fn update(&mut self, ctx: &mut AppContext<'_>, ui: &mut egui::Ui) -> Option<AppAction> {
|
||||
EditDeckView::new(&mut self.state, ctx.i18n).ui(ui);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use egui::{
|
||||
emath::GuiRounding, pos2, vec2, Color32, CornerRadius, FontId, Frame, Label, Layout, Slider,
|
||||
Stroke,
|
||||
@@ -7,7 +5,8 @@ use egui::{
|
||||
use enostr::Pubkey;
|
||||
use nostrdb::{Ndb, ProfileRecord, Transaction};
|
||||
use notedeck::{
|
||||
fonts::get_font_size, get_profile_url, name::get_display_name, tr, Images, NotedeckTextStyle,
|
||||
fonts::get_font_size, get_profile_url, name::get_display_name, tr, Images, Localization,
|
||||
NotedeckTextStyle,
|
||||
};
|
||||
use notedeck_ui::{
|
||||
app_images, colors, profile::display_name_widget, widgets::styled_button_toggleable,
|
||||
@@ -20,11 +19,13 @@ pub struct CustomZapView<'a> {
|
||||
txn: &'a Transaction,
|
||||
target_pubkey: &'a Pubkey,
|
||||
default_msats: u64,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl<'a> CustomZapView<'a> {
|
||||
pub fn new(
|
||||
i18n: &'a mut Localization,
|
||||
images: &'a mut Images,
|
||||
ndb: &'a Ndb,
|
||||
txn: &'a Transaction,
|
||||
@@ -37,6 +38,7 @@ impl<'a> CustomZapView<'a> {
|
||||
ndb,
|
||||
txn,
|
||||
default_msats,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +50,7 @@ impl<'a> CustomZapView<'a> {
|
||||
}
|
||||
|
||||
fn ui_internal(&mut self, ui: &mut egui::Ui) -> Option<u64> {
|
||||
show_title(ui);
|
||||
show_title(ui, self.i18n);
|
||||
|
||||
ui.add_space(16.0);
|
||||
|
||||
@@ -82,7 +84,7 @@ impl<'a> CustomZapView<'a> {
|
||||
} else {
|
||||
(self.default_msats / 1000).to_string()
|
||||
};
|
||||
show_amount(ui, id, &mut cur_amount, slider_width);
|
||||
show_amount(ui, self.i18n, id, &mut cur_amount, slider_width);
|
||||
let mut maybe_sats = cur_amount.parse::<u64>().ok();
|
||||
|
||||
let prev_slider_sats = maybe_sats.unwrap_or(default_sats).clamp(1, 100000);
|
||||
@@ -102,7 +104,7 @@ impl<'a> CustomZapView<'a> {
|
||||
maybe_sats = Some(slider_sats);
|
||||
}
|
||||
|
||||
if let Some(selection) = show_selection_buttons(ui, maybe_sats) {
|
||||
if let Some(selection) = show_selection_buttons(ui, maybe_sats, self.i18n) {
|
||||
cur_amount = selection.to_string();
|
||||
maybe_sats = Some(selection);
|
||||
}
|
||||
@@ -110,7 +112,7 @@ impl<'a> CustomZapView<'a> {
|
||||
ui.data_mut(|d| d.insert_temp(id, cur_amount));
|
||||
|
||||
let resp = ui.add(styled_button_toggleable(
|
||||
&tr!("Send", "Button label to send a zap"),
|
||||
&tr!(self.i18n, "Send", "Button label to send a zap"),
|
||||
colors::PINK,
|
||||
is_valid_zap(maybe_sats),
|
||||
));
|
||||
@@ -129,7 +131,7 @@ fn is_valid_zap(amount: Option<u64>) -> bool {
|
||||
amount.is_some_and(|sats| sats > 0)
|
||||
}
|
||||
|
||||
fn show_title(ui: &mut egui::Ui) {
|
||||
fn show_title(ui: &mut egui::Ui, i18n: &mut Localization) {
|
||||
let max_size = 32.0;
|
||||
ui.allocate_ui_with_layout(
|
||||
vec2(ui.available_width(), max_size),
|
||||
@@ -158,7 +160,7 @@ fn show_title(ui: &mut egui::Ui) {
|
||||
ui.add_space(8.0);
|
||||
|
||||
ui.add(egui::Label::new(
|
||||
egui::RichText::new(tr!("Zap", "Heading for zap (tip) action"))
|
||||
egui::RichText::new(tr!(i18n, "Zap", "Heading for zap (tip) action"))
|
||||
.text_style(NotedeckTextStyle::Heading2.text_style()),
|
||||
));
|
||||
},
|
||||
@@ -177,7 +179,13 @@ fn show_profile(ui: &mut egui::Ui, images: &mut Images, profile: Option<&Profile
|
||||
);
|
||||
}
|
||||
|
||||
fn show_amount(ui: &mut egui::Ui, id: egui::Id, user_input: &mut String, width: f32) {
|
||||
fn show_amount(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
id: egui::Id,
|
||||
user_input: &mut String,
|
||||
width: f32,
|
||||
) {
|
||||
let user_input_font = NotedeckTextStyle::Heading.get_bolded_font(ui.ctx());
|
||||
|
||||
let user_input_id = id.with("sats_amount");
|
||||
@@ -192,6 +200,7 @@ fn show_amount(ui: &mut egui::Ui, id: egui::Id, user_input: &mut String, width:
|
||||
|
||||
let sats_galley = painter.layout_no_wrap(
|
||||
tr!(
|
||||
i18n,
|
||||
"SATS",
|
||||
"Label for satoshis (Bitcoin unit) for custom zap amount input field"
|
||||
),
|
||||
@@ -219,7 +228,7 @@ fn show_amount(ui: &mut egui::Ui, id: egui::Id, user_input: &mut String, width:
|
||||
.font(user_input_font);
|
||||
|
||||
let amount_resp = ui.add(Label::new(
|
||||
egui::RichText::new(tr!("Amount", "Label for zap amount input field"))
|
||||
egui::RichText::new(tr!(i18n, "Amount", "Label for zap amount input field"))
|
||||
.text_style(NotedeckTextStyle::Heading3.text_style())
|
||||
.color(ui.visuals().noninteractive().text_color()),
|
||||
));
|
||||
@@ -300,7 +309,11 @@ const SELECTION_BUTTONS: [ZapSelectionButton; 8] = [
|
||||
ZapSelectionButton::Eighth,
|
||||
];
|
||||
|
||||
fn show_selection_buttons(ui: &mut egui::Ui, sats_selection: Option<u64>) -> Option<u64> {
|
||||
fn show_selection_buttons(
|
||||
ui: &mut egui::Ui,
|
||||
sats_selection: Option<u64>,
|
||||
i18n: &mut Localization,
|
||||
) -> Option<u64> {
|
||||
let mut our_selection = None;
|
||||
ui.allocate_ui_with_layout(
|
||||
vec2(224.0, 116.0),
|
||||
@@ -309,7 +322,8 @@ fn show_selection_buttons(ui: &mut egui::Ui, sats_selection: Option<u64>) -> Opt
|
||||
ui.spacing_mut().item_spacing = vec2(8.0, 8.0);
|
||||
|
||||
for button in SELECTION_BUTTONS {
|
||||
our_selection = our_selection.or(show_selection_button(ui, sats_selection, button));
|
||||
our_selection =
|
||||
our_selection.or(show_selection_button(ui, sats_selection, button, i18n));
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -321,6 +335,7 @@ fn show_selection_button(
|
||||
ui: &mut egui::Ui,
|
||||
sats_selection: Option<u64>,
|
||||
button: ZapSelectionButton,
|
||||
i18n: &mut Localization,
|
||||
) -> Option<u64> {
|
||||
let (rect, _) = ui.allocate_exact_size(vec2(50.0, 50.0), egui::Sense::click());
|
||||
let helper = AnimationHelper::new_from_rect(ui, ("zap_selection_button", &button), rect);
|
||||
@@ -353,7 +368,11 @@ fn show_selection_button(
|
||||
NotedeckTextStyle::Body.font_family(),
|
||||
);
|
||||
|
||||
let galley = painter.layout_no_wrap(button.to_string(), fontid, ui.visuals().text_color());
|
||||
let galley = painter.layout_no_wrap(
|
||||
button.to_desc_string(i18n),
|
||||
fontid,
|
||||
ui.visuals().text_color(),
|
||||
);
|
||||
let text_rect = {
|
||||
let mut galley_rect = galley.rect;
|
||||
galley_rect.set_center(rect.center());
|
||||
@@ -394,19 +413,17 @@ impl ZapSelectionButton {
|
||||
ZapSelectionButton::Eighth => 100_000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ZapSelectionButton {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
pub fn to_desc_string(&self, i18n: &mut Localization) -> String {
|
||||
match self {
|
||||
ZapSelectionButton::First => write!(f, "69"),
|
||||
ZapSelectionButton::Second => write!(f, "100"),
|
||||
ZapSelectionButton::Third => write!(f, "420"),
|
||||
ZapSelectionButton::Fourth => write!(f, "{}", tr!("5K", "Zap amount button for 5000 sats. Abbreviated because the button is too small to display the full amount.")),
|
||||
ZapSelectionButton::Fifth => write!(f, "{}", tr!("10K", "Zap amount button for 10000 sats. Abbreviated because the button is too small to display the full amount.")),
|
||||
ZapSelectionButton::Sixth => write!(f, "{}", tr!("20K", "Zap amount button for 20000 sats. Abbreviated because the button is too small to display the full amount.")),
|
||||
ZapSelectionButton::Seventh => write!(f, "{}", tr!("50K", "Zap amount button for 50000 sats. Abbreviated because the button is too small to display the full amount.")),
|
||||
ZapSelectionButton::Eighth => write!(f, "{}", tr!("100K", "Zap amount button for 100000 sats. Abbreviated because the button is too small to display the full amount.")),
|
||||
ZapSelectionButton::First => "69".to_string(),
|
||||
ZapSelectionButton::Second => "100".to_string(),
|
||||
ZapSelectionButton::Third => "420".to_string(),
|
||||
ZapSelectionButton::Fourth => tr!(i18n, "5K", "Zap amount button for 5000 sats. Abbreviated because the button is too small to display the full amount."),
|
||||
ZapSelectionButton::Fifth => tr!(i18n, "10K", "Zap amount button for 10000 sats. Abbreviated because the button is too small to display the full amount."),
|
||||
ZapSelectionButton::Sixth => tr!(i18n, "20K", "Zap amount button for 20000 sats. Abbreviated because the button is too small to display the full amount."),
|
||||
ZapSelectionButton::Seventh => tr!(i18n, "50K", "Zap amount button for 50000 sats. Abbreviated because the button is too small to display the full amount."),
|
||||
ZapSelectionButton::Eighth => tr!(i18n, "100K", "Zap amount button for 100000 sats. Abbreviated because the button is too small to display the full amount."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ use notedeck_ui::{
|
||||
NoteOptions, ProfilePic,
|
||||
};
|
||||
|
||||
use notedeck::{name::get_display_name, supported_mime_hosted_at_url, tr, NoteAction, NoteContext};
|
||||
use notedeck::{
|
||||
name::get_display_name, supported_mime_hosted_at_url, tr, Localization, NoteAction, NoteContext,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
pub struct PostView<'a, 'd> {
|
||||
@@ -182,6 +184,7 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
let textedit = TextEdit::multiline(&mut self.draft.buffer)
|
||||
.hint_text(
|
||||
egui::RichText::new(tr!(
|
||||
self.note_context.i18n,
|
||||
"Write a banger note here...",
|
||||
"Placeholder for note input field"
|
||||
))
|
||||
@@ -411,7 +414,10 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::BOTTOM), |ui| {
|
||||
let post_button_clicked = ui
|
||||
.add_sized([91.0, 32.0], post_button(!self.draft.buffer.is_empty()))
|
||||
.add_sized(
|
||||
[91.0, 32.0],
|
||||
post_button(self.note_context.i18n, !self.draft.buffer.is_empty()),
|
||||
)
|
||||
.clicked();
|
||||
|
||||
let shortcut_pressed = ui.input(|i| {
|
||||
@@ -609,9 +615,9 @@ fn render_post_view_media(
|
||||
}
|
||||
}
|
||||
|
||||
fn post_button(interactive: bool) -> impl egui::Widget {
|
||||
fn post_button<'a>(i18n: &'a mut Localization, interactive: bool) -> impl egui::Widget + 'a {
|
||||
move |ui: &mut egui::Ui| {
|
||||
let button = egui::Button::new(tr!("Post now", "Button label to post a note"));
|
||||
let button = egui::Button::new(tr!(i18n, "Post now", "Button label to post a note"));
|
||||
if interactive {
|
||||
ui.add(button)
|
||||
} else {
|
||||
@@ -804,6 +810,7 @@ mod preview {
|
||||
unknown_ids: app.unknown_ids,
|
||||
current_account_has_wallet: false,
|
||||
clipboard: app.clipboard,
|
||||
i18n: app.i18n,
|
||||
};
|
||||
|
||||
PostView::new(
|
||||
|
||||
@@ -2,17 +2,26 @@ use core::f32;
|
||||
|
||||
use egui::{vec2, Button, CornerRadius, Layout, Margin, RichText, ScrollArea, TextEdit};
|
||||
use enostr::ProfileState;
|
||||
use notedeck::{profile::unwrap_profile_url, tr, Images, NotedeckTextStyle};
|
||||
use notedeck::{profile::unwrap_profile_url, tr, Images, Localization, NotedeckTextStyle};
|
||||
use notedeck_ui::{profile::banner, ProfilePic};
|
||||
|
||||
pub struct EditProfileView<'a> {
|
||||
state: &'a mut ProfileState,
|
||||
img_cache: &'a mut Images,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl<'a> EditProfileView<'a> {
|
||||
pub fn new(state: &'a mut ProfileState, img_cache: &'a mut Images) -> Self {
|
||||
Self { state, img_cache }
|
||||
pub fn new(
|
||||
i18n: &'a mut Localization,
|
||||
state: &'a mut ProfileState,
|
||||
img_cache: &'a mut Images,
|
||||
) -> Self {
|
||||
Self {
|
||||
i18n,
|
||||
state,
|
||||
img_cache,
|
||||
}
|
||||
}
|
||||
|
||||
// return true to save
|
||||
@@ -34,8 +43,12 @@ impl<'a> EditProfileView<'a> {
|
||||
if ui
|
||||
.add(
|
||||
button(
|
||||
tr!("Save changes", "Button label to save profile changes")
|
||||
.as_str(),
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Save changes",
|
||||
"Button label to save profile changes"
|
||||
)
|
||||
.as_str(),
|
||||
119.0,
|
||||
)
|
||||
.fill(notedeck_ui::colors::PINK),
|
||||
@@ -70,42 +83,52 @@ impl<'a> EditProfileView<'a> {
|
||||
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!("Display name", "Profile display name field label").as_str(),
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Display name",
|
||||
"Profile display name field label"
|
||||
)
|
||||
.as_str(),
|
||||
));
|
||||
ui.add(singleline_textedit(self.state.str_mut("display_name")));
|
||||
});
|
||||
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!("Username", "Profile username field label").as_str(),
|
||||
tr!(self.i18n, "Username", "Profile username field label").as_str(),
|
||||
));
|
||||
ui.add(singleline_textedit(self.state.str_mut("name")));
|
||||
});
|
||||
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!("Profile picture", "Profile picture URL field label").as_str(),
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Profile picture",
|
||||
"Profile picture URL field label"
|
||||
)
|
||||
.as_str(),
|
||||
));
|
||||
ui.add(multiline_textedit(self.state.str_mut("picture")));
|
||||
});
|
||||
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!("Banner", "Profile banner URL field label").as_str(),
|
||||
tr!(self.i18n, "Banner", "Profile banner URL field label").as_str(),
|
||||
));
|
||||
ui.add(multiline_textedit(self.state.str_mut("banner")));
|
||||
});
|
||||
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!("About", "Profile about/bio field label").as_str(),
|
||||
tr!(self.i18n, "About", "Profile about/bio field label").as_str(),
|
||||
));
|
||||
ui.add(multiline_textedit(self.state.str_mut("about")));
|
||||
});
|
||||
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!("Website", "Profile website field label").as_str(),
|
||||
tr!(self.i18n, "Website", "Profile website field label").as_str(),
|
||||
));
|
||||
ui.add(singleline_textedit(self.state.str_mut("website")));
|
||||
});
|
||||
@@ -113,6 +136,7 @@ impl<'a> EditProfileView<'a> {
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Lightning network address (lud16)",
|
||||
"Bitcoin Lightning network address field label"
|
||||
)
|
||||
@@ -124,6 +148,7 @@ impl<'a> EditProfileView<'a> {
|
||||
in_frame(ui, |ui| {
|
||||
ui.add(label(
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Nostr address (NIP-05 identity)",
|
||||
"NIP-05 identity field label"
|
||||
)
|
||||
@@ -153,12 +178,14 @@ impl<'a> EditProfileView<'a> {
|
||||
ui.visuals().noninteractive().fg_stroke.color,
|
||||
RichText::new(if use_domain {
|
||||
tr!(
|
||||
self.i18n,
|
||||
"\"{domain}\" will be used for identification",
|
||||
"Domain identification message",
|
||||
domain = suffix
|
||||
)
|
||||
} else {
|
||||
tr!(
|
||||
self.i18n,
|
||||
"\"{username}\" at \"{domain}\" will be used for identification",
|
||||
"Username and domain identification message",
|
||||
username = prefix,
|
||||
|
||||
@@ -4,7 +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::tr;
|
||||
use notedeck::{tr, Localization};
|
||||
use notedeck_ui::profile::follow_button;
|
||||
use tracing::error;
|
||||
|
||||
@@ -91,8 +91,12 @@ impl<'a, 'd> ProfileView<'a, 'd> {
|
||||
)
|
||||
.get_ptr();
|
||||
|
||||
profile_timeline.selected_view =
|
||||
tabs_ui(ui, profile_timeline.selected_view, &profile_timeline.views);
|
||||
profile_timeline.selected_view = tabs_ui(
|
||||
ui,
|
||||
self.note_context.i18n,
|
||||
profile_timeline.selected_view,
|
||||
&profile_timeline.views,
|
||||
);
|
||||
|
||||
let reversed = false;
|
||||
// poll for new notes and insert them into our existing notes
|
||||
@@ -184,7 +188,10 @@ impl<'a, 'd> ProfileView<'a, 'd> {
|
||||
|
||||
match profile_type {
|
||||
ProfileType::MyProfile => {
|
||||
if ui.add(edit_profile_button()).clicked() {
|
||||
if ui
|
||||
.add(edit_profile_button(self.note_context.i18n))
|
||||
.clicked()
|
||||
{
|
||||
action = Some(ProfileViewAction::EditProfile);
|
||||
}
|
||||
}
|
||||
@@ -334,7 +341,7 @@ fn copy_key_widget(pfp_rect: &egui::Rect) -> impl egui::Widget + '_ {
|
||||
}
|
||||
}
|
||||
|
||||
fn edit_profile_button() -> impl egui::Widget + 'static {
|
||||
fn edit_profile_button<'a>(i18n: &'a mut Localization) -> impl egui::Widget + 'a {
|
||||
|ui: &mut egui::Ui| -> egui::Response {
|
||||
let (rect, resp) = ui.allocate_exact_size(vec2(124.0, 32.0), Sense::click());
|
||||
let painter = ui.painter_at(rect);
|
||||
@@ -363,7 +370,7 @@ fn edit_profile_button() -> impl egui::Widget + 'static {
|
||||
|
||||
let edit_icon_size = vec2(16.0, 16.0);
|
||||
let galley = painter.layout(
|
||||
tr!("Edit Profile", "Button label to edit user profile"),
|
||||
tr!(i18n, "Edit Profile", "Button label to edit user profile"),
|
||||
NotedeckTextStyle::Button.get_font_id(ui.ctx()),
|
||||
ui.visuals().text_color(),
|
||||
rect.width(),
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use crate::ui::{Preview, PreviewConfig};
|
||||
use egui::{Align, Button, CornerRadius, Frame, Id, Layout, Margin, Rgba, RichText, Ui, Vec2};
|
||||
use enostr::{RelayPool, RelayStatus};
|
||||
use notedeck::{tr, NotedeckTextStyle, RelayAction};
|
||||
use notedeck::{tr, Localization, NotedeckTextStyle, RelayAction};
|
||||
use notedeck_ui::app_images;
|
||||
use notedeck_ui::{colors::PINK, padding};
|
||||
use tracing::debug;
|
||||
@@ -13,6 +13,7 @@ use super::widgets::styled_button;
|
||||
pub struct RelayView<'a> {
|
||||
pool: &'a RelayPool,
|
||||
id_string_map: &'a mut HashMap<Id, String>,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl RelayView<'_> {
|
||||
@@ -26,7 +27,7 @@ impl RelayView<'_> {
|
||||
ui.horizontal(|ui| {
|
||||
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!("Relays", "Label for relay list section"))
|
||||
RichText::new(tr!(self.i18n, "Relays", "Label for relay list section"))
|
||||
.text_style(NotedeckTextStyle::Heading2.text_style()),
|
||||
);
|
||||
});
|
||||
@@ -53,10 +54,15 @@ impl RelayView<'_> {
|
||||
}
|
||||
|
||||
impl<'a> RelayView<'a> {
|
||||
pub fn new(pool: &'a RelayPool, id_string_map: &'a mut HashMap<Id, String>) -> Self {
|
||||
pub fn new(
|
||||
pool: &'a RelayPool,
|
||||
id_string_map: &'a mut HashMap<Id, String>,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
RelayView {
|
||||
pool,
|
||||
id_string_map,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +71,7 @@ impl<'a> RelayView<'a> {
|
||||
}
|
||||
|
||||
/// Show the current relays and return a relay the user selected to delete
|
||||
fn show_relays(&'a self, ui: &mut Ui) -> Option<String> {
|
||||
fn show_relays(&mut self, ui: &mut Ui) -> Option<String> {
|
||||
let mut relay_to_remove = None;
|
||||
for (index, relay_info) in get_relay_infos(self.pool).iter().enumerate() {
|
||||
ui.add_space(8.0);
|
||||
@@ -107,7 +113,7 @@ impl<'a> RelayView<'a> {
|
||||
relay_to_remove = Some(relay_info.relay_url.to_string());
|
||||
};
|
||||
|
||||
show_connection_status(ui, relay_info.status);
|
||||
show_connection_status(ui, self.i18n, relay_info.status);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -123,7 +129,7 @@ impl<'a> RelayView<'a> {
|
||||
match self.id_string_map.get(&id) {
|
||||
None => {
|
||||
ui.with_layout(Layout::top_down(Align::Min), |ui| {
|
||||
let relay_button = add_relay_button();
|
||||
let relay_button = add_relay_button(self.i18n);
|
||||
if ui.add(relay_button).clicked() {
|
||||
debug!("add relay clicked");
|
||||
self.id_string_map
|
||||
@@ -151,6 +157,7 @@ impl<'a> RelayView<'a> {
|
||||
let text_edit = egui::TextEdit::singleline(text_buffer)
|
||||
.hint_text(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Enter the relay here",
|
||||
"Placeholder for relay input field"
|
||||
))
|
||||
@@ -163,7 +170,10 @@ impl<'a> RelayView<'a> {
|
||||
ui.add(text_edit);
|
||||
ui.add_space(8.0);
|
||||
if ui
|
||||
.add_sized(egui::vec2(50.0, 40.0), add_relay_button2(is_enabled))
|
||||
.add_sized(
|
||||
egui::vec2(50.0, 40.0),
|
||||
add_relay_button2(self.i18n, is_enabled),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
self.id_string_map.remove(&id) // remove and return the value
|
||||
@@ -175,10 +185,10 @@ impl<'a> RelayView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_relay_button() -> Button<'static> {
|
||||
fn add_relay_button(i18n: &mut Localization) -> Button<'static> {
|
||||
Button::image_and_text(
|
||||
app_images::add_relay_image().fit_to_exact_size(Vec2::new(48.0, 48.0)),
|
||||
RichText::new(tr!("Add relay", "Button label to add a relay"))
|
||||
RichText::new(tr!(i18n, "Add relay", "Button label to add a relay"))
|
||||
.size(16.0)
|
||||
// TODO: this color should not be hard coded. Find some way to add it to the visuals
|
||||
.color(PINK),
|
||||
@@ -186,9 +196,9 @@ fn add_relay_button() -> Button<'static> {
|
||||
.frame(false)
|
||||
}
|
||||
|
||||
fn add_relay_button2(is_enabled: bool) -> impl egui::Widget + 'static {
|
||||
fn add_relay_button2<'a>(i18n: &'a mut Localization, is_enabled: bool) -> impl egui::Widget + 'a {
|
||||
move |ui: &mut egui::Ui| -> egui::Response {
|
||||
let add_text = tr!("Add", "Button label to add a relay");
|
||||
let add_text = tr!(i18n, "Add", "Button label to add a relay");
|
||||
let button_widget = styled_button(add_text.as_str(), notedeck_ui::colors::PINK);
|
||||
ui.add_enabled(is_enabled, button_widget)
|
||||
}
|
||||
@@ -219,7 +229,7 @@ fn relay_frame(ui: &mut Ui) -> Frame {
|
||||
.stroke(ui.style().visuals.noninteractive().bg_stroke)
|
||||
}
|
||||
|
||||
fn show_connection_status(ui: &mut Ui, status: RelayStatus) {
|
||||
fn show_connection_status(ui: &mut Ui, i18n: &mut Localization, status: RelayStatus) {
|
||||
let fg_color = match status {
|
||||
RelayStatus::Connected => ui.visuals().selection.bg_fill,
|
||||
RelayStatus::Connecting => ui.visuals().warn_fg_color,
|
||||
@@ -228,9 +238,11 @@ fn show_connection_status(ui: &mut Ui, status: RelayStatus) {
|
||||
let bg_color = egui::lerp(Rgba::from(fg_color)..=Rgba::BLACK, 0.8).into();
|
||||
|
||||
let label_text = match status {
|
||||
RelayStatus::Connected => tr!("Connected", "Status label for connected relay"),
|
||||
RelayStatus::Connecting => tr!("Connecting...", "Status label for connecting relay"),
|
||||
RelayStatus::Disconnected => tr!("Not Connected", "Status label for disconnected relay"),
|
||||
RelayStatus::Connected => tr!(i18n, "Connected", "Status label for connected relay"),
|
||||
RelayStatus::Connecting => tr!(i18n, "Connecting...", "Status label for connecting relay"),
|
||||
RelayStatus::Disconnected => {
|
||||
tr!(i18n, "Not Connected", "Status label for disconnected relay")
|
||||
}
|
||||
};
|
||||
|
||||
let frame = Frame::new()
|
||||
@@ -290,7 +302,7 @@ mod preview {
|
||||
fn update(&mut self, app: &mut AppContext<'_>, ui: &mut egui::Ui) -> Option<AppAction> {
|
||||
self.pool.try_recv();
|
||||
let mut id_string_map = HashMap::new();
|
||||
RelayView::new(app.pool, &mut id_string_map).ui(ui);
|
||||
RelayView::new(app.pool, &mut id_string_map, app.i18n).ui(ui);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use state::TypingType;
|
||||
use crate::{timeline::TimelineTab, ui::timeline::TimelineTabView};
|
||||
use egui_winit::clipboard::Clipboard;
|
||||
use nostrdb::{Filter, Ndb, Transaction};
|
||||
use notedeck::{tr, tr_plural, NoteAction, NoteContext, NoteRef};
|
||||
use notedeck::{tr, tr_plural, Localization, NoteAction, NoteContext, NoteRef};
|
||||
use notedeck_ui::{
|
||||
context_menu::{input_context, PasteBehavior},
|
||||
icons::search_icon,
|
||||
@@ -54,6 +54,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
||||
ui.spacing_mut().item_spacing = egui::vec2(0.0, 12.0);
|
||||
|
||||
let search_resp = search_box(
|
||||
self.note_context.i18n,
|
||||
&mut self.query.string,
|
||||
self.query.focus_state.clone(),
|
||||
ui,
|
||||
@@ -120,6 +121,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
||||
}
|
||||
SearchState::Searched => {
|
||||
ui.label(tr_plural!(
|
||||
self.note_context.i18n,
|
||||
"Got {count} result for '{query}'", // one
|
||||
"Got {count} results for '{query}'", // other
|
||||
"Search results count", // comment
|
||||
@@ -130,6 +132,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
||||
}
|
||||
SearchState::Typing(TypingType::AutoSearch) => {
|
||||
ui.label(tr!(
|
||||
self.note_context.i18n,
|
||||
"Searching for '{query}'",
|
||||
"Search in progress message",
|
||||
query = &self.query.string
|
||||
@@ -247,6 +250,7 @@ impl SearchResponse {
|
||||
}
|
||||
|
||||
fn search_box(
|
||||
i18n: &mut Localization,
|
||||
input: &mut String,
|
||||
focus_state: FocusState,
|
||||
ui: &mut egui::Ui,
|
||||
@@ -290,6 +294,7 @@ fn search_box(
|
||||
TextEdit::singleline(input)
|
||||
.hint_text(
|
||||
RichText::new(tr!(
|
||||
i18n,
|
||||
"Search notes...",
|
||||
"Placeholder for search notes input field"
|
||||
))
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
route::Route,
|
||||
};
|
||||
|
||||
use notedeck::{tr, Accounts, UserAccount};
|
||||
use notedeck::{tr, Accounts, Localization, UserAccount};
|
||||
use notedeck_ui::{
|
||||
anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE},
|
||||
app_images, colors, View,
|
||||
@@ -26,6 +26,7 @@ static ICON_WIDTH: f32 = 40.0;
|
||||
pub struct DesktopSidePanel<'a> {
|
||||
selected_account: &'a UserAccount,
|
||||
decks_cache: &'a DecksCache,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl View for DesktopSidePanel<'_> {
|
||||
@@ -58,10 +59,15 @@ impl SidePanelResponse {
|
||||
}
|
||||
|
||||
impl<'a> DesktopSidePanel<'a> {
|
||||
pub fn new(selected_account: &'a UserAccount, decks_cache: &'a DecksCache) -> Self {
|
||||
pub fn new(
|
||||
selected_account: &'a UserAccount,
|
||||
decks_cache: &'a DecksCache,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
Self {
|
||||
selected_account,
|
||||
decks_cache,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,9 +111,13 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
|
||||
ui.add_space(8.0);
|
||||
ui.add(egui::Label::new(
|
||||
RichText::new(tr!("DECKS", "Label for decks section in side panel"))
|
||||
.size(11.0)
|
||||
.color(ui.visuals().noninteractive().fg_stroke.color),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"DECKS",
|
||||
"Label for decks section in side panel"
|
||||
))
|
||||
.size(11.0)
|
||||
.color(ui.visuals().noninteractive().fg_stroke.color),
|
||||
));
|
||||
ui.add_space(8.0);
|
||||
let add_deck_resp = ui.add(add_deck_button());
|
||||
@@ -175,8 +185,9 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
decks_cache: &mut DecksCache,
|
||||
accounts: &Accounts,
|
||||
action: SidePanelAction,
|
||||
i18n: &mut Localization,
|
||||
) -> Option<SwitchingAction> {
|
||||
let router = get_active_columns_mut(accounts, decks_cache).get_first_router();
|
||||
let router = get_active_columns_mut(i18n, accounts, decks_cache).get_first_router();
|
||||
let mut switching_response = None;
|
||||
match action {
|
||||
/*
|
||||
@@ -218,7 +229,7 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
{
|
||||
router.go_back();
|
||||
} else {
|
||||
get_active_columns_mut(accounts, decks_cache).new_column_picker();
|
||||
get_active_columns_mut(i18n, accounts, decks_cache).new_column_picker();
|
||||
}
|
||||
}
|
||||
SidePanelAction::ComposeNote => {
|
||||
@@ -263,7 +274,7 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
switching_response = Some(crate::nav::SwitchingAction::Decks(
|
||||
DecksAction::Switch(index),
|
||||
));
|
||||
if let Some(edit_deck) = get_decks_mut(accounts, decks_cache)
|
||||
if let Some(edit_deck) = get_decks_mut(i18n, accounts, decks_cache)
|
||||
.decks_mut()
|
||||
.get_mut(index)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use egui::{vec2, Button, Label, Layout, RichText};
|
||||
use notedeck::{tr, NamedFontFamily, NotedeckTextStyle};
|
||||
use notedeck::{tr, Localization, NamedFontFamily, NotedeckTextStyle};
|
||||
use notedeck_ui::{colors::PINK, padding};
|
||||
use tracing::error;
|
||||
|
||||
@@ -7,11 +7,12 @@ use crate::support::Support;
|
||||
|
||||
pub struct SupportView<'a> {
|
||||
support: &'a mut Support,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl<'a> SupportView<'a> {
|
||||
pub fn new(support: &'a mut Support) -> Self {
|
||||
Self { support }
|
||||
pub fn new(support: &'a mut Support, i18n: &'a mut Localization) -> Self {
|
||||
Self { support, i18n }
|
||||
}
|
||||
|
||||
pub fn show(&mut self, ui: &mut egui::Ui) {
|
||||
@@ -22,14 +23,24 @@ impl<'a> SupportView<'a> {
|
||||
egui::FontFamily::Name(NamedFontFamily::Bold.as_str().into()),
|
||||
);
|
||||
ui.add(Label::new(
|
||||
RichText::new(tr!("Running into a bug?", "Heading for support section")).font(font),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Running into a bug?",
|
||||
"Heading for support section"
|
||||
))
|
||||
.font(font),
|
||||
));
|
||||
ui.label(
|
||||
RichText::new(tr!("Step 1", "Step 1 label in support instructions"))
|
||||
.text_style(NotedeckTextStyle::Heading3.text_style()),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Step 1",
|
||||
"Step 1 label in support instructions"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Heading3.text_style()),
|
||||
);
|
||||
padding(8.0, ui, |ui| {
|
||||
ui.label(tr!(
|
||||
self.i18n,
|
||||
"Open your default email client to get help from the Damus team",
|
||||
"Instruction to open email client"
|
||||
));
|
||||
@@ -37,7 +48,7 @@ impl<'a> SupportView<'a> {
|
||||
ui.allocate_ui_with_layout(size, Layout::top_down(egui::Align::Center), |ui| {
|
||||
let font_size =
|
||||
notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Body);
|
||||
let button_resp = ui.add(open_email_button(font_size, size));
|
||||
let button_resp = ui.add(open_email_button(self.i18n, font_size, size));
|
||||
if button_resp.clicked() {
|
||||
if let Err(e) = open::that(self.support.get_mailto_url()) {
|
||||
error!(
|
||||
@@ -55,19 +66,23 @@ impl<'a> SupportView<'a> {
|
||||
|
||||
if let Some(logs) = self.support.get_most_recent_log() {
|
||||
ui.label(
|
||||
RichText::new(tr!("Step 2", "Step 2 label in support instructions"))
|
||||
.text_style(NotedeckTextStyle::Heading3.text_style()),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Step 2",
|
||||
"Step 2 label in support instructions"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Heading3.text_style()),
|
||||
);
|
||||
let size = vec2(80.0, 40.0);
|
||||
let copy_button = Button::new(
|
||||
RichText::new(tr!("Copy", "Button label to copy logs")).size(
|
||||
RichText::new(tr!(self.i18n, "Copy", "Button label to copy logs")).size(
|
||||
notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Body),
|
||||
),
|
||||
)
|
||||
.fill(PINK)
|
||||
.min_size(size);
|
||||
padding(8.0, ui, |ui| {
|
||||
ui.add(Label::new(RichText::new(tr!("Press the button below to copy your most recent logs to your system's clipboard. Then paste it into your email.", "Instruction for copying logs"))).wrap());
|
||||
ui.add(Label::new(RichText::new(tr!(self.i18n,"Press the button below to copy your most recent logs to your system's clipboard. Then paste it into your email.", "Instruction for copying logs"))).wrap());
|
||||
ui.allocate_ui_with_layout(size, Layout::top_down(egui::Align::Center), |ui| {
|
||||
if ui.add(copy_button).clicked() {
|
||||
ui.ctx().copy_text(logs.to_string());
|
||||
@@ -86,9 +101,13 @@ impl<'a> SupportView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn open_email_button(font_size: f32, size: egui::Vec2) -> impl egui::Widget {
|
||||
fn open_email_button(
|
||||
i18n: &mut Localization,
|
||||
font_size: f32,
|
||||
size: egui::Vec2,
|
||||
) -> impl egui::Widget {
|
||||
Button::new(
|
||||
RichText::new(tr!("Open Email", "Button label to open email client")).size(font_size),
|
||||
RichText::new(tr!(i18n, "Open Email", "Button label to open email client")).size(font_size),
|
||||
)
|
||||
.fill(PINK)
|
||||
.min_size(size)
|
||||
|
||||
@@ -8,7 +8,9 @@ use std::f32::consts::PI;
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::timeline::{TimelineCache, TimelineKind, TimelineTab, ViewFilter};
|
||||
use notedeck::{note::root_note_id_from_selected_id, tr, NoteAction, NoteContext, ScrollInfo};
|
||||
use notedeck::{
|
||||
note::root_note_id_from_selected_id, tr, Localization, NoteAction, NoteContext, ScrollInfo,
|
||||
};
|
||||
use notedeck_ui::{
|
||||
anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE},
|
||||
NoteOptions, NoteView,
|
||||
@@ -103,7 +105,12 @@ fn timeline_ui(
|
||||
return None;
|
||||
};
|
||||
|
||||
timeline.selected_view = tabs_ui(ui, timeline.selected_view, &timeline.views);
|
||||
timeline.selected_view = tabs_ui(
|
||||
ui,
|
||||
note_context.i18n,
|
||||
timeline.selected_view,
|
||||
&timeline.views,
|
||||
);
|
||||
|
||||
// need this for some reason??
|
||||
ui.add_space(3.0);
|
||||
@@ -263,7 +270,12 @@ fn goto_top_button(center: Pos2) -> impl egui::Widget {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tabs_ui(ui: &mut egui::Ui, selected: usize, views: &[TimelineTab]) -> usize {
|
||||
pub fn tabs_ui(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
selected: usize,
|
||||
views: &[TimelineTab],
|
||||
) -> usize {
|
||||
ui.spacing_mut().item_spacing.y = 0.0;
|
||||
|
||||
let tab_res = egui_tabs::Tabs::new(views.len() as i32)
|
||||
@@ -281,9 +293,13 @@ pub fn tabs_ui(ui: &mut egui::Ui, selected: usize, views: &[TimelineTab]) -> usi
|
||||
let ind = state.index();
|
||||
|
||||
let txt = match views[ind as usize].filter {
|
||||
ViewFilter::Notes => tr!("Notes", "Label for notes-only filter"),
|
||||
ViewFilter::Notes => tr!(i18n, "Notes", "Label for notes-only filter"),
|
||||
ViewFilter::NotesAndReplies => {
|
||||
tr!("Notes & Replies", "Label for notes and replies filter")
|
||||
tr!(
|
||||
i18n,
|
||||
"Notes & Replies",
|
||||
"Label for notes and replies filter"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use egui::{vec2, CornerRadius, Layout};
|
||||
use notedeck::{
|
||||
get_current_wallet, tr, Accounts, DefaultZapMsats, GlobalWallet, NotedeckTextStyle,
|
||||
PendingDefaultZapState, Wallet, WalletError, WalletUIState, ZapWallet,
|
||||
get_current_wallet, tr, Accounts, DefaultZapMsats, GlobalWallet, Localization,
|
||||
NotedeckTextStyle, PendingDefaultZapState, Wallet, WalletError, WalletUIState, ZapWallet,
|
||||
};
|
||||
|
||||
use crate::{nav::RouterAction, route::Route};
|
||||
@@ -153,11 +153,12 @@ impl WalletAction {
|
||||
|
||||
pub struct WalletView<'a> {
|
||||
state: WalletState<'a>,
|
||||
i18n: &'a mut Localization,
|
||||
}
|
||||
|
||||
impl<'a> WalletView<'a> {
|
||||
pub fn new(state: WalletState<'a>) -> Self {
|
||||
Self { state }
|
||||
pub fn new(state: WalletState<'a>, i18n: &'a mut Localization) -> Self {
|
||||
Self { state, i18n }
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<WalletAction> {
|
||||
@@ -173,11 +174,17 @@ impl<'a> WalletView<'a> {
|
||||
wallet,
|
||||
default_zap_state,
|
||||
can_create_local_wallet,
|
||||
} => show_with_wallet(ui, wallet, default_zap_state, *can_create_local_wallet),
|
||||
} => show_with_wallet(
|
||||
ui,
|
||||
self.i18n,
|
||||
wallet,
|
||||
default_zap_state,
|
||||
*can_create_local_wallet,
|
||||
),
|
||||
WalletState::NoWallet {
|
||||
state,
|
||||
show_local_only,
|
||||
} => show_no_wallet(ui, state, *show_local_only),
|
||||
} => show_no_wallet(ui, self.i18n, state, *show_local_only),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,6 +203,7 @@ fn try_create_wallet(state: &mut WalletUIState) -> Option<Wallet> {
|
||||
|
||||
fn show_no_wallet(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
state: &mut WalletUIState,
|
||||
show_local_only: bool,
|
||||
) -> Option<WalletAction> {
|
||||
@@ -203,6 +211,7 @@ fn show_no_wallet(
|
||||
let text_edit = egui::TextEdit::singleline(&mut state.buf)
|
||||
.hint_text(
|
||||
egui::RichText::new(tr!(
|
||||
i18n,
|
||||
"Paste your NWC URI here...",
|
||||
"Placeholder text for NWC URI input"
|
||||
))
|
||||
@@ -222,10 +231,12 @@ fn show_no_wallet(
|
||||
|
||||
let error_str = match error_msg {
|
||||
WalletError::InvalidURI => tr!(
|
||||
i18n,
|
||||
"Invalid NWC URI",
|
||||
"Error message for invalid Nostr Wallet Connect URI"
|
||||
),
|
||||
WalletError::NoWallet => tr!(
|
||||
i18n,
|
||||
"Add a wallet to continue",
|
||||
"Error message for missing wallet"
|
||||
),
|
||||
@@ -239,6 +250,7 @@ fn show_no_wallet(
|
||||
ui.checkbox(
|
||||
&mut state.for_local_only,
|
||||
tr!(
|
||||
i18n,
|
||||
"Use this wallet for the current account only",
|
||||
"Checkbox label for using wallet only for current account"
|
||||
),
|
||||
@@ -248,7 +260,7 @@ fn show_no_wallet(
|
||||
|
||||
ui.with_layout(Layout::top_down(egui::Align::Center), |ui| {
|
||||
ui.add(styled_button(
|
||||
tr!("Add Wallet", "Button label to add a wallet").as_str(),
|
||||
tr!(i18n, "Add Wallet", "Button label to add a wallet").as_str(),
|
||||
notedeck_ui::colors::PINK,
|
||||
))
|
||||
.clicked()
|
||||
@@ -259,6 +271,7 @@ fn show_no_wallet(
|
||||
|
||||
fn show_with_wallet(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
wallet: &mut Wallet,
|
||||
default_zap_state: &mut DefaultZapState,
|
||||
can_create_local_wallet: bool,
|
||||
@@ -279,12 +292,12 @@ fn show_with_wallet(
|
||||
}
|
||||
});
|
||||
|
||||
let mut action = show_default_zap(ui, default_zap_state);
|
||||
let mut action = show_default_zap(ui, i18n, default_zap_state);
|
||||
|
||||
ui.with_layout(Layout::bottom_up(egui::Align::Min), |ui| 's: {
|
||||
if ui
|
||||
.add(styled_button(
|
||||
tr!("Delete Wallet", "Button label to delete a wallet").as_str(),
|
||||
tr!(i18n, "Delete Wallet", "Button label to delete a wallet").as_str(),
|
||||
ui.visuals().window_fill,
|
||||
))
|
||||
.clicked()
|
||||
@@ -299,6 +312,7 @@ fn show_with_wallet(
|
||||
.checkbox(
|
||||
&mut false,
|
||||
tr!(
|
||||
i18n,
|
||||
"Add a different wallet that will only be used for this account",
|
||||
"Button label to add a different wallet"
|
||||
),
|
||||
@@ -323,13 +337,17 @@ fn show_balance(ui: &mut egui::Ui, msats: u64) -> egui::Response {
|
||||
.inner
|
||||
}
|
||||
|
||||
fn show_default_zap(ui: &mut egui::Ui, state: &mut DefaultZapState) -> Option<WalletAction> {
|
||||
fn show_default_zap(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
state: &mut DefaultZapState,
|
||||
) -> Option<WalletAction> {
|
||||
let mut action = None;
|
||||
ui.allocate_ui_with_layout(
|
||||
vec2(ui.available_width(), 50.0),
|
||||
egui::Layout::left_to_right(egui::Align::Center).with_main_wrap(true),
|
||||
|ui| {
|
||||
ui.label(tr!("Default amount per zap: ", "Label for default zap amount input"));
|
||||
ui.label(tr!(i18n, "Default amount per zap: ", "Label for default zap amount input"));
|
||||
match state {
|
||||
DefaultZapState::Pending(pending_default_zap_state) => {
|
||||
let text = &mut pending_default_zap_state.amount_sats;
|
||||
@@ -361,27 +379,27 @@ fn show_default_zap(ui: &mut egui::Ui, state: &mut DefaultZapState) -> Option<Wa
|
||||
|
||||
ui.memory_mut(|m| m.request_focus(id));
|
||||
|
||||
ui.label(tr!("sats", "Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings."));
|
||||
ui.label(tr!(i18n, "sats", "Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings."));
|
||||
|
||||
if ui
|
||||
.add(styled_button(tr!("Save", "Button to save default zap amount").as_str(), ui.visuals().widgets.active.bg_fill))
|
||||
.add(styled_button(tr!(i18n, "Save", "Button to save default zap amount").as_str(), ui.visuals().widgets.active.bg_fill))
|
||||
.clicked()
|
||||
{
|
||||
action = Some(WalletAction::SetDefaultZapSats(text.to_string()));
|
||||
}
|
||||
}
|
||||
DefaultZapState::Valid(msats) => {
|
||||
if let Some(wallet_action) = show_valid_msats(ui, **msats) {
|
||||
if let Some(wallet_action) = show_valid_msats(ui, i18n, **msats) {
|
||||
action = Some(wallet_action);
|
||||
}
|
||||
ui.label(tr!("sats", "Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings."));
|
||||
ui.label(tr!(i18n, "sats", "Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings."));
|
||||
}
|
||||
}
|
||||
|
||||
if let DefaultZapState::Pending(pending) = state {
|
||||
if let Some(error_message) = &pending.error_message {
|
||||
let msg_str = match error_message {
|
||||
notedeck::DefaultZapError::InvalidUserInput => tr!("Invalid amount", "Error message for invalid zap amount"),
|
||||
notedeck::DefaultZapError::InvalidUserInput => tr!(i18n, "Invalid amount", "Error message for invalid zap amount"),
|
||||
};
|
||||
|
||||
ui.colored_label(ui.visuals().warn_fg_color, msg_str);
|
||||
@@ -393,7 +411,11 @@ fn show_default_zap(ui: &mut egui::Ui, state: &mut DefaultZapState) -> Option<Wa
|
||||
action
|
||||
}
|
||||
|
||||
fn show_valid_msats(ui: &mut egui::Ui, msats: u64) -> Option<WalletAction> {
|
||||
fn show_valid_msats(
|
||||
ui: &mut egui::Ui,
|
||||
i18n: &mut Localization,
|
||||
msats: u64,
|
||||
) -> Option<WalletAction> {
|
||||
let galley = {
|
||||
let painter = ui.painter();
|
||||
|
||||
@@ -409,7 +431,11 @@ fn show_valid_msats(ui: &mut egui::Ui, msats: u64) -> Option<WalletAction> {
|
||||
|
||||
let resp = resp
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
||||
.on_hover_text_at_pointer(tr!("Click to edit", "Hover text for editable zap amount"));
|
||||
.on_hover_text_at_pointer(tr!(
|
||||
i18n,
|
||||
"Click to edit",
|
||||
"Hover text for editable zap amount"
|
||||
));
|
||||
|
||||
let painter = ui.painter_at(resp.rect);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user