1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-03 03:50:58 +00:00

refactor(core/rust/ui): use TString instead of StrBuffer when constructing layouts

[no changelog]
This commit is contained in:
Martin Milata 2024-04-05 19:41:40 +02:00
parent 827b421394
commit c7832c39ab
7 changed files with 353 additions and 436 deletions

View File

@ -8,6 +8,7 @@ use crate::{
util::{iter_into_array, try_or_raise}, util::{iter_into_array, try_or_raise},
}, },
storage::{get_avatar_len, load_avatar}, storage::{get_avatar_len, load_avatar},
strutil::TString,
ui::{ ui::{
component::text::{ component::text::{
paragraphs::{Paragraph, ParagraphSource}, paragraphs::{Paragraph, ParagraphSource},
@ -24,16 +25,17 @@ use crate::{
pub const MAX_HEX_CHARS_ON_SCREEN: usize = 256; pub const MAX_HEX_CHARS_ON_SCREEN: usize = 256;
pub enum StrOrBytes { pub enum StrOrBytes {
Str(StrBuffer), Str(TString<'static>),
Bytes(Obj), Bytes(Obj),
} }
impl StrOrBytes { impl StrOrBytes {
pub fn as_str_offset(&self, offset: usize) -> StrBuffer { pub fn as_str_offset(&self, offset: usize) -> TString<'static> {
match self { match self {
StrOrBytes::Str(x) => x.skip_prefix(offset), StrOrBytes::Str(x) => x.skip_prefix(offset),
StrOrBytes::Bytes(x) => hexlify_bytes(*x, offset, MAX_HEX_CHARS_ON_SCREEN) StrOrBytes::Bytes(x) => hexlify_bytes(*x, offset, MAX_HEX_CHARS_ON_SCREEN)
.unwrap_or_else(|_| StrBuffer::from("ERROR")), .unwrap_or_else(|_| StrBuffer::from("ERROR"))
.into(),
} }
} }
} }
@ -53,8 +55,8 @@ impl TryFrom<Obj> for StrOrBytes {
} }
pub struct ConfirmBlob { pub struct ConfirmBlob {
pub description: StrBuffer, pub description: TString<'static>,
pub extra: StrBuffer, pub extra: TString<'static>,
pub data: StrOrBytes, pub data: StrOrBytes,
pub description_font: &'static TextStyle, pub description_font: &'static TextStyle,
pub extra_font: &'static TextStyle, pub extra_font: &'static TextStyle,

View File

@ -2,7 +2,7 @@ use heapless::Vec;
use crate::{ use crate::{
error::Error, error::Error,
micropython::buffer::StrBuffer, strutil::TString,
translations::TR, translations::TR,
ui::{ ui::{
component::{ component::{
@ -24,7 +24,7 @@ pub struct AddressDetails {
qr_code: Qr, qr_code: Qr,
details_view: Paragraphs<ParagraphVecShort<'static>>, details_view: Paragraphs<ParagraphVecShort<'static>>,
xpub_view: Frame<Paragraphs<Paragraph<'static>>>, xpub_view: Frame<Paragraphs<Paragraph<'static>>>,
xpubs: Vec<(StrBuffer, StrBuffer), MAX_XPUBS>, xpubs: Vec<(TString<'static>, TString<'static>), MAX_XPUBS>,
current_page: usize, current_page: usize,
current_subpage: usize, current_subpage: usize,
area: Rect, area: Rect,
@ -34,12 +34,14 @@ pub struct AddressDetails {
impl AddressDetails { impl AddressDetails {
pub fn new( pub fn new(
qr_address: StrBuffer, qr_address: TString<'static>,
case_sensitive: bool, case_sensitive: bool,
account: Option<StrBuffer>, account: Option<TString<'static>>,
path: Option<StrBuffer>, path: Option<TString<'static>>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let qr_code = Qr::new(qr_address, case_sensitive)?.with_border(QR_BORDER); let qr_code = qr_address
.map(|s| Qr::new(s, case_sensitive))?
.with_border(QR_BORDER);
let details_view = { let details_view = {
let mut para = ParagraphVecShort::new(); let mut para = ParagraphVecShort::new();
if let Some(account) = account { if let Some(account) = account {
@ -74,7 +76,11 @@ impl AddressDetails {
Ok(result) Ok(result)
} }
pub fn add_xpub(&mut self, title: StrBuffer, xpub: StrBuffer) -> Result<(), Error> { pub fn add_xpub(
&mut self,
title: TString<'static>,
xpub: TString<'static>,
) -> Result<(), Error> {
self.xpubs self.xpubs
.push((title, xpub)) .push((title, xpub))
.map_err(|_| Error::OutOfRange) .map_err(|_| Error::OutOfRange)
@ -149,7 +155,7 @@ impl AddressDetails {
fn fill_xpub_page(&mut self, ctx: &mut EventCtx) { fn fill_xpub_page(&mut self, ctx: &mut EventCtx) {
let i = self.current_page - 2; let i = self.current_page - 2;
self.xpub_view.update_title(ctx, self.xpubs[i].0.into()); self.xpub_view.update_title(ctx, self.xpubs[i].0);
self.xpub_view.update_content(ctx, |p| { self.xpub_view.update_content(ctx, |p| {
p.inner_mut().update(self.xpubs[i].1); p.inner_mut().update(self.xpubs[i].1);
p.change_page(0) p.change_page(0)

View File

@ -1,7 +1,7 @@
use core::mem; use core::mem;
use crate::{ use crate::{
strutil::StringType, strutil::TString,
translations::TR, translations::TR,
ui::{ ui::{
component::{ component::{
@ -21,19 +21,16 @@ const FOOTER_TEXT_MARGIN: i16 = 8;
const LOADER_OFFSET: i16 = -15; const LOADER_OFFSET: i16 = -15;
const LOADER_SPEED: u16 = 10; const LOADER_SPEED: u16 = 10;
pub struct CoinJoinProgress<T> { pub struct CoinJoinProgress {
value: u16, value: u16,
loader_y_offset: i16, loader_y_offset: i16,
text: T, text: TString<'static>,
area: Rect, area: Rect,
indeterminate: bool, indeterminate: bool,
} }
impl<T> CoinJoinProgress<T> impl CoinJoinProgress {
where pub fn new(text: TString<'static>, indeterminate: bool) -> Self {
T: StringType,
{
pub fn new(text: T, indeterminate: bool) -> Self {
Self { Self {
value: 0, value: 0,
loader_y_offset: LOADER_OFFSET, loader_y_offset: LOADER_OFFSET,
@ -44,10 +41,7 @@ where
} }
} }
impl<T> Component for CoinJoinProgress<T> impl Component for CoinJoinProgress {
where
T: StringType,
{
type Msg = Never; type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
@ -122,7 +116,7 @@ where
if let Some(rest) = top_rest { if let Some(rest) = top_rest {
text_multiline_bottom( text_multiline_bottom(
rest.inset(Insets::bottom(FOOTER_TEXT_MARGIN)), rest.inset(Insets::bottom(FOOTER_TEXT_MARGIN)),
self.text.as_ref().into(), self.text,
Font::NORMAL, Font::NORMAL,
theme::FG, theme::FG,
theme::BG, theme::BG,
@ -133,14 +127,11 @@ where
} }
#[cfg(feature = "ui_debug")] #[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for CoinJoinProgress<T> impl crate::trace::Trace for CoinJoinProgress {
where
T: StringType,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) { fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.component("CoinJoinProgress"); t.component("CoinJoinProgress");
t.string("header", TR::coinjoin__title_progress.into()); t.string("header", TR::coinjoin__title_progress.into());
t.string("text", self.text.as_ref().into()); t.string("text", self.text);
t.string("footer", TR::coinjoin__do_not_disconnect.into()); t.string("footer", TR::coinjoin__do_not_disconnect.into());
} }
} }

View File

@ -16,7 +16,7 @@ use crate::{
qstr::Qstr, qstr::Qstr,
util, util,
}, },
strutil::{StringType, TString}, strutil::TString,
translations::TR, translations::TR,
trezorhal::model, trezorhal::model,
ui::{ ui::{
@ -142,10 +142,7 @@ impl ComponentMsgObj for AddressDetails {
} }
} }
impl<T> ComponentMsgObj for CoinJoinProgress<T> impl ComponentMsgObj for CoinJoinProgress {
where
T: StringType,
{
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> { fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
unreachable!(); unreachable!();
} }
@ -242,10 +239,10 @@ impl ComponentMsgObj for super::component::bl_confirm::Confirm<'_> {
/// Function to create and call a `ButtonPage` dialog based on paginable content /// Function to create and call a `ButtonPage` dialog based on paginable content
/// (e.g. `Paragraphs` or `FormattedText`). /// (e.g. `Paragraphs` or `FormattedText`).
/// Has optional title (supply empty `StrBuffer` for that) and hold-to-confirm /// Has optional title (supply empty `TString` for that) and hold-to-confirm
/// functionality. /// functionality.
fn content_in_button_page<T: Component + Paginate + MaybeTrace + 'static>( fn content_in_button_page<T: Component + Paginate + MaybeTrace + 'static>(
title: StrBuffer, title: TString<'static>,
content: T, content: T,
verb: TString<'static>, verb: TString<'static>,
verb_cancel: Option<TString<'static>>, verb_cancel: Option<TString<'static>>,
@ -270,8 +267,8 @@ fn content_in_button_page<T: Component + Paginate + MaybeTrace + 'static>(
.with_confirm_btn(confirm_btn); .with_confirm_btn(confirm_btn);
let mut frame = ScrollableFrame::new(content); let mut frame = ScrollableFrame::new(content);
if !title.as_ref().is_empty() { if !title.is_empty() {
frame = frame.with_title(title.into()); frame = frame.with_title(title);
} }
let obj = LayoutObj::new(frame)?; let obj = LayoutObj::new(frame)?;
@ -280,9 +277,9 @@ fn content_in_button_page<T: Component + Paginate + MaybeTrace + 'static>(
extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let action: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?; let action: Option<TString> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
let description: Option<StrBuffer> = let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let verb: TString<'static> = let verb: TString<'static> =
kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?; kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?;
@ -294,8 +291,8 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
let paragraphs = { let paragraphs = {
let action = action.unwrap_or_default(); let action = action.unwrap_or("".into());
let description = description.unwrap_or_default(); let description = description.unwrap_or("".into());
let mut paragraphs = ParagraphVecShort::new(); let mut paragraphs = ParagraphVecShort::new();
if !reverse { if !reverse {
paragraphs paragraphs
@ -316,11 +313,11 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?;
let description: Option<StrBuffer> = let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let extra: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?; let extra: Option<TString> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
let verb: TString<'static> = let verb: TString<'static> =
kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?; kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?;
let verb_cancel: Option<TString<'static>> = kwargs let verb_cancel: Option<TString<'static>> = kwargs
@ -338,8 +335,8 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
}; };
let paragraphs = ConfirmBlob { let paragraphs = ConfirmBlob {
description: description.unwrap_or_else(StrBuffer::empty), description: description.unwrap_or("".into()),
extra: extra.unwrap_or_else(StrBuffer::empty), extra: extra.unwrap_or("".into()),
data: data.try_into()?, data: data.try_into()?,
description_font: &theme::TEXT_BOLD, description_font: &theme::TEXT_BOLD,
extra_font: &theme::TEXT_NORMAL, extra_font: &theme::TEXT_NORMAL,
@ -354,7 +351,7 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
@ -362,8 +359,8 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
for para in IterBuf::new().try_iterate(items)? { for para in IterBuf::new().try_iterate(items)? {
let [key, value, is_data]: [Obj; 3] = util::iter_into_array(para)?; let [key, value, is_data]: [Obj; 3] = util::iter_into_array(para)?;
let key = key.try_into_option::<StrBuffer>()?; let key = key.try_into_option::<TString>()?;
let value = value.try_into_option::<StrBuffer>()?; let value = value.try_into_option::<TString>()?;
let is_data: bool = is_data.try_into()?; let is_data: bool = is_data.try_into()?;
if let Some(key) = key { if let Some(key) = key {
@ -402,7 +399,7 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?; let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?;
// Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8] // Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8]
@ -411,7 +408,7 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
// discarded before returning to micropython. // discarded before returning to micropython.
let buffer_func = move || unsafe { unwrap!(get_buffer(data)) }; let buffer_func = move || unsafe { unwrap!(get_buffer(data)) };
let obj = LayoutObj::new(ConfirmHomescreen::new(title.into(), buffer_func))?; let obj = LayoutObj::new(ConfirmHomescreen::new(title, buffer_func))?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -420,7 +417,7 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let ops = OpTextLayout::new(theme::TEXT_NORMAL) let ops = OpTextLayout::new(theme::TEXT_NORMAL)
@ -471,17 +468,17 @@ extern "C" fn new_confirm_backup(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?; let address: TString = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?;
let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?; let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?;
let account: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?; let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
let path: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?; let path: Option<TString> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?;
let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?; let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?;
let mut ad = AddressDetails::new(address, case_sensitive, account, path)?; let mut ad = AddressDetails::new(address, case_sensitive, account, path)?;
for i in IterBuf::new().try_iterate(xpubs)? { for i in IterBuf::new().try_iterate(xpubs)? {
let [xtitle, text]: [StrBuffer; 2] = util::iter_into_array(i)?; let [xtitle, text]: [TString; 2] = util::iter_into_array(i)?;
ad.add_xpub(xtitle, text)?; ad.add_xpub(xtitle, text)?;
} }
@ -493,9 +490,9 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let value: StrBuffer = kwargs.get(Qstr::MP_QSTR_value)?.try_into()?; let value: TString = kwargs.get(Qstr::MP_QSTR_value)?.try_into()?;
let verb: Option<TString<'static>> = kwargs let verb: Option<TString<'static>> = kwargs
.get(Qstr::MP_QSTR_verb) .get(Qstr::MP_QSTR_verb)
@ -521,8 +518,8 @@ extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_confirm_joint_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_joint_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let spending_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_spending_amount)?.try_into()?; let spending_amount: TString = kwargs.get(Qstr::MP_QSTR_spending_amount)?.try_into()?;
let total_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?; let total_amount: TString = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?;
let paragraphs = Paragraphs::new([ let paragraphs = Paragraphs::new([
Paragraph::new(&theme::TEXT_BOLD, TR::joint__you_are_contributing), Paragraph::new(&theme::TEXT_BOLD, TR::joint__you_are_contributing),
@ -545,8 +542,8 @@ extern "C" fn new_confirm_joint_total(n_args: usize, args: *const Obj, kwargs: *
extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?; let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?;
let amount_change: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_change)?.try_into()?; let amount_change: TString = kwargs.get(Qstr::MP_QSTR_amount_change)?.try_into()?;
let amount_new: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_new)?.try_into()?; let amount_new: TString = kwargs.get(Qstr::MP_QSTR_amount_new)?.try_into()?;
let description = if sign < 0 { let description = if sign < 0 {
TR::modify_amount__decrease_amount TR::modify_amount__decrease_amount
@ -574,9 +571,9 @@ extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_confirm_output_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_output_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?; let address: TString = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?;
let address_label: StrBuffer = kwargs.get(Qstr::MP_QSTR_address_label)?.try_into()?; let address_label: TString = kwargs.get(Qstr::MP_QSTR_address_label)?.try_into()?;
let address_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_address_title)?.try_into()?; let address_title: TString = kwargs.get(Qstr::MP_QSTR_address_title)?.try_into()?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
let get_page = move |page_index| { let get_page = move |page_index| {
@ -602,7 +599,7 @@ extern "C" fn new_confirm_output_address(n_args: usize, args: *const Obj, kwargs
} }
ops = ops.text_mono(address); ops = ops.text_mono(address);
let formatted = FormattedText::new(ops).vertically_centered(); let formatted = FormattedText::new(ops).vertically_centered();
Page::new(btn_layout, btn_actions, formatted).with_title(address_title.into()) Page::new(btn_layout, btn_actions, formatted).with_title(address_title)
}; };
let pages = FlowPages::new(get_page, 1); let pages = FlowPages::new(get_page, 1);
@ -614,8 +611,8 @@ extern "C" fn new_confirm_output_address(n_args: usize, args: *const Obj, kwargs
extern "C" fn new_confirm_output_amount(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_output_amount(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount)?.try_into()?; let amount: TString = kwargs.get(Qstr::MP_QSTR_amount)?.try_into()?;
let amount_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_title)?.try_into()?; let amount_title: TString = kwargs.get(Qstr::MP_QSTR_amount_title)?.try_into()?;
let get_page = move |page_index| { let get_page = move |page_index| {
assert!(page_index == 0); assert!(page_index == 0);
@ -624,7 +621,7 @@ extern "C" fn new_confirm_output_amount(n_args: usize, args: *const Obj, kwargs:
let btn_actions = ButtonActions::cancel_none_confirm(); let btn_actions = ButtonActions::cancel_none_confirm();
let ops = OpTextLayout::new(theme::TEXT_MONO).text_mono(amount); let ops = OpTextLayout::new(theme::TEXT_MONO).text_mono(amount);
let formatted = FormattedText::new(ops).vertically_centered(); let formatted = FormattedText::new(ops).vertically_centered();
Page::new(btn_layout, btn_actions, formatted).with_title(amount_title.into()) Page::new(btn_layout, btn_actions, formatted).with_title(amount_title)
}; };
let pages = FlowPages::new(get_page, 1); let pages = FlowPages::new(get_page, 1);
@ -636,15 +633,15 @@ extern "C" fn new_confirm_output_amount(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let total_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?; let total_amount: TString = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?;
let fee_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_amount)?.try_into()?; let fee_amount: TString = kwargs.get(Qstr::MP_QSTR_fee_amount)?.try_into()?;
let fee_rate_amount: Option<StrBuffer> = kwargs let fee_rate_amount: Option<TString> = kwargs
.get(Qstr::MP_QSTR_fee_rate_amount)? .get(Qstr::MP_QSTR_fee_rate_amount)?
.try_into_option()?; .try_into_option()?;
let account_label: Option<StrBuffer> = let account_label: Option<TString> =
kwargs.get(Qstr::MP_QSTR_account_label)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_account_label)?.try_into_option()?;
let total_label: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_label)?.try_into()?; let total_label: TString = kwargs.get(Qstr::MP_QSTR_total_label)?.try_into()?;
let fee_label: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_label)?.try_into()?; let fee_label: TString = kwargs.get(Qstr::MP_QSTR_fee_label)?.try_into()?;
let get_page = move |page_index| { let get_page = move |page_index| {
match page_index { match page_index {
@ -671,7 +668,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
let btn_layout = ButtonLayout::arrow_none_arrow(); let btn_layout = ButtonLayout::arrow_none_arrow();
let btn_actions = ButtonActions::prev_none_next(); let btn_actions = ButtonActions::prev_none_next();
let fee_rate_amount = fee_rate_amount.unwrap_or_default(); let fee_rate_amount = fee_rate_amount.unwrap_or("".into());
let ops = OpTextLayout::new(theme::TEXT_MONO) let ops = OpTextLayout::new(theme::TEXT_MONO)
.text_bold(TR::confirm_total__title_fee) .text_bold(TR::confirm_total__title_fee)
@ -690,7 +687,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
let btn_layout = ButtonLayout::arrow_none_none(); let btn_layout = ButtonLayout::arrow_none_none();
let btn_actions = ButtonActions::prev_none_none(); let btn_actions = ButtonActions::prev_none_none();
let account_label = account_label.unwrap_or_default(); let account_label = account_label.unwrap_or("".into());
// TODO: include wallet info when available // TODO: include wallet info when available
@ -719,10 +716,10 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_altcoin_tx_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_altcoin_tx_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let amount_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_title)?.try_into()?; let amount_title: TString = kwargs.get(Qstr::MP_QSTR_amount_title)?.try_into()?;
let amount_value: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_value)?.try_into()?; let amount_value: TString = kwargs.get(Qstr::MP_QSTR_amount_value)?.try_into()?;
let fee_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_title)?.try_into()?; let fee_title: TString = kwargs.get(Qstr::MP_QSTR_fee_title)?.try_into()?;
let fee_value: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_value)?.try_into()?; let fee_value: TString = kwargs.get(Qstr::MP_QSTR_fee_value)?.try_into()?;
let cancel_cross: bool = kwargs.get_or(Qstr::MP_QSTR_cancel_cross, false)?; let cancel_cross: bool = kwargs.get_or(Qstr::MP_QSTR_cancel_cross, false)?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
@ -746,7 +743,7 @@ extern "C" fn new_altcoin_tx_summary(n_args: usize, args: *const Obj, kwargs: *m
.text_mono(fee_value); .text_mono(fee_value);
let formatted = FormattedText::new(ops); let formatted = FormattedText::new(ops);
Page::new(btn_layout, btn_actions, formatted).with_title(amount_title.into()) Page::new(btn_layout, btn_actions, formatted).with_title(amount_title)
} }
1 => { 1 => {
// Other information // Other information
@ -785,8 +782,8 @@ extern "C" fn new_altcoin_tx_summary(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_data)?.try_into()?; let address: TString = kwargs.get(Qstr::MP_QSTR_data)?.try_into()?;
let verb: TString<'static> = let verb: TString<'static> =
kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?; kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
@ -804,7 +801,7 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
}; };
let ops = OpTextLayout::new(style).text_mono(address); let ops = OpTextLayout::new(style).text_mono(address);
let formatted = FormattedText::new(ops).vertically_centered(); let formatted = FormattedText::new(ops).vertically_centered();
Page::new(btn_layout, btn_actions, formatted).with_title(title.into()) Page::new(btn_layout, btn_actions, formatted).with_title(title)
}; };
let pages = FlowPages::new(get_page, 1); let pages = FlowPages::new(get_page, 1);
@ -906,16 +903,16 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?; let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?;
let user_fee_change: StrBuffer = kwargs.get(Qstr::MP_QSTR_user_fee_change)?.try_into()?; let user_fee_change: TString = kwargs.get(Qstr::MP_QSTR_user_fee_change)?.try_into()?;
let total_fee_new: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_fee_new)?.try_into()?; let total_fee_new: TString = kwargs.get(Qstr::MP_QSTR_total_fee_new)?.try_into()?;
let fee_rate_amount: Option<StrBuffer> = kwargs let fee_rate_amount: Option<TString> = kwargs
.get(Qstr::MP_QSTR_fee_rate_amount)? .get(Qstr::MP_QSTR_fee_rate_amount)?
.try_into_option()?; .try_into_option()?;
let (description, change) = match sign { let (description, change) = match sign {
s if s < 0 => (TR::modify_fee__decrease_fee, user_fee_change), s if s < 0 => (TR::modify_fee__decrease_fee, user_fee_change),
s if s > 0 => (TR::modify_fee__increase_fee, user_fee_change), s if s > 0 => (TR::modify_fee__increase_fee, user_fee_change),
_ => (TR::modify_fee__no_change, StrBuffer::empty()), _ => (TR::modify_fee__no_change, "".into()),
}; };
let mut paragraphs_vec = ParagraphVecShort::new(); let mut paragraphs_vec = ParagraphVecShort::new();
@ -944,7 +941,7 @@ extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_multiple_pages_texts(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_multiple_pages_texts(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let verb: TString = kwargs.get(Qstr::MP_QSTR_verb)?.try_into()?; let verb: TString = kwargs.get(Qstr::MP_QSTR_verb)?.try_into()?;
let items: Gc<List> = kwargs.get(Qstr::MP_QSTR_items)?.try_into()?; let items: Gc<List> = kwargs.get(Qstr::MP_QSTR_items)?.try_into()?;
@ -991,7 +988,7 @@ extern "C" fn new_multiple_pages_texts(n_args: usize, args: *const Obj, kwargs:
}; };
let pages = FlowPages::new(get_page, page_count); let pages = FlowPages::new(get_page, page_count);
let obj = LayoutObj::new(Flow::new(pages).with_common_title(title.into()))?; let obj = LayoutObj::new(Flow::new(pages).with_common_title(title))?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -999,8 +996,8 @@ extern "C" fn new_multiple_pages_texts(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let app_name: StrBuffer = kwargs.get(Qstr::MP_QSTR_app_name)?.try_into()?; let app_name: TString = kwargs.get(Qstr::MP_QSTR_app_name)?.try_into()?;
let accounts: Gc<List> = kwargs.get(Qstr::MP_QSTR_accounts)?.try_into()?; let accounts: Gc<List> = kwargs.get(Qstr::MP_QSTR_accounts)?.try_into()?;
// Cache the page count so that we can move `accounts` into the closure. // Cache the page count so that we can move `accounts` into the closure.
@ -1053,7 +1050,7 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
// Returning the page index in case of confirmation. // Returning the page index in case of confirmation.
let obj = LayoutObj::new( let obj = LayoutObj::new(
Flow::new(pages) Flow::new(pages)
.with_common_title(title.into()) .with_common_title(title)
.with_return_confirmed_index(), .with_return_confirmed_index(),
)?; )?;
Ok(obj.into()) Ok(obj.into())
@ -1064,8 +1061,8 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let warning: StrBuffer = kwargs.get(Qstr::MP_QSTR_warning)?.try_into()?; let warning: TString = kwargs.get(Qstr::MP_QSTR_warning)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let get_page = move |page_index| { let get_page = move |page_index| {
assert!(page_index == 0); assert!(page_index == 0);
@ -1092,13 +1089,12 @@ extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
kwargs.get_or(Qstr::MP_QSTR_description, StrBuffer::empty())?;
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?; let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
let content = Frame::new( let content = Frame::new(
title.into(), title,
Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]), Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]),
); );
let obj = if time_ms == 0 { let obj = if time_ms == 0 {
@ -1118,7 +1114,7 @@ extern "C" fn new_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -
extern "C" fn new_show_passphrase() -> Obj { extern "C" fn new_show_passphrase() -> Obj {
let block = move || { let block = move || {
let text: StrBuffer = TR::passphrase__please_enter.try_into()?; let text: TString = TR::passphrase__please_enter.try_into()?;
let paragraph = Paragraph::new(&theme::TEXT_NORMAL, text).centered(); let paragraph = Paragraph::new(&theme::TEXT_NORMAL, text).centered();
let content = Paragraphs::new([paragraph]); let content = Paragraphs::new([paragraph]);
let obj = LayoutObj::new(content)?; let obj = LayoutObj::new(content)?;
@ -1129,7 +1125,7 @@ extern "C" fn new_show_passphrase() -> Obj {
extern "C" fn new_show_waiting_text(message: Obj) -> Obj { extern "C" fn new_show_waiting_text(message: Obj) -> Obj {
let block = || { let block = || {
let text: StrBuffer = message.try_into()?; let text: TString = message.try_into()?;
let paragraph = Paragraph::new(&theme::TEXT_NORMAL, text).centered(); let paragraph = Paragraph::new(&theme::TEXT_NORMAL, text).centered();
let content = Paragraphs::new([paragraph]); let content = Paragraphs::new([paragraph]);
let obj = LayoutObj::new(content)?; let obj = LayoutObj::new(content)?;
@ -1140,7 +1136,7 @@ extern "C" fn new_show_waiting_text(message: Obj) -> Obj {
extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let get_page = move |page_index| { let get_page = move |page_index| {
assert!(page_index == 0); assert!(page_index == 0);
@ -1167,7 +1163,7 @@ extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let verb_cancel: Option<TString<'static>> = kwargs let verb_cancel: Option<TString<'static>> = kwargs
.get(Qstr::MP_QSTR_verb_cancel) .get(Qstr::MP_QSTR_verb_cancel)
@ -1180,7 +1176,7 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
for para in IterBuf::new().try_iterate(items)? { for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = util::iter_into_array(para)?; let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?); let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: TString = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
if paragraphs.is_full() { if paragraphs.is_full() {
break; break;
@ -1188,7 +1184,7 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
} }
let obj = LayoutObj::new(Frame::new( let obj = LayoutObj::new(Frame::new(
title.into(), title,
ShowMore::<Paragraphs<ParagraphVecShort>>::new( ShowMore::<Paragraphs<ParagraphVecShort>>::new(
paragraphs.into_paragraphs(), paragraphs.into_paragraphs(),
verb_cancel, verb_cancel,
@ -1202,7 +1198,7 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
@ -1211,7 +1207,7 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
for para in IterBuf::new().try_iterate(items)? { for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = util::iter_into_array(para)?; let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?); let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: TString = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
} }
@ -1228,8 +1224,8 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let max_rounds: StrBuffer = kwargs.get(Qstr::MP_QSTR_max_rounds)?.try_into()?; let max_rounds: TString = kwargs.get(Qstr::MP_QSTR_max_rounds)?.try_into()?;
let max_feerate: StrBuffer = kwargs.get(Qstr::MP_QSTR_max_feerate)?.try_into()?; let max_feerate: TString = kwargs.get(Qstr::MP_QSTR_max_feerate)?.try_into()?;
// Decreasing bottom padding between paragraphs to fit one screen // Decreasing bottom padding between paragraphs to fit one screen
let paragraphs = Paragraphs::new([ let paragraphs = Paragraphs::new([
@ -1254,10 +1250,10 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let subprompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?; let subprompt: TString = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?;
let obj = LayoutObj::new(PinEntry::new(prompt.into(), subprompt.into()))?; let obj = LayoutObj::new(PinEntry::new(prompt, subprompt))?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -1266,11 +1262,9 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::new(prompt, PassphraseEntry::new()).with_title_centered())?;
Frame::new(prompt.into(), PassphraseEntry::new()).with_title_centered(),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1279,17 +1273,14 @@ extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let prefill_word: StrBuffer = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?;
let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?;
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::new( Frame::new(
prompt.into(), prompt,
WordlistEntry::prefilled_word( prefill_word
prefill_word.as_ref(), .map(|s| WordlistEntry::prefilled_word(s, WordlistType::Bip39, can_go_back)),
WordlistType::Bip39,
can_go_back,
),
) )
.with_title_centered(), .with_title_centered(),
)?; )?;
@ -1300,18 +1291,15 @@ extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let prefill_word: StrBuffer = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?;
let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?;
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::new( Frame::new(
prompt.into(), prompt,
WordlistEntry::prefilled_word( prefill_word
prefill_word.as_ref(), .map(|s| WordlistEntry::prefilled_word(s, WordlistType::Slip39, can_go_back)),
WordlistType::Slip39,
can_go_back,
),
) )
.with_title_centered(), .with_title_centered(),
)?; )?;
@ -1323,7 +1311,7 @@ extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
// we ignore passed in `title` and use `description` in its place // we ignore passed in `title` and use `description` in its place
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let words_iterable: Obj = kwargs.get(Qstr::MP_QSTR_words)?; let words_iterable: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
// There are only 3 words, but SimpleChoice requires 5 elements // There are only 3 words, but SimpleChoice requires 5 elements
let words: Vec<TString<'static>, 5> = util::iter_into_vec(words_iterable)?; let words: Vec<TString<'static>, 5> = util::iter_into_vec(words_iterable)?;
@ -1331,7 +1319,7 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
// Returning the index of the selected word, not the word itself // Returning the index of the selected word, not the word itself
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::new( Frame::new(
description.into(), description,
SimpleChoice::new(words, false) SimpleChoice::new(words, false)
.with_show_incomplete() .with_show_incomplete()
.with_return_index(), .with_return_index(),
@ -1364,14 +1352,13 @@ extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let min_count: u32 = kwargs.get(Qstr::MP_QSTR_min_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 max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?;
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?; let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::new(title.into(), NumberInput::new(min_count, max_count, count)) Frame::new(title, NumberInput::new(min_count, max_count, count)).with_title_centered(),
.with_title_centered(),
)?; )?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -1391,7 +1378,7 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
Ordering::Equal => &theme::TEXT_BOLD, Ordering::Equal => &theme::TEXT_BOLD,
Ordering::Greater => &theme::TEXT_NORMAL, Ordering::Greater => &theme::TEXT_NORMAL,
}; };
let text: StrBuffer = item.try_into()?; let text: TString = item.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
} }
@ -1420,7 +1407,7 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
let show_info: bool = kwargs.get(Qstr::MP_QSTR_show_info)?.try_into()?; let show_info: bool = kwargs.get(Qstr::MP_QSTR_show_info)?.try_into()?;
@ -1458,7 +1445,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], _kwargs: &Map| { let block = |_args: &[Obj], _kwargs: &Map| {
let title: StrBuffer = TR::word_count__title.try_into()?; let title: TString = TR::word_count__title.try_into()?;
let choices: Vec<TString<'static>, 5> = ["12", "18", "20", "24", "33"] let choices: Vec<TString<'static>, 5> = ["12", "18", "20", "24", "33"]
.map(|num| num.into()) .map(|num| num.into())
@ -1466,7 +1453,7 @@ extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mu
.collect(); .collect();
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::new(title.into(), SimpleChoice::new(choices, false)).with_title_centered(), Frame::new(title, SimpleChoice::new(choices, false)).with_title_centered(),
)?; )?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -1480,7 +1467,7 @@ extern "C" fn new_show_group_share_success(
) -> Obj { ) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?; let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?;
let lines: [StrBuffer; 4] = util::iter_into_array(lines_iterable)?; let lines: [TString; 4] = util::iter_into_array(lines_iterable)?;
let [l0, l1, l2, l3] = lines; let [l0, l1, l2, l3] = lines;
@ -1504,20 +1491,18 @@ extern "C" fn new_show_group_share_success(
extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?; let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?;
let title: Option<StrBuffer> = kwargs let title: Option<TString> = kwargs
.get(Qstr::MP_QSTR_title) .get(Qstr::MP_QSTR_title)
.and_then(Obj::try_into_option) .and_then(Obj::try_into_option)
.unwrap_or(None); .unwrap_or(None);
let mut progress = Progress::new(indeterminate, description.into()); let mut progress = Progress::new(indeterminate, description);
if let Some(title) = title { if let Some(title) = title {
progress = progress.with_title(title.into()); progress = progress.with_title(title);
}; };
// Description updates are received as &str and we need to provide a way to
// convert them to StrBuffer.
let obj = LayoutObj::new(progress)?; let obj = LayoutObj::new(progress)?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -1526,7 +1511,7 @@ extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_show_progress_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_progress_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?; let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?;
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?; let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
let skip_first_paint: bool = kwargs.get_or(Qstr::MP_QSTR_skip_first_paint, false)?; let skip_first_paint: bool = kwargs.get_or(Qstr::MP_QSTR_skip_first_paint, false)?;
@ -1549,23 +1534,19 @@ extern "C" fn new_show_progress_coinjoin(n_args: usize, args: *const Obj, kwargs
} }
extern "C" fn new_show_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let label: StrBuffer = kwargs let label: TString = kwargs
.get(Qstr::MP_QSTR_label)? .get(Qstr::MP_QSTR_label)?
.try_into_option()? .try_into_option()?
.unwrap_or_else(|| model::FULL_NAME.into()); .unwrap_or_else(|| model::FULL_NAME.into());
let notification: Option<StrBuffer> = let notification: Option<TString> =
kwargs.get(Qstr::MP_QSTR_notification)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_notification)?.try_into_option()?;
let notification_level: u8 = kwargs.get_or(Qstr::MP_QSTR_notification_level, 0)?; let notification_level: u8 = kwargs.get_or(Qstr::MP_QSTR_notification_level, 0)?;
let skip_first_paint: bool = kwargs.get(Qstr::MP_QSTR_skip_first_paint)?.try_into()?; let skip_first_paint: bool = kwargs.get(Qstr::MP_QSTR_skip_first_paint)?.try_into()?;
let hold: bool = kwargs.get(Qstr::MP_QSTR_hold)?.try_into()?; let hold: bool = kwargs.get(Qstr::MP_QSTR_hold)?.try_into()?;
let notification = notification.map(|w| (w.into(), notification_level)); let notification = notification.map(|w| (w, notification_level));
let loader_description = hold.then_some("Locking the device...".into()); let loader_description = hold.then_some("Locking the device...".into());
let obj = LayoutObj::new(Homescreen::new( let obj = LayoutObj::new(Homescreen::new(label, notification, loader_description))?;
label.into(),
notification,
loader_description,
))?;
if skip_first_paint { if skip_first_paint {
obj.skip_first_paint(); obj.skip_first_paint();
} }
@ -1576,7 +1557,7 @@ extern "C" fn new_show_homescreen(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let label: StrBuffer = kwargs let label: TString = kwargs
.get(Qstr::MP_QSTR_label)? .get(Qstr::MP_QSTR_label)?
.try_into_option()? .try_into_option()?
.unwrap_or_else(|| model::FULL_NAME.into()); .unwrap_or_else(|| model::FULL_NAME.into());
@ -1584,11 +1565,7 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut
let coinjoin_authorized: bool = kwargs.get_or(Qstr::MP_QSTR_coinjoin_authorized, false)?; let coinjoin_authorized: bool = kwargs.get_or(Qstr::MP_QSTR_coinjoin_authorized, false)?;
let skip_first_paint: bool = kwargs.get(Qstr::MP_QSTR_skip_first_paint)?.try_into()?; let skip_first_paint: bool = kwargs.get(Qstr::MP_QSTR_skip_first_paint)?.try_into()?;
let obj = LayoutObj::new(Lockscreen::new( let obj = LayoutObj::new(Lockscreen::new(label, bootscreen, coinjoin_authorized))?;
label.into(),
bootscreen,
coinjoin_authorized,
))?;
if skip_first_paint { if skip_first_paint {
obj.skip_first_paint(); obj.skip_first_paint();
} }
@ -1604,14 +1581,13 @@ extern "C" fn new_confirm_firmware_update(
) -> Obj { ) -> Obj {
use super::component::bl_confirm::Confirm; use super::component::bl_confirm::Confirm;
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let fingerprint: StrBuffer = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?; let fingerprint: TString = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?;
let title = TR::firmware_update__title; let title = TR::firmware_update__title;
let message = let message = Label::left_aligned(description, theme::TEXT_NORMAL).vertically_centered();
Label::left_aligned(description.into(), theme::TEXT_NORMAL).vertically_centered();
let fingerprint = Label::left_aligned( let fingerprint = Label::left_aligned(
fingerprint.into(), fingerprint,
theme::TEXT_NORMAL.with_line_breaking(LineBreaking::BreakWordsNoHyphen), theme::TEXT_NORMAL.with_line_breaking(LineBreaking::BreakWordsNoHyphen),
) )
.vertically_centered(); .vertically_centered();

View File

@ -2,8 +2,7 @@ use heapless::Vec;
use crate::{ use crate::{
error::Error, error::Error,
micropython::buffer::StrBuffer, strutil::TString,
strutil::StringType,
translations::TR, translations::TR,
ui::{ ui::{
component::{ component::{
@ -18,30 +17,24 @@ use super::{theme, Frame, FrameMsg};
const MAX_XPUBS: usize = 16; const MAX_XPUBS: usize = 16;
pub struct AddressDetails<T> { pub struct AddressDetails {
qr_code: Frame<Qr>, qr_code: Frame<Qr>,
details: Frame<Paragraphs<ParagraphVecShort<'static>>>, details: Frame<Paragraphs<ParagraphVecShort<'static>>>,
xpub_view: Frame<Paragraphs<Paragraph<'static>>>, xpub_view: Frame<Paragraphs<Paragraph<'static>>>,
xpubs: Vec<(T, T), MAX_XPUBS>, xpubs: Vec<(TString<'static>, TString<'static>), MAX_XPUBS>,
xpub_page_count: Vec<u8, MAX_XPUBS>, xpub_page_count: Vec<u8, MAX_XPUBS>,
current_page: usize, current_page: usize,
} }
impl<T> AddressDetails<T> impl AddressDetails {
where
T: StringType,
{
pub fn new( pub fn new(
qr_title: T, qr_title: TString<'static>,
qr_address: T, qr_address: TString<'static>,
case_sensitive: bool, case_sensitive: bool,
details_title: T, details_title: TString<'static>,
account: Option<StrBuffer>, account: Option<TString<'static>>,
path: Option<StrBuffer>, path: Option<TString<'static>>,
) -> Result<Self, Error> ) -> Result<Self, Error> {
where
T: From<&'static str>,
{
let mut para = ParagraphVecShort::new(); let mut para = ParagraphVecShort::new();
if let Some(a) = account { if let Some(a) = account {
para.add(Paragraph::new( para.add(Paragraph::new(
@ -60,14 +53,16 @@ where
let result = Self { let result = Self {
qr_code: Frame::left_aligned( qr_code: Frame::left_aligned(
theme::label_title(), theme::label_title(),
qr_title.into(), qr_title,
Qr::new(qr_address, case_sensitive)?.with_border(7), qr_address
.map(|s| Qr::new(s, case_sensitive))?
.with_border(7),
) )
.with_cancel_button() .with_cancel_button()
.with_border(theme::borders_horizontal_scroll()), .with_border(theme::borders_horizontal_scroll()),
details: Frame::left_aligned( details: Frame::left_aligned(
theme::label_title(), theme::label_title(),
details_title.into(), details_title,
para.into_paragraphs(), para.into_paragraphs(),
) )
.with_cancel_button() .with_cancel_button()
@ -86,24 +81,24 @@ where
Ok(result) Ok(result)
} }
pub fn add_xpub(&mut self, title: T, xpub: T) -> Result<(), Error> { pub fn add_xpub(
&mut self,
title: TString<'static>,
xpub: TString<'static>,
) -> Result<(), Error> {
self.xpubs self.xpubs
.push((title, xpub)) .push((title, xpub))
.map_err(|_| Error::OutOfRange) .map_err(|_| Error::OutOfRange)
} }
fn switch_xpub(&mut self, i: usize, page: usize) -> usize fn switch_xpub(&mut self, i: usize, page: usize) -> usize {
where
T: Clone,
{
// Context is needed for updating child so that it can request repaint. In this // Context is needed for updating child so that it can request repaint. In this
// case the parent component that handles paging always requests complete // case the parent component that handles paging always requests complete
// repaint after page change so we can use a dummy context here. // repaint after page change so we can use a dummy context here.
let mut dummy_ctx = EventCtx::new(); let mut dummy_ctx = EventCtx::new();
self.xpub_view self.xpub_view.update_title(&mut dummy_ctx, self.xpubs[i].0);
.update_title(&mut dummy_ctx, self.xpubs[i].0.clone().into());
self.xpub_view.update_content(&mut dummy_ctx, |p| { self.xpub_view.update_content(&mut dummy_ctx, |p| {
p.inner_mut().update(self.xpubs[i].1.clone()); p.inner_mut().update(self.xpubs[i].1);
let npages = p.page_count(); let npages = p.page_count();
p.change_page(page); p.change_page(page);
npages npages
@ -128,10 +123,7 @@ where
} }
} }
impl<T> Paginate for AddressDetails<T> impl Paginate for AddressDetails {
where
T: StringType + Clone,
{
fn page_count(&mut self) -> usize { fn page_count(&mut self) -> usize {
let total_xpub_pages: u8 = self.xpub_page_count.iter().copied().sum(); let total_xpub_pages: u8 = self.xpub_page_count.iter().copied().sum();
2usize.saturating_add(total_xpub_pages.into()) 2usize.saturating_add(total_xpub_pages.into())
@ -147,10 +139,7 @@ where
} }
} }
impl<T> Component for AddressDetails<T> impl Component for AddressDetails {
where
T: StringType + Clone,
{
type Msg = (); type Msg = ();
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
@ -198,10 +187,7 @@ where
} }
#[cfg(feature = "ui_debug")] #[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for AddressDetails<T> impl crate::trace::Trace for AddressDetails {
where
T: StringType,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) { fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.component("AddressDetails"); t.component("AddressDetails");
match self.current_page { match self.current_page {

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
error::Error, error::Error,
strutil::{self, StringType}, strutil::{self, TString},
translations::TR, translations::TR,
ui::{ ui::{
component::{ component::{
@ -21,9 +21,9 @@ pub enum NumberInputDialogMsg {
InfoRequested, InfoRequested,
} }
pub struct NumberInputDialog<T, F> pub struct NumberInputDialog<F>
where where
F: Fn(u32) -> T, F: Fn(u32) -> TString<'static>,
{ {
area: Rect, area: Rect,
description_func: F, description_func: F,
@ -34,10 +34,9 @@ where
confirm_button: Child<Button>, confirm_button: Child<Button>,
} }
impl<T, F> NumberInputDialog<T, F> impl<F> NumberInputDialog<F>
where where
F: Fn(u32) -> T, F: Fn(u32) -> TString<'static>,
T: StringType,
{ {
pub fn new(min: u32, max: u32, init_value: u32, description_func: F) -> Result<Self, Error> { pub fn new(min: u32, max: u32, init_value: u32, description_func: F) -> Result<Self, Error> {
let text = description_func(init_value); let text = description_func(init_value);
@ -71,10 +70,9 @@ where
} }
} }
impl<T, F> Component for NumberInputDialog<T, F> impl<F> Component for NumberInputDialog<F>
where where
T: StringType, F: Fn(u32) -> TString<'static>,
F: Fn(u32) -> T,
{ {
type Msg = NumberInputDialogMsg; type Msg = NumberInputDialogMsg;
@ -133,10 +131,9 @@ where
} }
#[cfg(feature = "ui_debug")] #[cfg(feature = "ui_debug")]
impl<T, F> crate::trace::Trace for NumberInputDialog<T, F> impl<F> crate::trace::Trace for NumberInputDialog<F>
where where
T: StringType, F: Fn(u32) -> TString<'static>,
F: Fn(u32) -> T,
{ {
fn trace(&self, t: &mut dyn crate::trace::Tracer) { fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.component("NumberInputDialog"); t.component("NumberInputDialog");

View File

@ -3,17 +3,10 @@ use core::{cmp::Ordering, convert::TryInto};
use crate::{ use crate::{
error::Error, error::Error,
micropython::{ micropython::{
buffer::{get_buffer, StrBuffer}, buffer::get_buffer, gc::Gc, iter::IterBuf, list::List, map::Map, module::Module, obj::Obj,
gc::Gc, qstr::Qstr, util,
iter::IterBuf,
list::List,
map::Map,
module::Module,
obj::Obj,
qstr::Qstr,
util,
}, },
strutil::{StringType, TString}, strutil::TString,
translations::TR, translations::TR,
trezorhal::model, trezorhal::model,
ui::{ ui::{
@ -239,10 +232,9 @@ where
} }
} }
impl<T, F> ComponentMsgObj for NumberInputDialog<T, F> impl<F> ComponentMsgObj for NumberInputDialog<F>
where where
T: StringType, F: Fn(u32) -> TString<'static>,
F: Fn(u32) -> T,
{ {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
let value = self.value().try_into()?; let value = self.value().try_into()?;
@ -323,10 +315,7 @@ where
} }
} }
impl<T> ComponentMsgObj for AddressDetails<T> impl ComponentMsgObj for AddressDetails {
where
T: StringType + Clone,
{
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> { fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
Ok(CANCELLED.as_obj()) Ok(CANCELLED.as_obj())
} }
@ -352,15 +341,15 @@ impl ComponentMsgObj for super::component::bl_confirm::Confirm<'_> {
extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let action: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?; let action: Option<TString> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
let description: Option<StrBuffer> = let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let verb: Option<StrBuffer> = kwargs let verb: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb) .get(Qstr::MP_QSTR_verb)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
let verb_cancel: Option<StrBuffer> = kwargs let verb_cancel: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb_cancel) .get(Qstr::MP_QSTR_verb_cancel)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
@ -369,8 +358,8 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
let hold_danger: bool = kwargs.get_or(Qstr::MP_QSTR_hold_danger, false)?; let hold_danger: bool = kwargs.get_or(Qstr::MP_QSTR_hold_danger, false)?;
let paragraphs = { let paragraphs = {
let action = action.unwrap_or_default(); let action = action.unwrap_or("".into());
let description = description.unwrap_or_default(); let description = description.unwrap_or("".into());
let mut paragraphs = ParagraphVecShort::new(); let mut paragraphs = ParagraphVecShort::new();
if !reverse { if !reverse {
paragraphs paragraphs
@ -387,17 +376,12 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
let mut page = if hold { let mut page = if hold {
ButtonPage::new(paragraphs, theme::BG).with_hold()? ButtonPage::new(paragraphs, theme::BG).with_hold()?
} else { } else {
ButtonPage::new(paragraphs, theme::BG) ButtonPage::new(paragraphs, theme::BG).with_cancel_confirm(verb_cancel, verb)
.with_cancel_confirm(verb_cancel.map(|c| c.into()), verb.map(|c| c.into()))
}; };
if hold && hold_danger { if hold && hold_danger {
page = page.with_confirm_style(theme::button_danger()) page = page.with_confirm_style(theme::button_danger())
} }
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(theme::label_title(), title, page))?;
theme::label_title(),
title.into(),
page,
))?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -405,8 +389,8 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let verb: Option<StrBuffer> = kwargs let verb: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb) .get(Qstr::MP_QSTR_verb)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
@ -415,10 +399,10 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m
let mut ops = OpTextLayout::new(theme::TEXT_NORMAL); let mut ops = OpTextLayout::new(theme::TEXT_NORMAL);
for item in IterBuf::new().try_iterate(items)? { for item in IterBuf::new().try_iterate(items)? {
if item.is_str() { if item.is_str() {
ops = ops.text_normal(StrBuffer::try_from(item)?) ops = ops.text_normal(TString::try_from(item)?)
} else { } else {
let [emphasis, text]: [Obj; 2] = util::iter_into_array(item)?; let [emphasis, text]: [Obj; 2] = util::iter_into_array(item)?;
let text: StrBuffer = text.try_into()?; let text: TString = text.try_into()?;
if emphasis.try_into()? { if emphasis.try_into()? {
ops = ops.text_demibold(text); ops = ops.text_demibold(text);
} else { } else {
@ -429,9 +413,9 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
ButtonPage::new(FormattedText::new(ops).vertically_centered(), theme::BG) ButtonPage::new(FormattedText::new(ops).vertically_centered(), theme::BG)
.with_cancel_confirm(None, verb.map(|v| v.into())), .with_cancel_confirm(None, verb),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -439,13 +423,13 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m
} }
struct ConfirmBlobParams { struct ConfirmBlobParams {
title: StrBuffer, title: TString<'static>,
subtitle: Option<StrBuffer>, subtitle: Option<TString<'static>>,
data: Obj, data: Obj,
description: Option<StrBuffer>, description: Option<TString<'static>>,
extra: Option<StrBuffer>, extra: Option<TString<'static>>,
verb: Option<StrBuffer>, verb: Option<TString<'static>>,
verb_cancel: Option<StrBuffer>, verb_cancel: Option<TString<'static>>,
info_button: bool, info_button: bool,
hold: bool, hold: bool,
chunkify: bool, chunkify: bool,
@ -454,11 +438,11 @@ struct ConfirmBlobParams {
impl ConfirmBlobParams { impl ConfirmBlobParams {
fn new( fn new(
title: StrBuffer, title: TString<'static>,
data: Obj, data: Obj,
description: Option<StrBuffer>, description: Option<TString<'static>>,
verb: Option<StrBuffer>, verb: Option<TString<'static>>,
verb_cancel: Option<StrBuffer>, verb_cancel: Option<TString<'static>>,
hold: bool, hold: bool,
) -> Self { ) -> Self {
Self { Self {
@ -476,12 +460,12 @@ impl ConfirmBlobParams {
} }
} }
fn with_extra(mut self, extra: Option<StrBuffer>) -> Self { fn with_extra(mut self, extra: Option<TString<'static>>) -> Self {
self.extra = extra; self.extra = extra;
self self
} }
fn with_subtitle(mut self, subtitle: Option<StrBuffer>) -> Self { fn with_subtitle(mut self, subtitle: Option<TString<'static>>) -> Self {
self.subtitle = subtitle; self.subtitle = subtitle;
self self
} }
@ -503,13 +487,13 @@ impl ConfirmBlobParams {
fn into_layout(self) -> Result<Obj, Error> { fn into_layout(self) -> Result<Obj, Error> {
let paragraphs = ConfirmBlob { let paragraphs = ConfirmBlob {
description: self.description.unwrap_or_else(StrBuffer::empty), description: self.description.unwrap_or("".into()),
extra: self.extra.unwrap_or_else(StrBuffer::empty), extra: self.extra.unwrap_or("".into()),
data: self.data.try_into()?, data: self.data.try_into()?,
description_font: &theme::TEXT_NORMAL, description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD, extra_font: &theme::TEXT_DEMIBOLD,
data_font: if self.chunkify { data_font: if self.chunkify {
let data: StrBuffer = self.data.try_into()?; let data: TString = self.data.try_into()?;
theme::get_chunkified_text_style(data.len()) theme::get_chunkified_text_style(data.len())
} else if self.text_mono { } else if self.text_mono {
&theme::TEXT_MONO &theme::TEXT_MONO
@ -521,14 +505,14 @@ impl ConfirmBlobParams {
let mut page = ButtonPage::new(paragraphs, theme::BG); let mut page = ButtonPage::new(paragraphs, theme::BG);
if let Some(verb) = self.verb { if let Some(verb) = self.verb {
page = page.with_cancel_confirm(self.verb_cancel.map(|v| v.into()), Some(verb.into())) page = page.with_cancel_confirm(self.verb_cancel, Some(verb))
} }
if self.hold { if self.hold {
page = page.with_hold()? page = page.with_hold()?
} }
let mut frame = Frame::left_aligned(theme::label_title(), self.title.into(), page); let mut frame = Frame::left_aligned(theme::label_title(), self.title, page);
if let Some(subtitle) = self.subtitle { if let Some(subtitle) = self.subtitle {
frame = frame.with_subtitle(theme::label_subtitle(), subtitle.into()); frame = frame.with_subtitle(theme::label_subtitle(), subtitle);
} }
if self.info_button { if self.info_button {
frame = frame.with_info_button(); frame = frame.with_info_button();
@ -540,16 +524,16 @@ impl ConfirmBlobParams {
extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?;
let description: Option<StrBuffer> = let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let extra: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?; let extra: Option<TString> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
let verb: Option<StrBuffer> = kwargs let verb: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb) .get(Qstr::MP_QSTR_verb)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
let verb_cancel: Option<StrBuffer> = kwargs let verb_cancel: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb_cancel) .get(Qstr::MP_QSTR_verb_cancel)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
@ -566,25 +550,24 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: Option<StrBuffer> = let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let verb: StrBuffer = let verb: TString = kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.try_into()?)?;
kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.try_into()?)?; let extra: Option<TString> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
let extra: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
let data_style = if chunkify { let data_style = if chunkify {
let address: StrBuffer = data.try_into()?; let address: TString = data.try_into()?;
theme::get_chunkified_text_style(address.len()) theme::get_chunkified_text_style(address.len())
} else { } else {
&theme::TEXT_MONO &theme::TEXT_MONO
}; };
let paragraphs = ConfirmBlob { let paragraphs = ConfirmBlob {
description: description.unwrap_or_else(StrBuffer::empty), description: description.unwrap_or("".into()),
extra: extra.unwrap_or_else(StrBuffer::empty), extra: extra.unwrap_or("".into()),
data: data.try_into()?, data: data.try_into()?,
description_font: &theme::TEXT_NORMAL, description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD, extra_font: &theme::TEXT_DEMIBOLD,
@ -595,10 +578,10 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::left_aligned( Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
ButtonPage::new(paragraphs, theme::BG) ButtonPage::new(paragraphs, theme::BG)
.with_swipe_left() .with_swipe_left()
.with_cancel_confirm(None, Some(verb.into())), .with_cancel_confirm(None, Some(verb)),
) )
.with_info_button(), .with_info_button(),
)?; )?;
@ -609,7 +592,7 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
@ -625,11 +608,7 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
ButtonPage::new(paragraphs.into_paragraphs(), theme::BG) ButtonPage::new(paragraphs.into_paragraphs(), theme::BG)
.with_cancel_confirm(None, Some(TR::buttons__confirm.into())) .with_cancel_confirm(None, Some(TR::buttons__confirm.into()))
}; };
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(theme::label_title(), title, page))?;
theme::label_title(),
title.into(),
page,
))?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -637,7 +616,7 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?; let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?;
// Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8] // Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8]
@ -663,7 +642,7 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
let buttons = Button::cancel_confirm_text(None, Some(TR::buttons__change.into())); let buttons = Button::cancel_confirm_text(None, Some(TR::buttons__change.into()));
let obj = LayoutObj::new(Frame::centered( let obj = LayoutObj::new(Frame::centered(
theme::label_title(), theme::label_title(),
title.into(), title,
Dialog::new(painter::jpeg_painter(buffer_func, size, 1), buttons), Dialog::new(painter::jpeg_painter(buffer_func, size, 1), buttons),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -674,8 +653,8 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let par_array: [Paragraph<'static>; 3] = [ let par_array: [Paragraph<'static>; 3] = [
Paragraph::new(&theme::TEXT_NORMAL, TR::reset__by_continuing).with_bottom_padding(17), /* simulating a carriage return */ Paragraph::new(&theme::TEXT_NORMAL, TR::reset__by_continuing).with_bottom_padding(17), /* simulating a carriage return */
@ -685,12 +664,12 @@ extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs:
let paragraphs = Paragraphs::new(par_array); let paragraphs = Paragraphs::new(par_array);
let buttons = Button::cancel_confirm( let buttons = Button::cancel_confirm(
Button::with_icon(theme::ICON_CANCEL), Button::with_icon(theme::ICON_CANCEL),
Button::with_text(button.into()).styled(theme::button_confirm()), Button::with_text(button).styled(theme::button_confirm()),
true, true,
); );
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
Dialog::new(paragraphs, buttons), Dialog::new(paragraphs, buttons),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -700,12 +679,12 @@ extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let qr_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_qr_title)?.try_into()?; let qr_title: TString<'static> = kwargs.get(Qstr::MP_QSTR_qr_title)?.try_into()?;
let details_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_details_title)?.try_into()?; let details_title: TString = kwargs.get(Qstr::MP_QSTR_details_title)?.try_into()?;
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?; let address: TString = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?;
let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?; let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?;
let account: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?; let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
let path: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?; let path: Option<TString> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?;
let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?; let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?;
@ -719,7 +698,7 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
)?; )?;
for i in IterBuf::new().try_iterate(xpubs)? { for i in IterBuf::new().try_iterate(xpubs)? {
let [xtitle, text]: [StrBuffer; 2] = util::iter_into_array(i)?; let [xtitle, text]: [TString; 2] = util::iter_into_array(i)?;
ad.add_xpub(xtitle, text)?; ad.add_xpub(xtitle, text)?;
} }
@ -732,7 +711,7 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
let horizontal: bool = kwargs.get_or(Qstr::MP_QSTR_horizontal, false)?; let horizontal: bool = kwargs.get_or(Qstr::MP_QSTR_horizontal, false)?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
@ -741,8 +720,8 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs:
for para in IterBuf::new().try_iterate(items)? { for para in IterBuf::new().try_iterate(items)? {
let [key, value]: [Obj; 2] = util::iter_into_array(para)?; let [key, value]: [Obj; 2] = util::iter_into_array(para)?;
let key: StrBuffer = key.try_into()?; let key: TString = key.try_into()?;
let value: StrBuffer = value.try_into()?; let value: TString = value.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key).no_break()); paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key).no_break());
if chunkify { if chunkify {
paragraphs.add(Paragraph::new( paragraphs.add(Paragraph::new(
@ -762,7 +741,7 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs:
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::left_aligned( Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
SimplePage::new(paragraphs.into_paragraphs(), axis, theme::BG) SimplePage::new(paragraphs.into_paragraphs(), axis, theme::BG)
.with_swipe_right_to_go_back(), .with_swipe_right_to_go_back(),
) )
@ -775,18 +754,18 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let subtitle: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?; let subtitle: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?;
let description: Option<StrBuffer> = let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?; let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
let verb: Option<StrBuffer> = kwargs let verb: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb) .get(Qstr::MP_QSTR_verb)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
let verb_cancel: Option<StrBuffer> = kwargs let verb_cancel: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb_cancel) .get(Qstr::MP_QSTR_verb_cancel)
.unwrap_or_else(|_| Obj::const_none()) .unwrap_or_else(|_| Obj::const_none())
.try_into_option()?; .try_into_option()?;
@ -806,7 +785,7 @@ extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
let cancel_arrow: bool = kwargs.get_or(Qstr::MP_QSTR_cancel_arrow, false)?; let cancel_arrow: bool = kwargs.get_or(Qstr::MP_QSTR_cancel_arrow, false)?;
@ -814,7 +793,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
let mut paragraphs = ParagraphVecShort::new(); let mut paragraphs = ParagraphVecShort::new();
for pair in IterBuf::new().try_iterate(items)? { for pair in IterBuf::new().try_iterate(items)? {
let [label, value]: [StrBuffer; 2] = util::iter_into_array(pair)?; let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, label).no_break()); paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, label).no_break());
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value)); paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value));
} }
@ -825,7 +804,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
if info_button { if info_button {
page = page.with_swipe_left(); page = page.with_swipe_left();
} }
let mut frame = Frame::left_aligned(theme::label_title(), title.into(), page); let mut frame = Frame::left_aligned(theme::label_title(), title, page);
if info_button { if info_button {
frame = frame.with_info_button(); frame = frame.with_info_button();
} }
@ -838,8 +817,8 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?; let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?;
let amount_change: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_change)?.try_into()?; let amount_change: TString = kwargs.get(Qstr::MP_QSTR_amount_change)?.try_into()?;
let amount_new: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_new)?.try_into()?; let amount_new: TString = kwargs.get(Qstr::MP_QSTR_amount_new)?.try_into()?;
let description = if sign < 0 { let description = if sign < 0 {
TR::modify_amount__decrease_amount TR::modify_amount__decrease_amount
@ -867,10 +846,10 @@ extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?; let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?;
let user_fee_change: StrBuffer = kwargs.get(Qstr::MP_QSTR_user_fee_change)?.try_into()?; let user_fee_change: TString = kwargs.get(Qstr::MP_QSTR_user_fee_change)?.try_into()?;
let total_fee_new: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_fee_new)?.try_into()?; let total_fee_new: TString = kwargs.get(Qstr::MP_QSTR_total_fee_new)?.try_into()?;
let (description, change, total_label) = match sign { let (description, change, total_label) = match sign {
s if s < 0 => ( s if s < 0 => (
@ -885,7 +864,7 @@ extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *m
), ),
_ => ( _ => (
TR::modify_fee__no_change, TR::modify_fee__no_change,
StrBuffer::empty(), "".into(),
TR::modify_fee__transaction_fee, TR::modify_fee__transaction_fee,
), ),
}; };
@ -900,7 +879,7 @@ extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *m
let obj = LayoutObj::new( let obj = LayoutObj::new(
Frame::left_aligned( Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
ButtonPage::new(paragraphs, theme::BG) ButtonPage::new(paragraphs, theme::BG)
.with_hold()? .with_hold()?
.with_swipe_left(), .with_swipe_left(),
@ -917,15 +896,14 @@ fn new_show_modal(
icon: BlendedImage, icon: BlendedImage,
button_style: ButtonStyleSheet, button_style: ButtonStyleSheet,
) -> Result<Obj, Error> { ) -> Result<Obj, Error> {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let value: StrBuffer = kwargs.get_or(Qstr::MP_QSTR_value, StrBuffer::empty())?; let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
let description: StrBuffer = kwargs.get_or(Qstr::MP_QSTR_description, StrBuffer::empty())?; let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
let button: StrBuffer = let button: TString = kwargs.get_or(Qstr::MP_QSTR_button, TR::buttons__continue.try_into()?)?;
kwargs.get_or(Qstr::MP_QSTR_button, TR::buttons__continue.try_into()?)?;
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?; let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?;
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?; let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
let no_buttons = button.as_ref().is_empty(); let no_buttons = button.is_empty();
let obj = if no_buttons && time_ms == 0 { let obj = if no_buttons && time_ms == 0 {
// No buttons and no timer, used when we only want to draw the dialog once and // No buttons and no timer, used when we only want to draw the dialog once and
// then throw away the layout object. // then throw away the layout object.
@ -955,7 +933,7 @@ fn new_show_modal(
title, title,
Button::cancel_confirm( Button::cancel_confirm(
Button::with_icon(theme::ICON_CANCEL), Button::with_icon(theme::ICON_CANCEL),
Button::with_text(button.into()).styled(button_style), Button::with_text(button).styled(button_style),
false, false,
), ),
) )
@ -969,9 +947,9 @@ fn new_show_modal(
IconDialog::new( IconDialog::new(
icon, icon,
title, title,
theme::button_bar(Button::with_text(button.into()).styled(button_style).map( theme::button_bar(Button::with_text(button).styled(button_style).map(|msg| {
|msg| (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed), (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
)), })),
) )
.with_value(value) .with_value(value)
.with_description(description), .with_description(description),
@ -998,8 +976,8 @@ extern "C" fn new_show_error(n_args: usize, args: *const Obj, kwargs: *mut Map)
extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let app_name: StrBuffer = kwargs.get(Qstr::MP_QSTR_app_name)?.try_into()?; let app_name: TString = kwargs.get(Qstr::MP_QSTR_app_name)?.try_into()?;
let icon: Option<TString> = kwargs.get(Qstr::MP_QSTR_icon_name)?.try_into_option()?; let icon: Option<TString> = kwargs.get(Qstr::MP_QSTR_icon_name)?.try_into_option()?;
let accounts: Gc<List> = kwargs.get(Qstr::MP_QSTR_accounts)?.try_into()?; let accounts: Gc<List> = kwargs.get(Qstr::MP_QSTR_accounts)?.try_into()?;
@ -1019,13 +997,9 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
true, true,
); );
let fido_page = FidoConfirm::new(app_name.into(), get_page, page_count, icon, controls); let fido_page = FidoConfirm::new(app_name, get_page, page_count, icon, controls);
let obj = LayoutObj::new(Frame::centered( let obj = LayoutObj::new(Frame::centered(theme::label_title(), title, fido_page))?;
theme::label_title(),
title.into(),
fido_page,
))?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1075,10 +1049,10 @@ extern "C" fn new_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -
extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = TR::addr_mismatch__contact_support_at.try_into()?; let description: TString = TR::addr_mismatch__contact_support_at.try_into()?;
let url: StrBuffer = TR::addr_mismatch__support_url.try_into()?; let url: TString = TR::addr_mismatch__support_url.try_into()?;
let button: StrBuffer = TR::buttons__quit.try_into()?; let button: TString = TR::buttons__quit.try_into()?;
let icon = BlendedImage::new( let icon = BlendedImage::new(
theme::IMAGE_BG_OCTAGON, theme::IMAGE_BG_OCTAGON,
@ -1093,7 +1067,7 @@ extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Ma
title, title,
Button::cancel_confirm( Button::cancel_confirm(
Button::with_icon(theme::ICON_BACK), Button::with_icon(theme::ICON_BACK),
Button::with_text(button.into()).styled(theme::button_reset()), Button::with_text(button).styled(theme::button_reset()),
true, true,
), ),
) )
@ -1115,18 +1089,17 @@ extern "C" fn new_show_mismatch(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?; let title: Option<TString> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?;
let description: StrBuffer = let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
kwargs.get_or(Qstr::MP_QSTR_description, StrBuffer::empty())?; let button: TString = kwargs.get_or(Qstr::MP_QSTR_button, "".into())?;
let button: StrBuffer = kwargs.get_or(Qstr::MP_QSTR_button, StrBuffer::empty())?;
let obj = if let Some(t) = title { let obj = if let Some(t) = title {
LayoutObj::new(Frame::left_aligned( LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
t.into(), t,
Dialog::new( Dialog::new(
Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]), Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]),
theme::button_bar(Button::with_text(button.into()).map(|msg| { theme::button_bar(Button::with_text(button).map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed) (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
})), })),
), ),
@ -1137,7 +1110,7 @@ extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map)
theme::borders(), theme::borders(),
Dialog::new( Dialog::new(
Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]), Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]),
theme::button_bar(Button::with_text(button.into()).map(|msg| { theme::button_bar(Button::with_text(button).map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed) (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
})), })),
), ),
@ -1163,9 +1136,9 @@ extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map)
extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let info_button: StrBuffer = kwargs.get(Qstr::MP_QSTR_info_button)?.try_into()?; let info_button: TString = kwargs.get(Qstr::MP_QSTR_info_button)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
let mut paragraphs = ParagraphVecShort::new(); let mut paragraphs = ParagraphVecShort::new();
@ -1173,18 +1146,18 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
for para in IterBuf::new().try_iterate(items)? { for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = util::iter_into_array(para)?; let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?); let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: TString = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
if paragraphs.is_full() { if paragraphs.is_full() {
break; break;
} }
} }
let buttons = Button::cancel_info_confirm(button.into(), info_button.into()); let buttons = Button::cancel_info_confirm(button, info_button);
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
Dialog::new(paragraphs.into_paragraphs(), buttons), Dialog::new(paragraphs.into_paragraphs(), buttons),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -1194,8 +1167,8 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
let mut paragraphs = ParagraphVecLong::new(); let mut paragraphs = ParagraphVecLong::new();
@ -1203,15 +1176,15 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
for para in IterBuf::new().try_iterate(items)? { for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = util::iter_into_array(para)?; let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?); let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: TString = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
} }
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
ButtonPage::new(paragraphs.into_paragraphs(), theme::BG) ButtonPage::new(paragraphs.into_paragraphs(), theme::BG)
.with_cancel_confirm(None, Some(button.into())) .with_cancel_confirm(None, Some(button))
.with_confirm_style(theme::button_default()) .with_confirm_style(theme::button_default())
.with_back_button(), .with_back_button(),
))?; ))?;
@ -1222,8 +1195,8 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let max_rounds: StrBuffer = kwargs.get(Qstr::MP_QSTR_max_rounds)?.try_into()?; let max_rounds: TString = kwargs.get(Qstr::MP_QSTR_max_rounds)?.try_into()?;
let max_feerate: StrBuffer = kwargs.get(Qstr::MP_QSTR_max_feerate)?.try_into()?; let max_feerate: TString = kwargs.get(Qstr::MP_QSTR_max_feerate)?.try_into()?;
let paragraphs = Paragraphs::new([ let paragraphs = Paragraphs::new([
Paragraph::new(&theme::TEXT_NORMAL, TR::coinjoin__max_rounds), Paragraph::new(&theme::TEXT_NORMAL, TR::coinjoin__max_rounds),
@ -1244,8 +1217,8 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let subprompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?; let subprompt: TString = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?;
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?; let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?;
let warning: bool = kwargs.get_or(Qstr::MP_QSTR_wrong_pin, false)?; let warning: bool = kwargs.get_or(Qstr::MP_QSTR_wrong_pin, false)?;
let warning = if warning { let warning = if warning {
@ -1253,12 +1226,7 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
} else { } else {
None None
}; };
let obj = LayoutObj::new(PinKeyboard::new( let obj = LayoutObj::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel))?;
prompt.into(),
subprompt.into(),
warning,
allow_cancel,
))?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1266,7 +1234,7 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let _prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let _max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?; let _max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?;
let obj = LayoutObj::new(PassphraseKeyboard::new())?; let obj = LayoutObj::new(PassphraseKeyboard::new())?;
Ok(obj.into()) Ok(obj.into())
@ -1276,12 +1244,12 @@ extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let prefill_word: StrBuffer = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?;
let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?;
let obj = LayoutObj::new(MnemonicKeyboard::new( let obj = LayoutObj::new(MnemonicKeyboard::new(
Bip39Input::prefilled_word(prefill_word.as_ref()), prefill_word.map(Bip39Input::prefilled_word),
prompt.into(), prompt,
can_go_back, can_go_back,
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -1291,12 +1259,12 @@ extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
let prefill_word: StrBuffer = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?;
let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?;
let obj = LayoutObj::new(MnemonicKeyboard::new( let obj = LayoutObj::new(MnemonicKeyboard::new(
Slip39Input::prefilled_word(prefill_word.as_ref()), prefill_word.map(Slip39Input::prefilled_word),
prompt.into(), prompt,
can_go_back, can_go_back,
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -1306,15 +1274,15 @@ extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let words_iterable: Obj = kwargs.get(Qstr::MP_QSTR_words)?; let words_iterable: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
let words: [TString<'static>; 3] = util::iter_into_array(words_iterable)?; let words: [TString<'static>; 3] = util::iter_into_array(words_iterable)?;
let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_DEMIBOLD, description)]); let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_DEMIBOLD, description)]);
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
Dialog::new(paragraphs, Button::select_word(words)), Dialog::new(paragraphs, Button::select_word(words)),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -1324,18 +1292,18 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let pages: Obj = kwargs.get(Qstr::MP_QSTR_pages)?; let pages: Obj = kwargs.get(Qstr::MP_QSTR_pages)?;
let mut paragraphs = ParagraphVecLong::new(); let mut paragraphs = ParagraphVecLong::new();
for page in IterBuf::new().try_iterate(pages)? { for page in IterBuf::new().try_iterate(pages)? {
let text: StrBuffer = page.try_into()?; let text: TString = page.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, text).break_after()); paragraphs.add(Paragraph::new(&theme::TEXT_MONO, text).break_after());
} }
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
ButtonPage::new(paragraphs.into_paragraphs(), theme::BG) ButtonPage::new(paragraphs.into_paragraphs(), theme::BG)
.with_hold()? .with_hold()?
.without_cancel(), .without_cancel(),
@ -1347,7 +1315,7 @@ extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let min_count: u32 = kwargs.get(Qstr::MP_QSTR_min_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 max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?;
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?; let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
@ -1355,7 +1323,7 @@ extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut M
assert!(description_callback != Obj::const_none()); assert!(description_callback != Obj::const_none());
let callback = move |i: u32| { let callback = move |i: u32| {
StrBuffer::try_from( TString::try_from(
description_callback description_callback
.call_with_n_args(&[i.try_into().unwrap()]) .call_with_n_args(&[i.try_into().unwrap()])
.unwrap(), .unwrap(),
@ -1365,7 +1333,7 @@ extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut M
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
NumberInputDialog::new(min_count, max_count, count, callback)?, NumberInputDialog::new(min_count, max_count, count, callback)?,
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -1375,8 +1343,8 @@ extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let active: usize = kwargs.get(Qstr::MP_QSTR_active)?.try_into()?; let active: usize = kwargs.get(Qstr::MP_QSTR_active)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
@ -1387,13 +1355,13 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
Ordering::Equal => &theme::TEXT_CHECKLIST_SELECTED, Ordering::Equal => &theme::TEXT_CHECKLIST_SELECTED,
Ordering::Greater => &theme::TEXT_CHECKLIST_DEFAULT, Ordering::Greater => &theme::TEXT_CHECKLIST_DEFAULT,
}; };
let text: StrBuffer = item.try_into()?; let text: TString = item.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
} }
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
Dialog::new( Dialog::new(
Checklist::from_paragraphs( Checklist::from_paragraphs(
theme::ICON_LIST_CURRENT, theme::ICON_LIST_CURRENT,
@ -1406,7 +1374,7 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
.with_check_width(theme::CHECKLIST_CHECK_WIDTH) .with_check_width(theme::CHECKLIST_CHECK_WIDTH)
.with_current_offset(theme::CHECKLIST_CURRENT_OFFSET) .with_current_offset(theme::CHECKLIST_CURRENT_OFFSET)
.with_done_offset(theme::CHECKLIST_DONE_OFFSET), .with_done_offset(theme::CHECKLIST_DONE_OFFSET),
theme::button_bar(Button::with_text(button.into()).map(|msg| { theme::button_bar(Button::with_text(button).map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed) (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
})), })),
), ),
@ -1418,9 +1386,9 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
@ -1430,7 +1398,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
]) ])
.with_spacing(theme::RECOVERY_SPACING); .with_spacing(theme::RECOVERY_SPACING);
let notification: StrBuffer = if dry_run { let notification: TString = if dry_run {
TR::recovery__title_dry_run.try_into()? TR::recovery__title_dry_run.try_into()?
} else { } else {
TR::recovery__title.try_into()? TR::recovery__title.try_into()?
@ -1439,7 +1407,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let obj = if info_button { let obj = if info_button {
LayoutObj::new(Frame::left_aligned( LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
notification.into(), notification,
Dialog::new( Dialog::new(
paragraphs, paragraphs,
Button::cancel_info_confirm( Button::cancel_info_confirm(
@ -1451,11 +1419,8 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
} else { } else {
LayoutObj::new(Frame::left_aligned( LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
notification.into(), notification,
Dialog::new( Dialog::new(paragraphs, Button::cancel_confirm_text(None, Some(button))),
paragraphs,
Button::cancel_confirm_text(None, Some(button.into())),
),
))? ))?
}; };
Ok(obj.into()) Ok(obj.into())
@ -1466,7 +1431,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
let title: StrBuffer = if dry_run { let title: TString = if dry_run {
TR::recovery__title_dry_run.try_into()? TR::recovery__title_dry_run.try_into()?
} else { } else {
TR::recovery__title.try_into()? TR::recovery__title.try_into()?
@ -1479,7 +1444,7 @@ extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mu
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
theme::label_title(), theme::label_title(),
title.into(), title,
Dialog::new(paragraphs, SelectWordCount::new()), Dialog::new(paragraphs, SelectWordCount::new()),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
@ -1494,7 +1459,7 @@ extern "C" fn new_show_group_share_success(
) -> Obj { ) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?; let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?;
let lines: [StrBuffer; 4] = util::iter_into_array(lines_iterable)?; let lines: [TString; 4] = util::iter_into_array(lines_iterable)?;
let obj = LayoutObj::new(IconDialog::new_shares( let obj = LayoutObj::new(IconDialog::new_shares(
lines, lines,
@ -1513,7 +1478,7 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:
let mut paragraphs = ParagraphVecLong::new(); let mut paragraphs = ParagraphVecLong::new();
for page in IterBuf::new().try_iterate(pages_iterable)? { for page in IterBuf::new().try_iterate(pages_iterable)? {
let [title, description]: [StrBuffer; 2] = util::iter_into_array(page)?; let [title, description]: [TString; 2] = util::iter_into_array(page)?;
paragraphs paragraphs
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, title)) .add(Paragraph::new(&theme::TEXT_DEMIBOLD, title))
.add(Paragraph::new(&theme::TEXT_NORMAL, description).break_after()); .add(Paragraph::new(&theme::TEXT_NORMAL, description).break_after());
@ -1534,9 +1499,9 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:
extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?; let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?;
let title: Option<StrBuffer> = kwargs let title: Option<TString> = kwargs
.get(Qstr::MP_QSTR_title) .get(Qstr::MP_QSTR_title)
.and_then(Obj::try_into_option) .and_then(Obj::try_into_option)
.unwrap_or(None); .unwrap_or(None);
@ -1544,16 +1509,10 @@ extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Ma
let (title, description) = if let Some(title) = title { let (title, description) = if let Some(title) = title {
(title, description) (title, description)
} else { } else {
(description, StrBuffer::empty()) (description, "".into())
}; };
// Description updates are received as &str and we need to provide a way to let obj = LayoutObj::new(Progress::new(title, indeterminate, description))?;
// convert them to StrBuffer.
let obj = LayoutObj::new(Progress::new(
title.into(),
indeterminate,
description.into(),
))?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1561,14 +1520,14 @@ extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Ma
extern "C" fn new_show_progress_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_progress_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?; let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?;
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?; let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
let skip_first_paint: bool = kwargs.get_or(Qstr::MP_QSTR_skip_first_paint, false)?; let skip_first_paint: bool = kwargs.get_or(Qstr::MP_QSTR_skip_first_paint, false)?;
// The second type parameter is actually not used in `new()` but we need to // The second type parameter is actually not used in `new()` but we need to
// provide it. // provide it.
let progress = CoinJoinProgress::<Never>::new(title.into(), indeterminate)?; let progress = CoinJoinProgress::<Never>::new(title, indeterminate)?;
let obj = if time_ms > 0 && indeterminate { let obj = if time_ms > 0 && indeterminate {
let timeout = Timeout::new(time_ms); let timeout = Timeout::new(time_ms);
LayoutObj::new((timeout, progress.map(|_msg| None)))? LayoutObj::new((timeout, progress.map(|_msg| None)))?
@ -1642,12 +1601,12 @@ extern "C" fn new_confirm_firmware_update(
) -> Obj { ) -> Obj {
use super::component::bl_confirm::{Confirm, ConfirmTitle}; use super::component::bl_confirm::{Confirm, ConfirmTitle};
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let fingerprint: StrBuffer = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?; let fingerprint: TString = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?;
let title_str = TR::firmware_update__title.into(); let title_str = TR::firmware_update__title.into();
let title = Label::left_aligned(title_str, theme::TEXT_BOLD).vertically_centered(); let title = Label::left_aligned(title_str, theme::TEXT_BOLD).vertically_centered();
let msg = Label::left_aligned(description.into(), theme::TEXT_NORMAL); let msg = Label::left_aligned(description, theme::TEXT_NORMAL);
let left = Button::with_text(TR::buttons__cancel.into()).styled(theme::button_default()); let left = Button::with_text(TR::buttons__cancel.into()).styled(theme::button_default());
let right = Button::with_text(TR::buttons__install.into()).styled(theme::button_confirm()); let right = Button::with_text(TR::buttons__install.into()).styled(theme::button_confirm());
@ -1655,7 +1614,7 @@ extern "C" fn new_confirm_firmware_update(
let obj = LayoutObj::new( let obj = LayoutObj::new(
Confirm::new(theme::BG, left, right, ConfirmTitle::Text(title), msg).with_info( Confirm::new(theme::BG, left, right, ConfirmTitle::Text(title), msg).with_info(
TR::firmware_update__title_fingerprint.into(), TR::firmware_update__title_fingerprint.into(),
fingerprint.into(), fingerprint,
theme::button_moreinfo(), theme::button_moreinfo(),
), ),
)?; )?;