mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-04-09 03:45:44 +00:00
fix(core/mercury): multi-share backup more info
The commit fixes More Info screen hidden behind context menu during a prompt for number of shares and shares threshold. It removes wrong title and enables changing the info text based on currently selected number.
This commit is contained in:
parent
b567a91c22
commit
0d987a68f4
1
core/.changelog.d/4006.fixed
Normal file
1
core/.changelog.d/4006.fixed
Normal file
@ -0,0 +1 @@
|
||||
[T3T1] Fix More info screen during multi-share backup creation
|
@ -525,6 +525,8 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_reset__share_checked_successfully_template;
|
||||
MP_QSTR_reset__share_completed_template;
|
||||
MP_QSTR_reset__share_words_title;
|
||||
MP_QSTR_reset__slip39_checklist_more_info_threshold;
|
||||
MP_QSTR_reset__slip39_checklist_more_info_threshold_example_template;
|
||||
MP_QSTR_reset__slip39_checklist_num_groups;
|
||||
MP_QSTR_reset__slip39_checklist_num_groups_x_template;
|
||||
MP_QSTR_reset__slip39_checklist_num_shares;
|
||||
|
@ -1355,6 +1355,8 @@ pub enum TranslatedString {
|
||||
brightness__changed_title = 954, // "Display brightness changed"
|
||||
brightness__change_title = 955, // "Change display brightness"
|
||||
words__title_done = 956, // "Done"
|
||||
reset__slip39_checklist_more_info_threshold = 957, // "The threshold sets the minumum number of shares needed to recover your wallet."
|
||||
reset__slip39_checklist_more_info_threshold_example_template = 958, // "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet."
|
||||
}
|
||||
|
||||
impl TranslatedString {
|
||||
@ -2704,6 +2706,8 @@ impl TranslatedString {
|
||||
Self::brightness__changed_title => "Display brightness changed",
|
||||
Self::brightness__change_title => "Change display brightness",
|
||||
Self::words__title_done => "Done",
|
||||
Self::reset__slip39_checklist_more_info_threshold => "The threshold sets the minumum number of shares needed to recover your wallet.",
|
||||
Self::reset__slip39_checklist_more_info_threshold_example_template => "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet.",
|
||||
}
|
||||
}
|
||||
|
||||
@ -4054,6 +4058,8 @@ impl TranslatedString {
|
||||
Qstr::MP_QSTR_brightness__changed_title => Some(Self::brightness__changed_title),
|
||||
Qstr::MP_QSTR_brightness__change_title => Some(Self::brightness__change_title),
|
||||
Qstr::MP_QSTR_words__title_done => Some(Self::words__title_done),
|
||||
Qstr::MP_QSTR_reset__slip39_checklist_more_info_threshold => Some(Self::reset__slip39_checklist_more_info_threshold),
|
||||
Qstr::MP_QSTR_reset__slip39_checklist_more_info_threshold_example_template => Some(Self::reset__slip39_checklist_more_info_threshold_example_template),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ mod swipe_content;
|
||||
mod swipe_up_screen;
|
||||
#[cfg(feature = "translations")]
|
||||
mod tap_to_confirm;
|
||||
mod updatable_more_info;
|
||||
mod welcome_screen;
|
||||
|
||||
#[cfg(feature = "translations")]
|
||||
@ -82,6 +83,7 @@ pub use swipe_content::{InternallySwipable, InternallySwipableContent, SwipeCont
|
||||
pub use swipe_up_screen::{SwipeUpScreen, SwipeUpScreenMsg};
|
||||
#[cfg(feature = "translations")]
|
||||
pub use tap_to_confirm::TapToConfirm;
|
||||
pub use updatable_more_info::UpdatableMoreInfo;
|
||||
pub use vertical_menu::{VerticalMenu, VerticalMenuChoiceMsg};
|
||||
pub use welcome_screen::WelcomeScreen;
|
||||
|
||||
|
@ -4,7 +4,6 @@ use crate::{
|
||||
ui::{
|
||||
component::{
|
||||
base::ComponentExt,
|
||||
paginated::Paginate,
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
Child, Component, Event, EventCtx, Pad, SwipeDirection,
|
||||
},
|
||||
@ -17,28 +16,22 @@ use crate::{
|
||||
|
||||
use super::{theme, Button, ButtonMsg};
|
||||
|
||||
pub struct NumberInputDialogMsg(pub u32);
|
||||
pub enum NumberInputDialogMsg {
|
||||
Confirmed(u32),
|
||||
Changed(u32),
|
||||
}
|
||||
|
||||
pub struct NumberInputDialog<F>
|
||||
where
|
||||
F: Fn(u32) -> TString<'static>,
|
||||
{
|
||||
pub struct NumberInputDialog {
|
||||
area: Rect,
|
||||
description_func: F,
|
||||
input: Child<NumberInput>,
|
||||
paragraphs: Child<Paragraphs<Paragraph<'static>>>,
|
||||
paragraphs_pad: Pad,
|
||||
}
|
||||
|
||||
impl<F> NumberInputDialog<F>
|
||||
where
|
||||
F: Fn(u32) -> TString<'static>,
|
||||
{
|
||||
pub fn new(min: u32, max: u32, init_value: u32, description_func: F) -> Result<Self, Error> {
|
||||
let text = description_func(init_value);
|
||||
impl NumberInputDialog {
|
||||
pub fn new(min: u32, max: u32, init_value: u32, text: TString<'static>) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
area: Rect::zero(),
|
||||
description_func,
|
||||
input: NumberInput::new(min, max, init_value).into_child(),
|
||||
paragraphs: Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text))
|
||||
.into_child(),
|
||||
@ -46,27 +39,12 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn update_text(&mut self, ctx: &mut EventCtx, value: u32) {
|
||||
let text = (self.description_func)(value);
|
||||
self.paragraphs.mutate(ctx, move |ctx, para| {
|
||||
para.inner_mut().update(text);
|
||||
// Recompute bounding box.
|
||||
para.change_page(0);
|
||||
ctx.request_paint()
|
||||
});
|
||||
self.paragraphs_pad.clear();
|
||||
ctx.request_paint();
|
||||
}
|
||||
|
||||
pub fn value(&self) -> u32 {
|
||||
self.input.inner().value
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Component for NumberInputDialog<F>
|
||||
where
|
||||
F: Fn(u32) -> TString<'static>,
|
||||
{
|
||||
impl Component for NumberInputDialog {
|
||||
type Msg = NumberInputDialogMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
@ -87,11 +65,11 @@ where
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Some(NumberInputMsg::Changed(i)) = self.input.event(ctx, event) {
|
||||
self.update_text(ctx, i);
|
||||
return Some(NumberInputDialogMsg::Changed(i));
|
||||
}
|
||||
|
||||
if let Event::Swipe(SwipeEvent::End(SwipeDirection::Up)) = event {
|
||||
return Some(NumberInputDialogMsg(self.input.inner().value));
|
||||
return Some(NumberInputDialogMsg::Confirmed(self.input.inner().value));
|
||||
}
|
||||
self.paragraphs.event(ctx, event);
|
||||
None
|
||||
@ -109,10 +87,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F> crate::trace::Trace for NumberInputDialog<F>
|
||||
where
|
||||
F: Fn(u32) -> TString<'static>,
|
||||
{
|
||||
impl crate::trace::Trace for NumberInputDialog {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("NumberInputDialog");
|
||||
t.child("input", &self.input);
|
||||
|
@ -0,0 +1,82 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{
|
||||
paginated::Paginate,
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
Component, Event, EventCtx, Never,
|
||||
},
|
||||
geometry::Rect,
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::theme;
|
||||
|
||||
pub struct UpdatableMoreInfo<F>
|
||||
where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
info_func: F,
|
||||
paragraphs: Paragraphs<Paragraph<'static>>,
|
||||
}
|
||||
|
||||
impl<F> UpdatableMoreInfo<F>
|
||||
where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
pub fn new(info_func: F) -> Self {
|
||||
Self {
|
||||
info_func,
|
||||
paragraphs: Paragraphs::new(Paragraph::new(
|
||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||
TString::empty(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_text(&mut self, ctx: &mut EventCtx) {
|
||||
let text = (self.info_func)();
|
||||
self.paragraphs.inner_mut().update(text);
|
||||
self.paragraphs.change_page(0);
|
||||
ctx.request_paint();
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Component for UpdatableMoreInfo<F>
|
||||
where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.paragraphs.place(bounds);
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Event::Attach(_) = event {
|
||||
self.update_text(ctx);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
todo!("remove when ui-t3t1 done");
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.paragraphs.render(target);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F> crate::trace::Trace for UpdatableMoreInfo<F>
|
||||
where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("UpdatableMoreInfo");
|
||||
t.child("paragraphs", &self.paragraphs);
|
||||
}
|
||||
}
|
@ -5,24 +5,21 @@ use crate::{
|
||||
translations::TR,
|
||||
ui::{
|
||||
button_request::ButtonRequest,
|
||||
component::{
|
||||
swipe_detect::SwipeSettings,
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
ButtonRequestExt, ComponentExt, SwipeDirection,
|
||||
},
|
||||
component::{swipe_detect::SwipeSettings, ButtonRequestExt, ComponentExt, SwipeDirection},
|
||||
flow::{
|
||||
base::{DecisionBuilder as _, StateChange},
|
||||
FlowMsg, FlowState, SwipeFlow,
|
||||
},
|
||||
layout::obj::LayoutObj,
|
||||
model_mercury::component::SwipeContent,
|
||||
},
|
||||
};
|
||||
|
||||
use core::sync::atomic::{AtomicU16, Ordering};
|
||||
|
||||
use super::super::{
|
||||
component::{
|
||||
CancelInfoConfirmMsg, Frame, FrameMsg, NumberInputDialog, NumberInputDialogMsg,
|
||||
VerticalMenu, VerticalMenuChoiceMsg,
|
||||
SwipeContent, UpdatableMoreInfo, VerticalMenu, VerticalMenuChoiceMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -61,6 +58,8 @@ impl FlowState for RequestNumber {
|
||||
}
|
||||
}
|
||||
|
||||
static NUM_DISPLAYED: AtomicU16 = AtomicU16::new(0);
|
||||
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
pub extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestNumber::new_obj) }
|
||||
@ -72,27 +71,22 @@ impl RequestNumber {
|
||||
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
|
||||
let min_count: u32 = kwargs.get(Qstr::MP_QSTR_min_count)?.try_into()?;
|
||||
let max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?;
|
||||
let description: Obj = kwargs.get(Qstr::MP_QSTR_description)?;
|
||||
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||
let info: Obj = kwargs.get(Qstr::MP_QSTR_info)?;
|
||||
assert!(description != Obj::const_none());
|
||||
assert!(info != Obj::const_none());
|
||||
let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?;
|
||||
let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?;
|
||||
|
||||
let description_cb = move |i: u32| {
|
||||
TString::try_from(
|
||||
description
|
||||
.call_with_n_args(&[i.try_into().unwrap()])
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
let info_cb = move |i: u32| {
|
||||
TString::try_from(info.call_with_n_args(&[i.try_into().unwrap()]).unwrap()).unwrap()
|
||||
NUM_DISPLAYED.store(count as u16, Ordering::Relaxed);
|
||||
let info_cb = move || {
|
||||
let curr_number = NUM_DISPLAYED.load(Ordering::Relaxed) as u32;
|
||||
let text = info
|
||||
.call_with_n_args(&[curr_number.try_into().unwrap()])
|
||||
.unwrap();
|
||||
TString::try_from(text).unwrap()
|
||||
};
|
||||
|
||||
let number_input_dialog =
|
||||
NumberInputDialog::new(min_count, max_count, count, description_cb)?;
|
||||
let number_input_dialog = NumberInputDialog::new(min_count, max_count, count, description)?;
|
||||
let content_number_input =
|
||||
Frame::left_aligned(title, SwipeContent::new(number_input_dialog))
|
||||
.with_menu_button()
|
||||
@ -101,12 +95,19 @@ impl RequestNumber {
|
||||
.with_swipe(SwipeDirection::Left, SwipeSettings::default())
|
||||
.map(|msg| match msg {
|
||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
||||
FrameMsg::Content(NumberInputDialogMsg(n)) => Some(FlowMsg::Choice(n as usize)),
|
||||
FrameMsg::Content(NumberInputDialogMsg::Changed(n)) => {
|
||||
NUM_DISPLAYED.store(n as u16, Ordering::Relaxed);
|
||||
None
|
||||
}
|
||||
FrameMsg::Content(NumberInputDialogMsg::Confirmed(n)) => {
|
||||
NUM_DISPLAYED.store(n as u16, Ordering::Relaxed);
|
||||
Some(FlowMsg::Choice(n as usize))
|
||||
}
|
||||
})
|
||||
.one_button_request(ButtonRequest::from_num(br_code, br_name));
|
||||
|
||||
let content_menu = Frame::left_aligned(
|
||||
"".into(),
|
||||
TString::empty(),
|
||||
VerticalMenu::empty().item(theme::ICON_CHEVRON_RIGHT, TR::buttons__more_info.into()),
|
||||
)
|
||||
.with_cancel_button()
|
||||
@ -117,20 +118,14 @@ impl RequestNumber {
|
||||
FrameMsg::Button(_) => None,
|
||||
});
|
||||
|
||||
let paragraphs_info = Paragraphs::new(Paragraph::new(
|
||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||
info_cb(0), // TODO: get the value
|
||||
));
|
||||
let content_info = Frame::left_aligned(
|
||||
TR::backup__title_skip.into(),
|
||||
SwipeContent::new(paragraphs_info),
|
||||
)
|
||||
.with_cancel_button()
|
||||
.with_swipe(SwipeDirection::Right, SwipeSettings::immediate())
|
||||
.map(|msg| match msg {
|
||||
FrameMsg::Button(CancelInfoConfirmMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||
_ => None,
|
||||
});
|
||||
let updatable_info = UpdatableMoreInfo::new(info_cb);
|
||||
let content_info = Frame::left_aligned(TString::empty(), SwipeContent::new(updatable_info))
|
||||
.with_cancel_button()
|
||||
.with_swipe(SwipeDirection::Right, SwipeSettings::immediate())
|
||||
.map(|msg| match msg {
|
||||
FrameMsg::Button(CancelInfoConfirmMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let res = SwipeFlow::new(&RequestNumber::Number)?
|
||||
.with_page(&RequestNumber::Number, content_number_input)?
|
||||
|
@ -1704,7 +1704,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// count: int,
|
||||
/// min_count: int,
|
||||
/// max_count: int,
|
||||
/// description: Callable[[int], str] | None = None,
|
||||
/// description: str,
|
||||
/// info: Callable[[int], str] | None = None,
|
||||
/// br_code: ButtonRequestType,
|
||||
/// br_name: str,
|
||||
|
@ -420,7 +420,7 @@ def flow_request_number(
|
||||
count: int,
|
||||
min_count: int,
|
||||
max_count: int,
|
||||
description: Callable[[int], str] | None = None,
|
||||
description: str,
|
||||
info: Callable[[int], str] | None = None,
|
||||
br_code: ButtonRequestType,
|
||||
br_name: str,
|
||||
|
@ -652,6 +652,8 @@ class TR:
|
||||
reset__share_checked_successfully_template: str = "Share #{0} checked successfully."
|
||||
reset__share_completed_template: str = "Share #{0} completed"
|
||||
reset__share_words_title: str = "Standard backup"
|
||||
reset__slip39_checklist_more_info_threshold: str = "The threshold sets the minumum number of shares needed to recover your wallet."
|
||||
reset__slip39_checklist_more_info_threshold_example_template: str = "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet."
|
||||
reset__slip39_checklist_num_groups: str = "Number of groups"
|
||||
reset__slip39_checklist_num_groups_x_template: str = "Number of groups: {0}"
|
||||
reset__slip39_checklist_num_shares: str = "Number of shares"
|
||||
|
@ -183,11 +183,13 @@ async def _backup_slip39_advanced(
|
||||
groups_count = await layout.slip39_advanced_prompt_number_of_groups()
|
||||
|
||||
# get group threshold
|
||||
await layout.slip39_show_checklist(1, advanced=True)
|
||||
await layout.slip39_show_checklist(1, advanced=True, count=groups_count)
|
||||
group_threshold = await layout.slip39_advanced_prompt_group_threshold(groups_count)
|
||||
|
||||
# get shares and thresholds
|
||||
await layout.slip39_show_checklist(2, advanced=True)
|
||||
await layout.slip39_show_checklist(
|
||||
2, advanced=True, count=groups_count, threshold=group_threshold
|
||||
)
|
||||
groups = []
|
||||
for i in range(groups_count):
|
||||
share_count = await layout.slip39_prompt_number_of_shares(i)
|
||||
|
@ -157,7 +157,7 @@ def _slip_39_checklist_items(
|
||||
|
||||
async def _prompt_number(
|
||||
title: str,
|
||||
description: Callable[[int], str],
|
||||
description: str,
|
||||
info: Callable[[int], str],
|
||||
count: int,
|
||||
min_count: int,
|
||||
@ -200,38 +200,20 @@ async def slip39_prompt_threshold(
|
||||
min_count = min(2, num_of_shares)
|
||||
max_count = num_of_shares
|
||||
|
||||
def description(count: int) -> str:
|
||||
if group_id is None:
|
||||
return TR.reset__select_threshold
|
||||
else:
|
||||
return TR.reset__num_shares_for_group_template.format(group_id + 1)
|
||||
description = (
|
||||
TR.reset__select_threshold
|
||||
if group_id is None
|
||||
else TR.reset__num_shares_for_group_template.format(group_id + 1)
|
||||
)
|
||||
|
||||
def info(count: int) -> str:
|
||||
# TODO: this is madness...
|
||||
text = TR.reset__the_threshold_sets_the_number_of_shares
|
||||
if group_id is None:
|
||||
# FIXME: need to propagate the argument in rust, temporary hack to show plausible value
|
||||
count = num_of_shares - 1
|
||||
text += TR.reset__needed_to_recover_your_wallet
|
||||
text += TR.reset__set_it_to_count_template.format(count)
|
||||
if num_of_shares == 1:
|
||||
text += TR.reset__one_share
|
||||
elif num_of_shares == count:
|
||||
text += TR.reset__all_x_of_y_template.format(count, num_of_shares)
|
||||
else:
|
||||
text += TR.reset__any_x_of_y_template.format(count, num_of_shares)
|
||||
text += "."
|
||||
else:
|
||||
text += TR.reset__needed_to_form_a_group
|
||||
text += TR.reset__set_it_to_count_template.format(count)
|
||||
if num_of_shares == 1:
|
||||
text += TR.reset__one_share + " "
|
||||
elif num_of_shares == count:
|
||||
text += TR.reset__all_x_of_y_template.format(count, num_of_shares)
|
||||
else:
|
||||
text += TR.reset__any_x_of_y_template.format(count, num_of_shares)
|
||||
text += " " + TR.reset__to_form_group_template.format(group_id + 1)
|
||||
return text
|
||||
return (
|
||||
TR.reset__slip39_checklist_more_info_threshold
|
||||
+ "\n"
|
||||
+ TR.reset__slip39_checklist_more_info_threshold_example_template.format(
|
||||
count, num_of_shares, count
|
||||
)
|
||||
)
|
||||
|
||||
return await _prompt_number(
|
||||
TR.reset__title_set_threshold,
|
||||
@ -249,13 +231,11 @@ async def slip39_prompt_number_of_shares(group_id: int | None = None) -> int:
|
||||
min_count = 1
|
||||
max_count = 16
|
||||
|
||||
def description(i: int):
|
||||
if group_id is None:
|
||||
return TR.reset__num_of_shares_how_many
|
||||
else:
|
||||
return TR.reset__total_number_of_shares_in_group_template.format(
|
||||
group_id + 1
|
||||
)
|
||||
description = (
|
||||
TR.reset__num_of_shares_how_many
|
||||
if group_id is None
|
||||
else TR.reset__total_number_of_shares_in_group_template.format(group_id + 1)
|
||||
)
|
||||
|
||||
if group_id is None:
|
||||
info = TR.reset__num_of_shares_long_info
|
||||
@ -282,7 +262,7 @@ async def slip39_advanced_prompt_number_of_groups() -> int:
|
||||
|
||||
return await _prompt_number(
|
||||
TR.reset__title_set_number_of_groups,
|
||||
lambda i: description,
|
||||
description,
|
||||
lambda i: info,
|
||||
count,
|
||||
min_count,
|
||||
@ -300,7 +280,7 @@ async def slip39_advanced_prompt_group_threshold(num_of_groups: int) -> int:
|
||||
|
||||
return await _prompt_number(
|
||||
TR.reset__title_set_group_threshold,
|
||||
lambda i: description,
|
||||
description,
|
||||
lambda i: info,
|
||||
count,
|
||||
min_count,
|
||||
|
@ -654,6 +654,8 @@
|
||||
"reset__share_checked_successfully_template": "Share #{0} checked successfully.",
|
||||
"reset__share_completed_template": "Share #{0} completed",
|
||||
"reset__share_words_title": "Standard backup",
|
||||
"reset__slip39_checklist_more_info_threshold": "The threshold sets the minumum number of shares needed to recover your wallet.",
|
||||
"reset__slip39_checklist_more_info_threshold_example_template": "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet.",
|
||||
"reset__slip39_checklist_num_groups": "Number of groups",
|
||||
"reset__slip39_checklist_num_groups_x_template": "Number of groups: {0}",
|
||||
"reset__slip39_checklist_num_shares": "Number of shares",
|
||||
|
@ -955,5 +955,7 @@
|
||||
"953": "setting__apply",
|
||||
"954": "brightness__changed_title",
|
||||
"955": "brightness__change_title",
|
||||
"956": "words__title_done"
|
||||
"956": "words__title_done",
|
||||
"957": "reset__slip39_checklist_more_info_threshold",
|
||||
"958": "reset__slip39_checklist_more_info_threshold_example_template"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user