mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-03 12:00:59 +00:00
chore(core/rust): tracing and other smaller improvements/clippy lints
This commit is contained in:
parent
eee4c624f9
commit
73c493d118
@ -2,6 +2,8 @@
|
|||||||
#![deny(clippy::all)]
|
#![deny(clippy::all)]
|
||||||
#![allow(clippy::new_without_default)]
|
#![allow(clippy::new_without_default)]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
// Allowing dead code not to cause a lot of warnings when building for a specific target
|
||||||
|
// (when building for TR, a lot of code only used in TT would get marked as unused).
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(optimize_attribute)]
|
#![feature(optimize_attribute)]
|
||||||
@ -40,6 +42,9 @@ fn panic_debug(panic_info: &core::panic::PanicInfo) -> ! {
|
|||||||
|
|
||||||
if let Some(location) = panic_info.location() {
|
if let Some(location) = panic_info.location() {
|
||||||
let file = location.file();
|
let file = location.file();
|
||||||
|
print!(file);
|
||||||
|
print!(":");
|
||||||
|
println!(inttostr!(location.line()));
|
||||||
trezorhal::fatal_error::__fatal_error("", "rs", file, location.line(), "");
|
trezorhal::fatal_error::__fatal_error("", "rs", file, location.line(), "");
|
||||||
} else {
|
} else {
|
||||||
trezorhal::fatal_error::__fatal_error("", "rs", "", 0, "");
|
trezorhal::fatal_error::__fatal_error("", "rs", "", 0, "");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
mod maybe_trace {
|
mod maybe_trace_private {
|
||||||
use crate::trace::Trace;
|
use crate::trace::Trace;
|
||||||
|
|
||||||
pub trait MaybeTrace: Trace {}
|
pub trait MaybeTrace: Trace {}
|
||||||
@ -7,9 +7,9 @@ mod maybe_trace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "ui_debug"))]
|
#[cfg(not(feature = "ui_debug"))]
|
||||||
mod maybe_trace {
|
mod maybe_trace_private {
|
||||||
pub trait MaybeTrace {}
|
pub trait MaybeTrace {}
|
||||||
impl<T> MaybeTrace for T {}
|
impl<T> MaybeTrace for T {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use maybe_trace::MaybeTrace;
|
pub use maybe_trace_private::MaybeTrace;
|
||||||
|
@ -112,7 +112,7 @@ impl<F: FnMut(&str)> JsonTracer<F> {
|
|||||||
|
|
||||||
impl<F: FnMut(&str)> ListTracer for JsonTracer<F> {
|
impl<F: FnMut(&str)> ListTracer for JsonTracer<F> {
|
||||||
fn child(&mut self, value: &dyn Trace) {
|
fn child(&mut self, value: &dyn Trace) {
|
||||||
ListTracer::in_child(self, &mut |t| value.trace(t));
|
ListTracer::in_child(self, &|t| value.trace(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int(&mut self, i: i64) {
|
fn int(&mut self, i: i64) {
|
||||||
@ -196,7 +196,6 @@ pub trait Trace {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
extern crate serde_json;
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -215,7 +215,7 @@ where
|
|||||||
U: crate::trace::Trace,
|
U: crate::trace::Trace,
|
||||||
{
|
{
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.in_list("children", &mut |l| {
|
t.in_list("children", &|l| {
|
||||||
l.child(&self.0);
|
l.child(&self.0);
|
||||||
l.child(&self.1);
|
l.child(&self.1);
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
display,
|
display,
|
||||||
display::{Color, Font},
|
display::{Color, Font},
|
||||||
geometry::Rect,
|
geometry::Rect,
|
||||||
|
util::animation_disabled,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,6 +55,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self, ctx: &mut EventCtx, now: Instant) {
|
pub fn start(&mut self, ctx: &mut EventCtx, now: Instant) {
|
||||||
|
// Not starting if animations are disabled.
|
||||||
|
if animation_disabled() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let State::Initial = self.state {
|
if let State::Initial = self.state {
|
||||||
let text_width = self.font.text_width(self.text.as_ref());
|
let text_width = self.font.text_width(self.text.as_ref());
|
||||||
let max_offset = self.area.width() - text_width;
|
let max_offset = self.area.width() - text_width;
|
||||||
@ -150,6 +156,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
// Not doing anything if animations are disabled.
|
||||||
|
if animation_disabled() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
if let Event::Timer(token) = event {
|
if let Event::Timer(token) = event {
|
||||||
|
@ -29,7 +29,9 @@ pub enum PageMsg<T, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Paginate {
|
pub trait Paginate {
|
||||||
|
/// How many pages of content are there in total?
|
||||||
fn page_count(&mut self) -> usize;
|
fn page_count(&mut self) -> usize;
|
||||||
|
/// Navigate to the given page.
|
||||||
fn change_page(&mut self, active_page: usize);
|
fn change_page(&mut self, active_page: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ where
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
let fit: Cell<Option<LayoutFit>> = Cell::new(None);
|
let fit: Cell<Option<LayoutFit>> = Cell::new(None);
|
||||||
t.component("FormattedText");
|
t.component("FormattedText");
|
||||||
t.in_list("text", &mut |l| {
|
t.in_list("text", &|l| {
|
||||||
let result = self.layout_content(&mut TraceSink(l));
|
let result = self.layout_content(&mut TraceSink(l));
|
||||||
fit.set(Some(result));
|
fit.set(Some(result));
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use super::iter::GlyphMetrics;
|
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
display,
|
display,
|
||||||
display::{toif::Icon, Color, Font},
|
display::{toif::Icon, Color, Font, GlyphMetrics},
|
||||||
geometry::{Alignment, Dimensions, Offset, Point, Rect, BOTTOM_LEFT},
|
geometry::{Alignment, Dimensions, Offset, Point, Rect, BOTTOM_LEFT},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,9 +54,9 @@ pub struct TextLayout {
|
|||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct TextStyle {
|
pub struct TextStyle {
|
||||||
/// Text font ID. Can be overridden by `Op::Font`.
|
/// Text font ID.
|
||||||
pub text_font: Font,
|
pub text_font: Font,
|
||||||
/// Text color. Can be overridden by `Op::Color`.
|
/// Text color.
|
||||||
pub text_color: Color,
|
pub text_color: Color,
|
||||||
/// Background color.
|
/// Background color.
|
||||||
pub background_color: Color,
|
pub background_color: Color,
|
||||||
@ -161,16 +160,19 @@ impl TextLayout {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Baseline `Point` where we are starting to draw the text.
|
||||||
pub fn initial_cursor(&self) -> Point {
|
pub fn initial_cursor(&self) -> Point {
|
||||||
let font = &self.style.text_font;
|
let font = &self.style.text_font;
|
||||||
self.bounds.top_left()
|
self.bounds.top_left()
|
||||||
+ Offset::y(font.text_max_height() - font.text_baseline() + self.padding_top)
|
+ Offset::y(font.text_max_height() - font.text_baseline() + self.padding_top)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trying to fit the content on the current screen.
|
||||||
pub fn fit_text(&self, text: &str) -> LayoutFit {
|
pub fn fit_text(&self, text: &str) -> LayoutFit {
|
||||||
self.layout_text(text, &mut self.initial_cursor(), &mut TextNoOp)
|
self.layout_text(text, &mut self.initial_cursor(), &mut TextNoOp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw as much text as possible on the current screen.
|
||||||
pub fn render_text(&self, text: &str) {
|
pub fn render_text(&self, text: &str) {
|
||||||
self.layout_text(text, &mut self.initial_cursor(), &mut TextRenderer);
|
self.layout_text(text, &mut self.initial_cursor(), &mut TextRenderer);
|
||||||
}
|
}
|
||||||
@ -218,6 +220,9 @@ impl TextLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loop through the `text` and try to fit it on the current screen,
|
||||||
|
/// reporting events to `sink`, which may do something with them (e.g. draw
|
||||||
|
/// on screen).
|
||||||
pub fn layout_text(
|
pub fn layout_text(
|
||||||
&self,
|
&self,
|
||||||
text: &str,
|
text: &str,
|
||||||
@ -225,11 +230,10 @@ impl TextLayout {
|
|||||||
sink: &mut dyn LayoutSink,
|
sink: &mut dyn LayoutSink,
|
||||||
) -> LayoutFit {
|
) -> LayoutFit {
|
||||||
let init_cursor = *cursor;
|
let init_cursor = *cursor;
|
||||||
let bottom = (self.bounds.y1 - self.padding_bottom).max(self.bounds.y0);
|
|
||||||
let mut remaining_text = text;
|
let mut remaining_text = text;
|
||||||
|
|
||||||
// Check if bounding box is high enough for at least one line.
|
// Check if bounding box is high enough for at least one line.
|
||||||
if cursor.y > bottom {
|
if cursor.y > self.bottom_y() {
|
||||||
sink.out_of_bounds();
|
sink.out_of_bounds();
|
||||||
return LayoutFit::OutOfBounds {
|
return LayoutFit::OutOfBounds {
|
||||||
processed_chars: 0,
|
processed_chars: 0,
|
||||||
@ -244,6 +248,7 @@ impl TextLayout {
|
|||||||
) && self.continues_from_prev_page
|
) && self.continues_from_prev_page
|
||||||
{
|
{
|
||||||
sink.prev_page_ellipsis(*cursor, self);
|
sink.prev_page_ellipsis(*cursor, self);
|
||||||
|
// Move the cursor to the right, always the same distance
|
||||||
cursor.x += self.style.prev_page_ellipsis_width();
|
cursor.x += self.style.prev_page_ellipsis_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +276,12 @@ impl TextLayout {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Report the span at the cursor position.
|
// Report the span at the cursor position.
|
||||||
sink.text(*cursor, self, &remaining_text[..span.length]);
|
// Not doing it when the span length is 0, as that
|
||||||
|
// means we encountered a newline/line-break, which we do not draw.
|
||||||
|
// Line-breaks are reported later.
|
||||||
|
if span.length > 0 {
|
||||||
|
sink.text(*cursor, self, &remaining_text[..span.length]);
|
||||||
|
}
|
||||||
|
|
||||||
// Continue with the rest of the remaining_text.
|
// Continue with the rest of the remaining_text.
|
||||||
remaining_text = &remaining_text[span.length + span.skip_next_chars..];
|
remaining_text = &remaining_text[span.length + span.skip_next_chars..];
|
||||||
@ -287,7 +297,8 @@ impl TextLayout {
|
|||||||
sink.hyphen(*cursor, self);
|
sink.hyphen(*cursor, self);
|
||||||
}
|
}
|
||||||
// Check the amount of vertical space we have left.
|
// Check the amount of vertical space we have left.
|
||||||
if cursor.y + span.advance.y > bottom {
|
if cursor.y + span.advance.y > self.bottom_y() {
|
||||||
|
// Not enough space on this page.
|
||||||
if !remaining_text.is_empty() {
|
if !remaining_text.is_empty() {
|
||||||
// Append ellipsis to indicate more content is available, but only if we
|
// Append ellipsis to indicate more content is available, but only if we
|
||||||
// haven't already appended a hyphen.
|
// haven't already appended a hyphen.
|
||||||
@ -329,6 +340,7 @@ impl TextLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Overall height of the content, including paddings.
|
||||||
fn layout_height(&self, init_cursor: Point, end_cursor: Point) -> i16 {
|
fn layout_height(&self, init_cursor: Point, end_cursor: Point) -> i16 {
|
||||||
self.padding_top
|
self.padding_top
|
||||||
+ self.style.text_font.text_height()
|
+ self.style.text_font.text_height()
|
||||||
@ -336,7 +348,8 @@ impl TextLayout {
|
|||||||
+ self.padding_bottom
|
+ self.padding_bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bottom_y(&self) -> i16 {
|
/// Y coordinate of the bottom of the available space/bounds
|
||||||
|
pub fn bottom_y(&self) -> i16 {
|
||||||
(self.bounds.y1 - self.padding_bottom).max(self.bounds.y0)
|
(self.bounds.y1 - self.padding_bottom).max(self.bounds.y0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,6 +364,9 @@ impl Dimensions for TextLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether we can fit content on the current screen.
|
||||||
|
/// Knows how many characters got processed and how high the content is.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum LayoutFit {
|
pub enum LayoutFit {
|
||||||
/// Entire content fits. Vertical size is returned in `height`.
|
/// Entire content fits. Vertical size is returned in `height`.
|
||||||
Fitting { processed_chars: usize, height: i16 },
|
Fitting { processed_chars: usize, height: i16 },
|
||||||
@ -359,6 +375,7 @@ pub enum LayoutFit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutFit {
|
impl LayoutFit {
|
||||||
|
/// How high is the processed/fitted content.
|
||||||
pub fn height(&self) -> i16 {
|
pub fn height(&self) -> i16 {
|
||||||
match self {
|
match self {
|
||||||
LayoutFit::Fitting { height, .. } => *height,
|
LayoutFit::Fitting { height, .. } => *height,
|
||||||
@ -368,24 +385,36 @@ impl LayoutFit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor for text segment operations.
|
/// Visitor for text segment operations.
|
||||||
|
/// Defines responses for certain kind of events encountered
|
||||||
|
/// when processing the content.
|
||||||
pub trait LayoutSink {
|
pub trait LayoutSink {
|
||||||
|
/// Text should be processed.
|
||||||
fn text(&mut self, _cursor: Point, _layout: &TextLayout, _text: &str) {}
|
fn text(&mut self, _cursor: Point, _layout: &TextLayout, _text: &str) {}
|
||||||
|
/// Hyphen at the end of line.
|
||||||
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
||||||
|
/// Ellipsis at the end of the page.
|
||||||
fn ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
fn ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
||||||
|
/// Ellipsis at the beginning of the page.
|
||||||
fn prev_page_ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
fn prev_page_ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
||||||
|
/// Line break - a newline.
|
||||||
fn line_break(&mut self, _cursor: Point) {}
|
fn line_break(&mut self, _cursor: Point) {}
|
||||||
|
/// Content cannot fit on the screen.
|
||||||
fn out_of_bounds(&mut self) {}
|
fn out_of_bounds(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `LayoutSink` without any functionality.
|
||||||
|
/// Used to consume events when counting pages
|
||||||
|
/// or navigating to a certain page number.
|
||||||
pub struct TextNoOp;
|
pub struct TextNoOp;
|
||||||
|
|
||||||
impl LayoutSink for TextNoOp {}
|
impl LayoutSink for TextNoOp {}
|
||||||
|
|
||||||
|
/// `LayoutSink` for rendering the content.
|
||||||
pub struct TextRenderer;
|
pub struct TextRenderer;
|
||||||
|
|
||||||
impl LayoutSink for TextRenderer {
|
impl LayoutSink for TextRenderer {
|
||||||
fn text(&mut self, cursor: Point, layout: &TextLayout, text: &str) {
|
fn text(&mut self, cursor: Point, layout: &TextLayout, text: &str) {
|
||||||
display::text(
|
display::text_left(
|
||||||
cursor,
|
cursor,
|
||||||
text,
|
text,
|
||||||
layout.style.text_font,
|
layout.style.text_font,
|
||||||
@ -395,7 +424,7 @@ impl LayoutSink for TextRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn hyphen(&mut self, cursor: Point, layout: &TextLayout) {
|
fn hyphen(&mut self, cursor: Point, layout: &TextLayout) {
|
||||||
display::text(
|
display::text_left(
|
||||||
cursor,
|
cursor,
|
||||||
"-",
|
"-",
|
||||||
layout.style.text_font,
|
layout.style.text_font,
|
||||||
@ -405,15 +434,16 @@ impl LayoutSink for TextRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ellipsis(&mut self, cursor: Point, layout: &TextLayout) {
|
fn ellipsis(&mut self, cursor: Point, layout: &TextLayout) {
|
||||||
if let Some(icon) = layout.style.ellipsis_icon {
|
if let Some((icon, margin)) = layout.style.ellipsis_icon {
|
||||||
|
let bottom_left = cursor + Offset::new(margin, 1);
|
||||||
icon.draw(
|
icon.draw(
|
||||||
cursor,
|
bottom_left,
|
||||||
BOTTOM_LEFT,
|
BOTTOM_LEFT,
|
||||||
layout.style.ellipsis_color,
|
layout.style.ellipsis_color,
|
||||||
layout.style.background_color,
|
layout.style.background_color,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
display::text(
|
display::text_left(
|
||||||
cursor,
|
cursor,
|
||||||
ELLIPSIS,
|
ELLIPSIS,
|
||||||
layout.style.text_font,
|
layout.style.text_font,
|
||||||
@ -424,7 +454,7 @@ impl LayoutSink for TextRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prev_page_ellipsis(&mut self, cursor: Point, layout: &TextLayout) {
|
fn prev_page_ellipsis(&mut self, cursor: Point, layout: &TextLayout) {
|
||||||
if let Some(icon) = layout.style.prev_page_ellipsis_icon {
|
if let Some((icon, _margin)) = layout.style.prev_page_ellipsis_icon {
|
||||||
icon.draw(
|
icon.draw(
|
||||||
cursor,
|
cursor,
|
||||||
BOTTOM_LEFT,
|
BOTTOM_LEFT,
|
||||||
@ -432,7 +462,7 @@ impl LayoutSink for TextRenderer {
|
|||||||
layout.style.background_color,
|
layout.style.background_color,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
display::text(
|
display::text_left(
|
||||||
cursor,
|
cursor,
|
||||||
ELLIPSIS,
|
ELLIPSIS,
|
||||||
layout.style.text_font,
|
layout.style.text_font,
|
||||||
@ -454,23 +484,23 @@ pub mod trace {
|
|||||||
|
|
||||||
impl LayoutSink for TraceSink<'_> {
|
impl LayoutSink for TraceSink<'_> {
|
||||||
fn text(&mut self, _cursor: Point, _layout: &TextLayout, text: &str) {
|
fn text(&mut self, _cursor: Point, _layout: &TextLayout, text: &str) {
|
||||||
self.0.string(&text);
|
self.0.string(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {
|
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||||
self.0.string(&"-");
|
self.0.string("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {
|
fn ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||||
self.0.string(&ELLIPSIS);
|
self.0.string(ELLIPSIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prev_page_ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {
|
fn prev_page_ellipsis(&mut self, _cursor: Point, _layout: &TextLayout) {
|
||||||
self.0.string(&ELLIPSIS);
|
self.0.string(ELLIPSIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_break(&mut self, _cursor: Point) {
|
fn line_break(&mut self, _cursor: Point) {
|
||||||
self.0.string(&"\n");
|
self.0.string("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,6 +537,8 @@ impl<'a> Op<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Carries info about the content that was processed
|
||||||
|
/// on the current line.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
struct Span {
|
struct Span {
|
||||||
/// How many characters from the input text this span is laying out.
|
/// How many characters from the input text this span is laying out.
|
||||||
@ -603,7 +635,7 @@ impl Span {
|
|||||||
}
|
}
|
||||||
found_any_whitespace = true;
|
found_any_whitespace = true;
|
||||||
} else if span_width + char_width > max_width {
|
} else if span_width + char_width > max_width {
|
||||||
// Return the last breakpoint.
|
// Cannot fit on this line. Return the last breakpoint.
|
||||||
return line;
|
return line;
|
||||||
} else {
|
} else {
|
||||||
let have_space_for_break =
|
let have_space_for_break =
|
||||||
@ -625,7 +657,7 @@ impl Span {
|
|||||||
span_width += char_width;
|
span_width += char_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The whole text is fitting.
|
// The whole text is fitting on the current line.
|
||||||
Self {
|
Self {
|
||||||
length: text.len(),
|
length: text.len(),
|
||||||
advance: Offset::x(span_width),
|
advance: Offset::x(span_width),
|
||||||
|
@ -239,13 +239,13 @@ pub mod trace {
|
|||||||
impl<T: ParagraphSource> crate::trace::Trace for Paragraphs<T> {
|
impl<T: ParagraphSource> crate::trace::Trace for Paragraphs<T> {
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.string("component", "Paragraphs");
|
t.string("component", "Paragraphs");
|
||||||
t.in_list("paragraphs", &mut |par_list| {
|
t.in_list("paragraphs", &|par_list| {
|
||||||
Self::foreach_visible(
|
Self::foreach_visible(
|
||||||
&self.source,
|
&self.source,
|
||||||
&self.visible,
|
&self.visible,
|
||||||
self.offset,
|
self.offset,
|
||||||
&mut |layout, content| {
|
&mut |layout, content| {
|
||||||
par_list.in_list(&mut |par| {
|
par_list.in_list(&|par| {
|
||||||
layout.layout_text(
|
layout.layout_text(
|
||||||
content,
|
content,
|
||||||
&mut layout.initial_cursor(),
|
&mut layout.initial_cursor(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
constant::{screen, LOADER_OUTER},
|
constant::{screen, LOADER_OUTER},
|
||||||
display::{rect_fill, rect_fill_rounded, rect_fill_rounded1, Color, Icon},
|
display::{rect_fill, rect_fill_rounded, Color, Icon},
|
||||||
geometry::{Offset, Point, Rect, CENTER},
|
geometry::{Offset, Point, Rect, CENTER},
|
||||||
};
|
};
|
||||||
use core::f32::consts::SQRT_2;
|
use core::f32::consts::SQRT_2;
|
||||||
@ -18,7 +18,7 @@ fn star_small(center: Point, fg: Color, _bg: Color) {
|
|||||||
|
|
||||||
fn star_medium(center: Point, fg: Color, bg: Color) {
|
fn star_medium(center: Point, fg: Color, bg: Color) {
|
||||||
let r = Rect::from_center_and_size(center, Offset::uniform(SIZE_MEDIUM));
|
let r = Rect::from_center_and_size(center, Offset::uniform(SIZE_MEDIUM));
|
||||||
rect_fill_rounded1(r, fg, bg);
|
rect_fill_rounded(r, fg, bg, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn star_large(center: Point, fg: Color, bg: Color) {
|
fn star_large(center: Point, fg: Color, bg: Color) {
|
||||||
|
@ -15,6 +15,9 @@ use crate::trezorhal::{
|
|||||||
},
|
},
|
||||||
uzlib::UZLIB_WINDOW_SIZE,
|
uzlib::UZLIB_WINDOW_SIZE,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "dma2d")]
|
||||||
|
use crate::ui::component::image::Image;
|
||||||
|
|
||||||
#[cfg(not(feature = "dma2d"))]
|
#[cfg(not(feature = "dma2d"))]
|
||||||
use crate::ui::geometry::TOP_LEFT;
|
use crate::ui::geometry::TOP_LEFT;
|
||||||
|
|
||||||
@ -23,12 +26,11 @@ use crate::{
|
|||||||
trezorhal::{buffers, display, time, uzlib::UzlibContext},
|
trezorhal::{buffers, display, time, uzlib::UzlibContext},
|
||||||
ui::lerp::Lerp,
|
ui::lerp::Lerp,
|
||||||
};
|
};
|
||||||
use core::slice;
|
|
||||||
|
|
||||||
#[cfg(feature = "dma2d")]
|
// Reexports
|
||||||
use crate::ui::component::image::Image;
|
|
||||||
pub use crate::ui::display::toif::Icon;
|
pub use crate::ui::display::toif::Icon;
|
||||||
#[cfg(any(feature = "model_tt", feature = "model_tr"))]
|
pub use color::Color;
|
||||||
|
pub use font::{Font, Glyph, GlyphMetrics};
|
||||||
pub use loader::{loader, loader_indeterminate, LOADER_MAX, LOADER_MIN};
|
pub use loader::{loader, loader_indeterminate, LOADER_MAX, LOADER_MIN};
|
||||||
|
|
||||||
pub fn backlight() -> u16 {
|
pub fn backlight() -> u16 {
|
||||||
@ -58,6 +60,7 @@ pub fn fade_backlight_duration(target: u16, duration_ms: u32) {
|
|||||||
set_backlight(target as u16);
|
set_backlight(target as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fill a whole rectangle with a specific color.
|
||||||
pub fn rect_fill(r: Rect, fg_color: Color) {
|
pub fn rect_fill(r: Rect, fg_color: Color) {
|
||||||
display::bar(r.x0, r.y0, r.width(), r.height(), fg_color.into());
|
display::bar(r.x0, r.y0, r.width(), r.height(), fg_color.into());
|
||||||
}
|
}
|
||||||
@ -69,30 +72,54 @@ pub fn rect_stroke(r: Rect, fg_color: Color) {
|
|||||||
display::bar(r.x0 + r.width() - 1, r.y0, 1, r.height(), fg_color.into());
|
display::bar(r.x0 + r.width() - 1, r.y0, 1, r.height(), fg_color.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw a rectangle with rounded corners.
|
||||||
pub fn rect_fill_rounded(r: Rect, fg_color: Color, bg_color: Color, radius: u8) {
|
pub fn rect_fill_rounded(r: Rect, fg_color: Color, bg_color: Color, radius: u8) {
|
||||||
assert!([2, 4, 8, 16].iter().any(|allowed| radius == *allowed));
|
if radius == 1 {
|
||||||
display::bar_radius(
|
rect_fill_rounded1(r, fg_color, bg_color);
|
||||||
r.x0,
|
} else {
|
||||||
r.y0,
|
assert!([2, 4, 8, 16].iter().any(|allowed| radius == *allowed));
|
||||||
r.width(),
|
display::bar_radius(
|
||||||
r.height(),
|
r.x0,
|
||||||
fg_color.into(),
|
r.y0,
|
||||||
bg_color.into(),
|
r.width(),
|
||||||
radius,
|
r.height(),
|
||||||
);
|
fg_color.into(),
|
||||||
|
bg_color.into(),
|
||||||
|
radius,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used on T1 only.
|
/// Filling a rectangle with a rounding of 1 pixel - removing the corners.
|
||||||
pub fn rect_fill_rounded1(r: Rect, fg_color: Color, bg_color: Color) {
|
fn rect_fill_rounded1(r: Rect, fg_color: Color, bg_color: Color) {
|
||||||
display::bar(r.x0, r.y0, r.width(), r.height(), fg_color.into());
|
rect_fill(r, fg_color);
|
||||||
let corners = [
|
rect_fill_corners(r, bg_color);
|
||||||
r.top_left(),
|
}
|
||||||
r.top_right() - Offset::x(1),
|
|
||||||
r.bottom_right() - Offset::uniform(1),
|
/// Creating a rectangular outline with a given radius/rounding.
|
||||||
r.bottom_left() - Offset::y(1),
|
pub fn rect_outline_rounded(r: Rect, fg_color: Color, bg_color: Color, radius: u8) {
|
||||||
];
|
// Painting a bigger rectangle with FG and inner smaller with BG
|
||||||
for p in corners.iter() {
|
// to create the outline.
|
||||||
display::bar(p.x, p.y, 1, 1, bg_color.into());
|
let inner_r = r.shrink(1);
|
||||||
|
if radius == 1 {
|
||||||
|
rect_fill_rounded(r, fg_color, bg_color, 1);
|
||||||
|
rect_fill(inner_r, bg_color);
|
||||||
|
rect_fill_corners(inner_r, fg_color);
|
||||||
|
} else if radius == 2 {
|
||||||
|
rect_fill_rounded(r, fg_color, bg_color, 2);
|
||||||
|
rect_fill_rounded(inner_r, bg_color, fg_color, 1);
|
||||||
|
} else if radius == 4 {
|
||||||
|
rect_fill_rounded(r, fg_color, bg_color, 4);
|
||||||
|
rect_fill_rounded(inner_r, bg_color, fg_color, 2);
|
||||||
|
rect_fill_corners(inner_r, bg_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Filling all four corners of a rectangle with a given color.
|
||||||
|
pub fn rect_fill_corners(r: Rect, fg_color: Color) {
|
||||||
|
for p in r.corner_points().iter() {
|
||||||
|
// This draws a 1x1 rectangle at the given point.
|
||||||
|
display::bar(p.x, p.y, 1, 1, fg_color.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +141,7 @@ impl<'a> TextOverlay<'a> {
|
|||||||
text,
|
text,
|
||||||
font,
|
font,
|
||||||
max_height: font.max_height(),
|
max_height: font.max_height(),
|
||||||
baseline: font.baseline(),
|
baseline: font.text_baseline(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,7 +828,8 @@ pub fn dotted_line(start: Point, width: i16, color: Color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color: Color) {
|
/// Display text left-aligned to a certain Point
|
||||||
|
pub fn text_left(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color: Color) {
|
||||||
display::text(
|
display::text(
|
||||||
baseline.x,
|
baseline.x,
|
||||||
baseline.y,
|
baseline.y,
|
||||||
@ -812,6 +840,7 @@ pub fn text(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Display text centered around a certain Point
|
||||||
pub fn text_center(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color: Color) {
|
pub fn text_center(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color: Color) {
|
||||||
let w = font.text_width(text);
|
let w = font.text_width(text);
|
||||||
display::text(
|
display::text(
|
||||||
@ -824,6 +853,7 @@ pub fn text_center(baseline: Point, text: &str, font: Font, fg_color: Color, bg_
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Display text right-alligned to a certain Point
|
||||||
pub fn text_right(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color: Color) {
|
pub fn text_right(baseline: Point, text: &str, font: Font, fg_color: Color, bg_color: Color) {
|
||||||
let w = font.text_width(text);
|
let w = font.text_width(text);
|
||||||
display::text(
|
display::text(
|
||||||
|
@ -202,6 +202,8 @@ impl From<Offset> for Point {
|
|||||||
|
|
||||||
/// A rectangle in 2D space defined by the top-left point `x0`,`y0` and the
|
/// A rectangle in 2D space defined by the top-left point `x0`,`y0` and the
|
||||||
/// bottom-right point `x1`,`y1`.
|
/// bottom-right point `x1`,`y1`.
|
||||||
|
/// NOTE: bottom-right point is not included in the rectangle, it is outside of
|
||||||
|
/// it.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
pub x0: i16,
|
pub x0: i16,
|
||||||
@ -304,10 +306,12 @@ impl Rect {
|
|||||||
self.bottom_left().center(self.bottom_right())
|
self.bottom_left().center(self.bottom_right())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether a `Point` is inside the `Rect`.
|
||||||
pub const fn contains(&self, point: Point) -> bool {
|
pub const fn contains(&self, point: Point) -> bool {
|
||||||
point.x >= self.x0 && point.x < self.x1 && point.y >= self.y0 && point.y < self.y1
|
point.x >= self.x0 && point.x < self.x1 && point.y >= self.y0 && point.y < self.y1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a bigger `Rect` that contains both `self` and `other`.
|
||||||
pub const fn union(&self, other: Self) -> Self {
|
pub const fn union(&self, other: Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x0: min(self.x0, other.x0),
|
x0: min(self.x0, other.x0),
|
||||||
@ -317,6 +321,8 @@ impl Rect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a smaller `Rect` from the bigger one by moving
|
||||||
|
/// all the four sides closer to the center.
|
||||||
pub const fn inset(&self, insets: Insets) -> Self {
|
pub const fn inset(&self, insets: Insets) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x0: self.x0 + insets.left,
|
x0: self.x0 + insets.left,
|
||||||
@ -335,24 +341,12 @@ impl Rect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn cut_from_left(&self, width: i16) -> Self {
|
/// Move all the sides closer to the center by the same distance.
|
||||||
Self {
|
pub const fn shrink(&self, size: i16) -> Self {
|
||||||
x0: self.x0,
|
self.inset(Insets::uniform(size))
|
||||||
y0: self.y0,
|
|
||||||
x1: self.x0 + width,
|
|
||||||
y1: self.y1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn cut_from_right(&self, width: i16) -> Self {
|
|
||||||
Self {
|
|
||||||
x0: self.x1 - width,
|
|
||||||
y0: self.y0,
|
|
||||||
x1: self.x1,
|
|
||||||
y1: self.y1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split `Rect` into top and bottom, given the top one's `height`.
|
||||||
pub const fn split_top(self, height: i16) -> (Self, Self) {
|
pub const fn split_top(self, height: i16) -> (Self, Self) {
|
||||||
let height = clamp(height, 0, self.height());
|
let height = clamp(height, 0, self.height());
|
||||||
|
|
||||||
@ -367,10 +361,12 @@ impl Rect {
|
|||||||
(top, bottom)
|
(top, bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split `Rect` into top and bottom, given the bottom one's `height`.
|
||||||
pub const fn split_bottom(self, height: i16) -> (Self, Self) {
|
pub const fn split_bottom(self, height: i16) -> (Self, Self) {
|
||||||
self.split_top(self.height() - height)
|
self.split_top(self.height() - height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split `Rect` into left and right, given the left one's `width`.
|
||||||
pub const fn split_left(self, width: i16) -> (Self, Self) {
|
pub const fn split_left(self, width: i16) -> (Self, Self) {
|
||||||
let width = clamp(width, 0, self.width());
|
let width = clamp(width, 0, self.width());
|
||||||
|
|
||||||
@ -385,6 +381,7 @@ impl Rect {
|
|||||||
(left, right)
|
(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Split `Rect` into left and right, given the right one's `width`.
|
||||||
pub const fn split_right(self, width: i16) -> (Self, Self) {
|
pub const fn split_right(self, width: i16) -> (Self, Self) {
|
||||||
self.split_left(self.width() - width)
|
self.split_left(self.width() - width)
|
||||||
}
|
}
|
||||||
@ -406,6 +403,7 @@ impl Rect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moving `Rect` by the given offset.
|
||||||
pub const fn translate(&self, offset: Offset) -> Self {
|
pub const fn translate(&self, offset: Offset) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x0: self.x0 + offset.x,
|
x0: self.x0 + offset.x,
|
||||||
@ -414,6 +412,16 @@ impl Rect {
|
|||||||
y1: self.y1 + offset.y,
|
y1: self.y1 + offset.y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get all four corner points.
|
||||||
|
pub fn corner_points(&self) -> [Point; 4] {
|
||||||
|
[
|
||||||
|
self.top_left(),
|
||||||
|
self.top_right() - Offset::x(1),
|
||||||
|
self.bottom_right() - Offset::uniform(1),
|
||||||
|
self.bottom_left() - Offset::y(1),
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
@ -538,7 +546,7 @@ impl Grid {
|
|||||||
let cell_height = (self.area.height() - spacing_height) / nrows;
|
let cell_height = (self.area.height() - spacing_height) / nrows;
|
||||||
|
|
||||||
// Not every area can be fully covered by equal-sized cells and spaces, there
|
// Not every area can be fully covered by equal-sized cells and spaces, there
|
||||||
// might be serveral pixels left unused. We'll distribute them by 1px to
|
// might be several pixels left unused. We'll distribute them by 1px to
|
||||||
// the leftmost cells.
|
// the leftmost cells.
|
||||||
let leftover_width = (self.area.width() - spacing_width) % ncols;
|
let leftover_width = (self.area.width() - spacing_width) % ncols;
|
||||||
let leftover_height = (self.area.height() - spacing_height) % nrows;
|
let leftover_height = (self.area.height() - spacing_height) % nrows;
|
||||||
|
@ -19,7 +19,7 @@ use crate::ui::{
|
|||||||
text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt},
|
text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt},
|
||||||
Event, EventCtx,
|
Event, EventCtx,
|
||||||
},
|
},
|
||||||
constant::{screen, BACKLIGHT_NORMAL, WIDTH},
|
constant::{screen, WIDTH},
|
||||||
display::{fade_backlight_duration, Color, Icon, TextOverlay},
|
display::{fade_backlight_duration, Color, Icon, TextOverlay},
|
||||||
event::ButtonEvent,
|
event::ButtonEvent,
|
||||||
geometry::{LinearPlacement, Offset, Rect, CENTER},
|
geometry::{LinearPlacement, Offset, Rect, CENTER},
|
||||||
@ -31,7 +31,7 @@ use crate::ui::{
|
|||||||
theme::{bld_button_cancel, bld_button_default, BLD_BG, BLD_FG},
|
theme::{bld_button_cancel, bld_button_default, BLD_BG, BLD_FG},
|
||||||
},
|
},
|
||||||
component::{Button, ButtonPos, ResultScreen},
|
component::{Button, ButtonPos, ResultScreen},
|
||||||
theme::{ICON_FAIL, ICON_SUCCESS, LOGO_EMPTY},
|
theme::{BACKLIGHT_NORMAL, ICON_FAIL, ICON_SUCCESS, LOGO_EMPTY},
|
||||||
},
|
},
|
||||||
util::{from_c_array, from_c_str},
|
util::{from_c_array, from_c_str},
|
||||||
};
|
};
|
||||||
|
@ -132,12 +132,12 @@ where
|
|||||||
ButtonContent::Text(text) => {
|
ButtonContent::Text(text) => {
|
||||||
let background_color = style.text_color.negate();
|
let background_color = style.text_color.negate();
|
||||||
if style.border_horiz {
|
if style.border_horiz {
|
||||||
display::rect_fill_rounded1(self.area, background_color, theme::BG);
|
display::rect_fill_rounded(self.area, background_color, theme::BG, 1);
|
||||||
} else {
|
} else {
|
||||||
display::rect_fill(self.area, background_color)
|
display::rect_fill(self.area, background_color)
|
||||||
}
|
}
|
||||||
|
|
||||||
display::text(
|
display::text_left(
|
||||||
self.baseline,
|
self.baseline,
|
||||||
text.as_ref(),
|
text.as_ref(),
|
||||||
style.font,
|
style.font,
|
||||||
|
@ -83,7 +83,11 @@ where
|
|||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.component("Dialog");
|
t.component("Dialog");
|
||||||
t.child("content", &self.content);
|
t.child("content", &self.content);
|
||||||
self.left_btn.as_ref().map(|b| t.child("left", b));
|
if let Some(b) = self.left_btn.as_ref() {
|
||||||
self.right_btn.as_ref().map(|b| t.child("right", b));
|
t.child("left", b)
|
||||||
|
}
|
||||||
|
if let Some(b) = self.right_btn.as_ref() {
|
||||||
|
t.child("right", b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&mut self) {
|
fn paint(&mut self) {
|
||||||
display::text(
|
display::text_left(
|
||||||
self.area.bottom_left() - Offset::y(2),
|
self.area.bottom_left() - Offset::y(2),
|
||||||
self.title.as_ref(),
|
self.title.as_ref(),
|
||||||
Font::BOLD,
|
Font::BOLD,
|
||||||
|
@ -160,8 +160,12 @@ impl<S: ParagraphStrType> crate::trace::Trace for ResultPopup<S> {
|
|||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.component("ResultPopup");
|
t.component("ResultPopup");
|
||||||
t.child("text", &self.text);
|
t.child("text", &self.text);
|
||||||
self.button.as_ref().map(|b| t.child("button", b));
|
if let Some(b) = self.button.as_ref() {
|
||||||
self.headline.as_ref().map(|h| t.child("headline", h));
|
t.child("button", b)
|
||||||
|
}
|
||||||
|
if let Some(h) = self.headline.as_ref() {
|
||||||
|
t.child("headline", h)
|
||||||
|
}
|
||||||
t.child("result_anim", &self.result_anim);
|
t.child("result_anim", &self.result_anim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,98 +144,3 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// """Confirm text."""
|
/// """Confirm text."""
|
||||||
Qstr::MP_QSTR_confirm_text => obj_fn_kw!(0, new_confirm_text).as_obj(),
|
Qstr::MP_QSTR_confirm_text => obj_fn_kw!(0, new_confirm_text).as_obj(),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
extern crate json;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
trace::tests::trace,
|
|
||||||
ui::{
|
|
||||||
component::Component,
|
|
||||||
model_tr::{
|
|
||||||
component::{Dialog, DialogMsg},
|
|
||||||
constant,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
impl<T, U> ComponentMsgObj for Dialog<T, U>
|
|
||||||
where
|
|
||||||
T: ComponentMsgObj,
|
|
||||||
U: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
|
||||||
match msg {
|
|
||||||
DialogMsg::Content(c) => self.inner().msg_try_into_obj(c),
|
|
||||||
DialogMsg::LeftClicked => Ok(CANCELLED.as_obj()),
|
|
||||||
DialogMsg::RightClicked => Ok(CONFIRMED.as_obj()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn trace_example_layout() {
|
|
||||||
let mut layout = Dialog::new(
|
|
||||||
FormattedText::new(
|
|
||||||
theme::TEXT_NORMAL,
|
|
||||||
theme::FORMATTED,
|
|
||||||
"Testing text layout, with some text, and some more text. And {param}",
|
|
||||||
)
|
|
||||||
.with("param", "parameters!"),
|
|
||||||
Some(Button::with_text(
|
|
||||||
ButtonPos::Left,
|
|
||||||
"Left",
|
|
||||||
theme::button_cancel(),
|
|
||||||
)),
|
|
||||||
Some(Button::with_text(
|
|
||||||
ButtonPos::Right,
|
|
||||||
"Right",
|
|
||||||
theme::button_default(),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
layout.place(constant::screen());
|
|
||||||
assert_eq!(
|
|
||||||
trace(&layout),
|
|
||||||
r#"<Dialog content:<Text content:Testing text layout,
|
|
||||||
with some text, and
|
|
||||||
some more text. And p-
|
|
||||||
arameters! > left:<Button text:Left > right:<Button text:Right > >"#
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn trace_layout_title() {
|
|
||||||
let mut layout = Frame::new(
|
|
||||||
"Please confirm",
|
|
||||||
Dialog::new(
|
|
||||||
FormattedText::new(
|
|
||||||
theme::TEXT_NORMAL,
|
|
||||||
theme::FORMATTED,
|
|
||||||
"Testing text layout, with some text, and some more text. And {param}",
|
|
||||||
)
|
|
||||||
.with("param", "parameters!"),
|
|
||||||
Some(Button::with_text(
|
|
||||||
ButtonPos::Left,
|
|
||||||
"Left",
|
|
||||||
theme::button_cancel(),
|
|
||||||
)),
|
|
||||||
Some(Button::with_text(
|
|
||||||
ButtonPos::Right,
|
|
||||||
"Right",
|
|
||||||
theme::button_default(),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
layout.place(constant::screen());
|
|
||||||
assert_eq!(
|
|
||||||
trace(&layout),
|
|
||||||
r#"<Frame title:Please confirm content:<Dialog content:<Text content:Testing text layout,
|
|
||||||
with some text, and
|
|
||||||
some more text. And p-
|
|
||||||
arameters! > left:<Button text:Left > right:<Button text:Right > > >"#
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -6,6 +6,9 @@ use crate::ui::{
|
|||||||
|
|
||||||
use super::component::{ButtonStyle, ButtonStyleSheet};
|
use super::component::{ButtonStyle, ButtonStyleSheet};
|
||||||
|
|
||||||
|
// Typical backlight values.
|
||||||
|
pub const BACKLIGHT_NORMAL: u16 = 150;
|
||||||
|
|
||||||
// Color palette.
|
// Color palette.
|
||||||
pub const WHITE: Color = Color::rgb(255, 255, 255);
|
pub const WHITE: Color = Color::rgb(255, 255, 255);
|
||||||
pub const BLACK: Color = Color::rgb(0, 0, 0);
|
pub const BLACK: Color = Color::rgb(0, 0, 0);
|
||||||
|
@ -200,7 +200,7 @@ impl<T> Button<T> {
|
|||||||
let start_of_baseline = self.area.center()
|
let start_of_baseline = self.area.center()
|
||||||
+ Offset::new(-width / 2, height / 2)
|
+ Offset::new(-width / 2, height / 2)
|
||||||
+ Offset::y(Self::BASELINE_OFFSET);
|
+ Offset::y(Self::BASELINE_OFFSET);
|
||||||
display::text(
|
display::text_left(
|
||||||
start_of_baseline,
|
start_of_baseline,
|
||||||
text,
|
text,
|
||||||
style.font,
|
style.font,
|
||||||
@ -575,7 +575,7 @@ impl IconText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if use_text {
|
if use_text {
|
||||||
display::text(
|
display::text_left(
|
||||||
text_pos,
|
text_pos,
|
||||||
self.text,
|
self.text,
|
||||||
style.font,
|
style.font,
|
||||||
|
@ -191,8 +191,13 @@ where
|
|||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.component("Frame");
|
t.component("Frame");
|
||||||
t.child("title", &self.title);
|
t.child("title", &self.title);
|
||||||
self.subtitle.as_ref().map(|s| t.child("subtitle", s));
|
t.child("content", &self.content);
|
||||||
self.button.as_ref().map(|b| t.child("button", b));
|
if let Some(subtitle) = &self.subtitle {
|
||||||
|
t.child("subtitle", subtitle);
|
||||||
|
}
|
||||||
|
if let Some(button) = &self.button {
|
||||||
|
t.child("button", button);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
trezorhal::bip39,
|
trezorhal::bip39,
|
||||||
ui::{
|
ui::{
|
||||||
component::{Component, Event, EventCtx},
|
component::{text::common::TextBox, Component, Event, EventCtx},
|
||||||
display,
|
display,
|
||||||
display::toif::Icon,
|
display::toif::Icon,
|
||||||
geometry::{Offset, Rect, CENTER},
|
geometry::{Offset, Rect, CENTER},
|
||||||
model_tt::{
|
model_tt::{
|
||||||
component::{
|
component::{
|
||||||
keyboard::{
|
keyboard::{
|
||||||
common::{paint_pending_marker, MultiTapKeyboard, TextBox},
|
common::{paint_pending_marker, MultiTapKeyboard},
|
||||||
mnemonic::{MnemonicInput, MnemonicInputMsg, MNEMONIC_KEY_COUNT},
|
mnemonic::{MnemonicInput, MnemonicInputMsg, MNEMONIC_KEY_COUNT},
|
||||||
},
|
},
|
||||||
Button, ButtonContent, ButtonMsg,
|
Button, ButtonContent, ButtonMsg,
|
||||||
@ -110,7 +110,7 @@ impl Component for Bip39Input {
|
|||||||
// Content starts in the left-center point, offset by 16px to the right and 8px
|
// Content starts in the left-center point, offset by 16px to the right and 8px
|
||||||
// to the bottom.
|
// to the bottom.
|
||||||
let text_baseline = area.top_left().center(area.bottom_left()) + Offset::new(16, 8);
|
let text_baseline = area.top_left().center(area.bottom_left()) + Offset::new(16, 8);
|
||||||
display::text(
|
display::text_left(
|
||||||
text_baseline,
|
text_baseline,
|
||||||
text,
|
text,
|
||||||
style.font,
|
style.font,
|
||||||
@ -121,7 +121,7 @@ impl Component for Bip39Input {
|
|||||||
// Paint the rest of the suggested dictionary word.
|
// Paint the rest of the suggested dictionary word.
|
||||||
if let Some(word) = self.suggested_word.and_then(|w| w.get(text.len()..)) {
|
if let Some(word) = self.suggested_word.and_then(|w| w.get(text.len()..)) {
|
||||||
let word_baseline = text_baseline + Offset::new(width, 0);
|
let word_baseline = text_baseline + Offset::new(width, 0);
|
||||||
display::text(
|
display::text_left(
|
||||||
word_baseline,
|
word_baseline,
|
||||||
word,
|
word,
|
||||||
style.font,
|
style.font,
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
component::{base::ComponentExt, Child, Component, Event, EventCtx, Never},
|
component::{
|
||||||
|
base::ComponentExt, text::common::TextBox, Child, Component, Event, EventCtx, Never,
|
||||||
|
},
|
||||||
display,
|
display,
|
||||||
display::toif::Icon,
|
display::toif::Icon,
|
||||||
geometry::{Grid, Offset, Rect},
|
geometry::{Grid, Offset, Rect},
|
||||||
model_tt::component::{
|
model_tt::component::{
|
||||||
button::{Button, ButtonContent, ButtonMsg},
|
button::{Button, ButtonContent, ButtonMsg},
|
||||||
keyboard::common::{paint_pending_marker, MultiTapKeyboard, TextBox},
|
keyboard::common::{paint_pending_marker, MultiTapKeyboard},
|
||||||
swipe::{Swipe, SwipeDirection},
|
swipe::{Swipe, SwipeDirection},
|
||||||
theme, ScrollBar,
|
theme, ScrollBar,
|
||||||
},
|
},
|
||||||
@ -378,5 +380,6 @@ impl Component for Input {
|
|||||||
impl crate::trace::Trace for PassphraseKeyboard {
|
impl crate::trace::Trace for PassphraseKeyboard {
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.component("PassphraseKeyboard");
|
t.component("PassphraseKeyboard");
|
||||||
|
t.string("passphrase", self.passphrase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,5 +468,16 @@ where
|
|||||||
{
|
{
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.component("PinKeyboard");
|
t.component("PinKeyboard");
|
||||||
|
// So that debuglink knows the locations of the buttons
|
||||||
|
let mut digits_order: String<10> = String::new();
|
||||||
|
for btn in self.digit_btns.iter() {
|
||||||
|
let btn_content = btn.inner().content();
|
||||||
|
if let ButtonContent::Text(text) = btn_content {
|
||||||
|
unwrap!(digits_order.push_str(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.string("digits_order", &digits_order);
|
||||||
|
t.string("pin", self.textbox.inner().pin());
|
||||||
|
t.bool("display_digits", self.textbox.inner().display_digits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,17 @@ use heapless::String;
|
|||||||
use crate::{
|
use crate::{
|
||||||
trezorhal::slip39,
|
trezorhal::slip39,
|
||||||
ui::{
|
ui::{
|
||||||
component::{Component, Event, EventCtx},
|
component::{
|
||||||
|
text::common::{TextBox, TextEdit},
|
||||||
|
Component, Event, EventCtx,
|
||||||
|
},
|
||||||
display,
|
display,
|
||||||
display::toif::Icon,
|
display::toif::Icon,
|
||||||
geometry::{Offset, Rect, CENTER},
|
geometry::{Offset, Rect, CENTER},
|
||||||
model_tt::{
|
model_tt::{
|
||||||
component::{
|
component::{
|
||||||
keyboard::{
|
keyboard::{
|
||||||
common::{paint_pending_marker, MultiTapKeyboard, TextBox, TextEdit},
|
common::{paint_pending_marker, MultiTapKeyboard},
|
||||||
mnemonic::{MnemonicInput, MnemonicInputMsg, MNEMONIC_KEY_COUNT},
|
mnemonic::{MnemonicInput, MnemonicInputMsg, MNEMONIC_KEY_COUNT},
|
||||||
},
|
},
|
||||||
Button, ButtonContent, ButtonMsg,
|
Button, ButtonContent, ButtonMsg,
|
||||||
@ -156,7 +159,7 @@ impl Component for Slip39Input {
|
|||||||
.assert_if_debugging_ui("Text buffer is too small");
|
.assert_if_debugging_ui("Text buffer is too small");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
display::text(
|
display::text_left(
|
||||||
text_baseline,
|
text_baseline,
|
||||||
text.as_str(),
|
text.as_str(),
|
||||||
style.font,
|
style.font,
|
||||||
|
@ -494,7 +494,7 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
extern crate serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
trace::tests::trace,
|
trace::tests::trace,
|
||||||
|
@ -9,8 +9,6 @@ pub const LOADER_OUTER: i16 = 60;
|
|||||||
pub const LOADER_INNER: i16 = 42;
|
pub const LOADER_INNER: i16 = 42;
|
||||||
pub const LOADER_ICON_MAX_SIZE: i16 = 64;
|
pub const LOADER_ICON_MAX_SIZE: i16 = 64;
|
||||||
|
|
||||||
pub const BACKLIGHT_NORMAL: i32 = 150;
|
|
||||||
|
|
||||||
pub const fn size() -> Offset {
|
pub const fn size() -> Offset {
|
||||||
Offset::new(WIDTH, HEIGHT)
|
Offset::new(WIDTH, HEIGHT)
|
||||||
}
|
}
|
||||||
|
@ -1340,23 +1340,11 @@ 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).unwrap().try_into().unwrap();
|
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||||
let description: StrBuffer = kwargs
|
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||||
.get(Qstr::MP_QSTR_description)
|
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||||
.unwrap()
|
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
|
||||||
.try_into()
|
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
|
||||||
.unwrap();
|
|
||||||
let button: StrBuffer = kwargs
|
|
||||||
.get(Qstr::MP_QSTR_button)
|
|
||||||
.unwrap()
|
|
||||||
.try_into()
|
|
||||||
.unwrap();
|
|
||||||
let dry_run: bool = kwargs
|
|
||||||
.get(Qstr::MP_QSTR_dry_run)
|
|
||||||
.unwrap()
|
|
||||||
.try_into()
|
|
||||||
.unwrap();
|
|
||||||
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false).unwrap();
|
|
||||||
|
|
||||||
let paragraphs = Paragraphs::new([
|
let paragraphs = Paragraphs::new([
|
||||||
Paragraph::new(&theme::TEXT_DEMIBOLD, title).centered(),
|
Paragraph::new(&theme::TEXT_DEMIBOLD, title).centered(),
|
||||||
@ -1391,11 +1379,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
|
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
|
||||||
.get(Qstr::MP_QSTR_dry_run)
|
|
||||||
.unwrap()
|
|
||||||
.try_into()
|
|
||||||
.unwrap();
|
|
||||||
let title = if dry_run {
|
let title = if dry_run {
|
||||||
"SEED CHECK"
|
"SEED CHECK"
|
||||||
} else {
|
} else {
|
||||||
@ -1554,7 +1538,7 @@ extern "C" fn draw_welcome_screen() -> Obj {
|
|||||||
screen.place(constant::screen());
|
screen.place(constant::screen());
|
||||||
display::sync();
|
display::sync();
|
||||||
screen.paint();
|
screen.paint();
|
||||||
display::set_backlight(150); // BACKLIGHT_NORMAL
|
display::set_backlight(theme::BACKLIGHT_NORMAL);
|
||||||
Obj::const_none()
|
Obj::const_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1575,8 +1559,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// """Disable animations, debug builds only."""
|
/// """Disable animations, debug builds only."""
|
||||||
Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(),
|
Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(),
|
||||||
|
|
||||||
/// def jpeg_info(data: bytes) -> (width: int, height: int, mcu_height: int):
|
/// def jpeg_info(data: bytes) -> tuple[int, int, int]:
|
||||||
/// """Get JPEG image dimensions."""
|
/// """Get JPEG image dimensions (width: int, height: int, mcu_height: int)."""
|
||||||
Qstr::MP_QSTR_jpeg_info => obj_fn_1!(upy_jpeg_info).as_obj(),
|
Qstr::MP_QSTR_jpeg_info => obj_fn_1!(upy_jpeg_info).as_obj(),
|
||||||
|
|
||||||
/// def jpeg_test(data: bytes) -> bool:
|
/// def jpeg_test(data: bytes) -> bool:
|
||||||
@ -1662,7 +1646,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// def show_spending_details(
|
/// def show_spending_details(
|
||||||
/// *,
|
/// *,
|
||||||
/// account: str,
|
/// account: str,
|
||||||
/// fee_rate: str | None = None,
|
/// fee_rate: str | None,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Show metadata when for outgoing transaction."""
|
/// """Show metadata when for outgoing transaction."""
|
||||||
Qstr::MP_QSTR_show_spending_details => obj_fn_kw!(0, new_show_spending_details).as_obj(),
|
Qstr::MP_QSTR_show_spending_details => obj_fn_kw!(0, new_show_spending_details).as_obj(),
|
||||||
@ -1671,8 +1655,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// *,
|
/// *,
|
||||||
/// title: str,
|
/// title: str,
|
||||||
/// value: str,
|
/// value: str,
|
||||||
/// description: str | None = None,
|
/// description: str | None,
|
||||||
/// subtitle: str | None = None,
|
/// subtitle: str | None,
|
||||||
/// verb: str | None = None,
|
/// verb: str | None = None,
|
||||||
/// verb_cancel: str | None = None,
|
/// verb_cancel: str | None = None,
|
||||||
/// info_button: bool = False,
|
/// info_button: bool = False,
|
||||||
@ -1773,8 +1757,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// def show_simple(
|
/// def show_simple(
|
||||||
/// *,
|
/// *,
|
||||||
/// title: str | None,
|
/// title: str | None,
|
||||||
/// description: str,
|
/// description: str = "",
|
||||||
/// button: str | None = None,
|
/// button: str = "",
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Simple dialog with text and one button."""
|
/// """Simple dialog with text and one button."""
|
||||||
Qstr::MP_QSTR_show_simple => obj_fn_kw!(0, new_show_simple).as_obj(),
|
Qstr::MP_QSTR_show_simple => obj_fn_kw!(0, new_show_simple).as_obj(),
|
||||||
@ -1823,21 +1807,21 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// prompt: str,
|
/// prompt: str,
|
||||||
/// max_len: int,
|
/// max_len: int,
|
||||||
/// ) -> str | object:
|
/// ) -> str | object:
|
||||||
/// """Passphrase input keyboard."""
|
/// """Passphrase input keyboard."""
|
||||||
Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(),
|
Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(),
|
||||||
|
|
||||||
/// def request_bip39(
|
/// def request_bip39(
|
||||||
/// *,
|
/// *,
|
||||||
/// prompt: str,
|
/// prompt: str,
|
||||||
/// ) -> str:
|
/// ) -> str:
|
||||||
/// """BIP39 word input keyboard."""
|
/// """BIP39 word input keyboard."""
|
||||||
Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(),
|
Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(),
|
||||||
|
|
||||||
/// def request_slip39(
|
/// def request_slip39(
|
||||||
/// *,
|
/// *,
|
||||||
/// prompt: str,
|
/// prompt: str,
|
||||||
/// ) -> str:
|
/// ) -> str:
|
||||||
/// """SLIP39 word input keyboard."""
|
/// """SLIP39 word input keyboard."""
|
||||||
Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(),
|
Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(),
|
||||||
|
|
||||||
/// def select_word(
|
/// def select_word(
|
||||||
@ -1846,7 +1830,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// description: str,
|
/// description: str,
|
||||||
/// words: Iterable[str],
|
/// words: Iterable[str],
|
||||||
/// ) -> int:
|
/// ) -> int:
|
||||||
/// """Select mnemonic word from three possibilities - seed check after backup. The
|
/// """Select mnemonic word from three possibilities - seed check after backup. The
|
||||||
/// iterable must be of exact size. Returns index in range `0..3`."""
|
/// iterable must be of exact size. Returns index in range `0..3`."""
|
||||||
Qstr::MP_QSTR_select_word => obj_fn_kw!(0, new_select_word).as_obj(),
|
Qstr::MP_QSTR_select_word => obj_fn_kw!(0, new_select_word).as_obj(),
|
||||||
|
|
||||||
@ -1855,7 +1839,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// title: str,
|
/// title: str,
|
||||||
/// pages: Iterable[str],
|
/// pages: Iterable[str],
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
/// """Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
||||||
Qstr::MP_QSTR_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
Qstr::MP_QSTR_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
||||||
|
|
||||||
/// def request_number(
|
/// def request_number(
|
||||||
@ -1866,7 +1850,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// max_count: int,
|
/// max_count: int,
|
||||||
/// description: Callable[[int], str] | None = None,
|
/// description: Callable[[int], str] | None = None,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Number input with + and - buttons, description, and info button."""
|
/// """Number input with + and - buttons, description, and info button."""
|
||||||
Qstr::MP_QSTR_request_number => obj_fn_kw!(0, new_request_number).as_obj(),
|
Qstr::MP_QSTR_request_number => obj_fn_kw!(0, new_request_number).as_obj(),
|
||||||
|
|
||||||
/// def show_checklist(
|
/// def show_checklist(
|
||||||
@ -1876,8 +1860,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// active: int,
|
/// active: int,
|
||||||
/// button: str,
|
/// button: str,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Checklist of backup steps. Active index is highlighted, previous items have check
|
/// """Checklist of backup steps. Active index is highlighted, previous items have check
|
||||||
/// mark nex to them."""
|
/// mark next to them."""
|
||||||
Qstr::MP_QSTR_show_checklist => obj_fn_kw!(0, new_show_checklist).as_obj(),
|
Qstr::MP_QSTR_show_checklist => obj_fn_kw!(0, new_show_checklist).as_obj(),
|
||||||
|
|
||||||
/// def confirm_recovery(
|
/// def confirm_recovery(
|
||||||
@ -1886,41 +1870,41 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// description: str,
|
/// description: str,
|
||||||
/// button: str,
|
/// button: str,
|
||||||
/// dry_run: bool,
|
/// dry_run: bool,
|
||||||
/// info_button: bool,
|
/// info_button: bool = False,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Device recovery homescreen."""
|
/// """Device recovery homescreen."""
|
||||||
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),
|
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),
|
||||||
|
|
||||||
/// def select_word_count(
|
/// def select_word_count(
|
||||||
/// *,
|
/// *,
|
||||||
/// dry_run: bool,
|
/// dry_run: bool,
|
||||||
/// ) -> int | CANCELLED:
|
/// ) -> int | str: # TT returns int
|
||||||
/// """Select mnemonic word count from (12, 18, 20, 24, 33)."""
|
/// """Select mnemonic word count from (12, 18, 20, 24, 33)."""
|
||||||
Qstr::MP_QSTR_select_word_count => obj_fn_kw!(0, new_select_word_count).as_obj(),
|
Qstr::MP_QSTR_select_word_count => obj_fn_kw!(0, new_select_word_count).as_obj(),
|
||||||
|
|
||||||
/// def show_group_share_success(
|
/// def show_group_share_success(
|
||||||
/// *,
|
/// *,
|
||||||
/// lines: Iterable[str]
|
/// lines: Iterable[str]
|
||||||
/// ) -> int:
|
/// ) -> int:
|
||||||
/// """Shown after successfully finishing a group."""
|
/// """Shown after successfully finishing a group."""
|
||||||
Qstr::MP_QSTR_show_group_share_success => obj_fn_kw!(0, new_show_group_share_success).as_obj(),
|
Qstr::MP_QSTR_show_group_share_success => obj_fn_kw!(0, new_show_group_share_success).as_obj(),
|
||||||
|
|
||||||
/// def show_remaining_shares(
|
/// def show_remaining_shares(
|
||||||
/// *,
|
/// *,
|
||||||
/// pages: Iterable[tuple[str, str]],
|
/// pages: Iterable[tuple[str, str]],
|
||||||
/// ) -> int:
|
/// ) -> int:
|
||||||
/// """Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
/// """Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
||||||
Qstr::MP_QSTR_show_remaining_shares => obj_fn_kw!(0, new_show_remaining_shares).as_obj(),
|
Qstr::MP_QSTR_show_remaining_shares => obj_fn_kw!(0, new_show_remaining_shares).as_obj(),
|
||||||
|
|
||||||
/// def show_progress(
|
/// def show_progress(
|
||||||
/// *,
|
/// *,
|
||||||
/// title: str,
|
/// title: str,
|
||||||
/// indeterminate: bool = False,
|
/// indeterminate: bool = False,
|
||||||
/// description: str | None = None,
|
/// description: str = "",
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Show progress loader. Please note that the number of lines reserved on screen for
|
/// """Show progress loader. Please note that the number of lines reserved on screen for
|
||||||
/// description is determined at construction time. If you want multiline descriptions
|
/// description is determined at construction time. If you want multiline descriptions
|
||||||
/// make sure the initial desciption has at least that amount of lines."""
|
/// make sure the initial description has at least that amount of lines."""
|
||||||
Qstr::MP_QSTR_show_progress => obj_fn_kw!(0, new_show_progress).as_obj(),
|
Qstr::MP_QSTR_show_progress => obj_fn_kw!(0, new_show_progress).as_obj(),
|
||||||
|
|
||||||
/// def show_progress_coinjoin(
|
/// def show_progress_coinjoin(
|
||||||
@ -1930,7 +1914,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// time_ms: int = 0,
|
/// time_ms: int = 0,
|
||||||
/// skip_first_paint: bool = False,
|
/// skip_first_paint: bool = False,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Show progress loader for coinjoin. Returns CANCELLED after a specified time when
|
/// """Show progress loader for coinjoin. Returns CANCELLED after a specified time when
|
||||||
/// time_ms timeout is passed."""
|
/// time_ms timeout is passed."""
|
||||||
Qstr::MP_QSTR_show_progress_coinjoin => obj_fn_kw!(0, new_show_progress_coinjoin).as_obj(),
|
Qstr::MP_QSTR_show_progress_coinjoin => obj_fn_kw!(0, new_show_progress_coinjoin).as_obj(),
|
||||||
|
|
||||||
@ -1961,7 +1945,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
extern crate serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
trace::tests::trace,
|
trace::tests::trace,
|
||||||
|
Loading…
Reference in New Issue
Block a user