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)]
|
||||
#![allow(clippy::new_without_default)]
|
||||
#![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)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(optimize_attribute)]
|
||||
@ -40,6 +42,9 @@ fn panic_debug(panic_info: &core::panic::PanicInfo) -> ! {
|
||||
|
||||
if let Some(location) = panic_info.location() {
|
||||
let file = location.file();
|
||||
print!(file);
|
||||
print!(":");
|
||||
println!(inttostr!(location.line()));
|
||||
trezorhal::fatal_error::__fatal_error("", "rs", file, location.line(), "");
|
||||
} else {
|
||||
trezorhal::fatal_error::__fatal_error("", "rs", "", 0, "");
|
||||
|
@ -1,5 +1,5 @@
|
||||
#[cfg(feature = "ui_debug")]
|
||||
mod maybe_trace {
|
||||
mod maybe_trace_private {
|
||||
use crate::trace::Trace;
|
||||
|
||||
pub trait MaybeTrace: Trace {}
|
||||
@ -7,9 +7,9 @@ mod maybe_trace {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ui_debug"))]
|
||||
mod maybe_trace {
|
||||
mod maybe_trace_private {
|
||||
pub trait MaybeTrace {}
|
||||
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> {
|
||||
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) {
|
||||
@ -196,7 +196,6 @@ pub trait Trace {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
extern crate serde_json;
|
||||
use serde_json::Value;
|
||||
|
||||
use super::*;
|
||||
|
@ -215,7 +215,7 @@ where
|
||||
U: crate::trace::Trace,
|
||||
{
|
||||
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.1);
|
||||
});
|
||||
|
@ -6,6 +6,7 @@ use crate::{
|
||||
display,
|
||||
display::{Color, Font},
|
||||
geometry::Rect,
|
||||
util::animation_disabled,
|
||||
},
|
||||
};
|
||||
|
||||
@ -54,6 +55,11 @@ where
|
||||
}
|
||||
|
||||
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 {
|
||||
let text_width = self.font.text_width(self.text.as_ref());
|
||||
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> {
|
||||
// Not doing anything if animations are disabled.
|
||||
if animation_disabled() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
|
||||
if let Event::Timer(token) = event {
|
||||
|
@ -29,7 +29,9 @@ pub enum PageMsg<T, U> {
|
||||
}
|
||||
|
||||
pub trait Paginate {
|
||||
/// How many pages of content are there in total?
|
||||
fn page_count(&mut self) -> usize;
|
||||
/// Navigate to the given page.
|
||||
fn change_page(&mut self, active_page: usize);
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ where
|
||||
use core::cell::Cell;
|
||||
let fit: Cell<Option<LayoutFit>> = Cell::new(None);
|
||||
t.component("FormattedText");
|
||||
t.in_list("text", &mut |l| {
|
||||
t.in_list("text", &|l| {
|
||||
let result = self.layout_content(&mut TraceSink(l));
|
||||
fit.set(Some(result));
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
use super::iter::GlyphMetrics;
|
||||
use crate::ui::{
|
||||
display,
|
||||
display::{toif::Icon, Color, Font},
|
||||
display::{toif::Icon, Color, Font, GlyphMetrics},
|
||||
geometry::{Alignment, Dimensions, Offset, Point, Rect, BOTTOM_LEFT},
|
||||
};
|
||||
|
||||
@ -55,9 +54,9 @@ pub struct TextLayout {
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TextStyle {
|
||||
/// Text font ID. Can be overridden by `Op::Font`.
|
||||
/// Text font ID.
|
||||
pub text_font: Font,
|
||||
/// Text color. Can be overridden by `Op::Color`.
|
||||
/// Text color.
|
||||
pub text_color: Color,
|
||||
/// Background color.
|
||||
pub background_color: Color,
|
||||
@ -161,16 +160,19 @@ impl TextLayout {
|
||||
self
|
||||
}
|
||||
|
||||
/// Baseline `Point` where we are starting to draw the text.
|
||||
pub fn initial_cursor(&self) -> Point {
|
||||
let font = &self.style.text_font;
|
||||
self.bounds.top_left()
|
||||
+ 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 {
|
||||
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) {
|
||||
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(
|
||||
&self,
|
||||
text: &str,
|
||||
@ -225,11 +230,10 @@ impl TextLayout {
|
||||
sink: &mut dyn LayoutSink,
|
||||
) -> LayoutFit {
|
||||
let init_cursor = *cursor;
|
||||
let bottom = (self.bounds.y1 - self.padding_bottom).max(self.bounds.y0);
|
||||
let mut remaining_text = text;
|
||||
|
||||
// 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();
|
||||
return LayoutFit::OutOfBounds {
|
||||
processed_chars: 0,
|
||||
@ -244,6 +248,7 @@ impl TextLayout {
|
||||
) && self.continues_from_prev_page
|
||||
{
|
||||
sink.prev_page_ellipsis(*cursor, self);
|
||||
// Move the cursor to the right, always the same distance
|
||||
cursor.x += self.style.prev_page_ellipsis_width();
|
||||
}
|
||||
|
||||
@ -271,7 +276,12 @@ impl TextLayout {
|
||||
};
|
||||
|
||||
// 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.
|
||||
remaining_text = &remaining_text[span.length + span.skip_next_chars..];
|
||||
@ -287,7 +297,8 @@ impl TextLayout {
|
||||
sink.hyphen(*cursor, self);
|
||||
}
|
||||
// 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() {
|
||||
// Append ellipsis to indicate more content is available, but only if we
|
||||
// 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 {
|
||||
self.padding_top
|
||||
+ self.style.text_font.text_height()
|
||||
@ -336,7 +348,8 @@ impl TextLayout {
|
||||
+ 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)
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
/// Entire content fits. Vertical size is returned in `height`.
|
||||
Fitting { processed_chars: usize, height: i16 },
|
||||
@ -359,6 +375,7 @@ pub enum LayoutFit {
|
||||
}
|
||||
|
||||
impl LayoutFit {
|
||||
/// How high is the processed/fitted content.
|
||||
pub fn height(&self) -> i16 {
|
||||
match self {
|
||||
LayoutFit::Fitting { height, .. } => *height,
|
||||
@ -368,24 +385,36 @@ impl LayoutFit {
|
||||
}
|
||||
|
||||
/// Visitor for text segment operations.
|
||||
/// Defines responses for certain kind of events encountered
|
||||
/// when processing the content.
|
||||
pub trait LayoutSink {
|
||||
/// Text should be processed.
|
||||
fn text(&mut self, _cursor: Point, _layout: &TextLayout, _text: &str) {}
|
||||
/// Hyphen at the end of line.
|
||||
fn hyphen(&mut self, _cursor: Point, _layout: &TextLayout) {}
|
||||
/// Ellipsis at the end of the page.
|
||||
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) {}
|
||||
/// Line break - a newline.
|
||||
fn line_break(&mut self, _cursor: Point) {}
|
||||
/// Content cannot fit on the screen.
|
||||
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;
|
||||
|
||||
impl LayoutSink for TextNoOp {}
|
||||
|
||||
/// `LayoutSink` for rendering the content.
|
||||
pub struct TextRenderer;
|
||||
|
||||
impl LayoutSink for TextRenderer {
|
||||
fn text(&mut self, cursor: Point, layout: &TextLayout, text: &str) {
|
||||
display::text(
|
||||
display::text_left(
|
||||
cursor,
|
||||
text,
|
||||
layout.style.text_font,
|
||||
@ -395,7 +424,7 @@ impl LayoutSink for TextRenderer {
|
||||
}
|
||||
|
||||
fn hyphen(&mut self, cursor: Point, layout: &TextLayout) {
|
||||
display::text(
|
||||
display::text_left(
|
||||
cursor,
|
||||
"-",
|
||||
layout.style.text_font,
|
||||
@ -405,15 +434,16 @@ impl LayoutSink for TextRenderer {
|
||||
}
|
||||
|
||||
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(
|
||||
cursor,
|
||||
bottom_left,
|
||||
BOTTOM_LEFT,
|
||||
layout.style.ellipsis_color,
|
||||
layout.style.background_color,
|
||||
);
|
||||
} else {
|
||||
display::text(
|
||||
display::text_left(
|
||||
cursor,
|
||||
ELLIPSIS,
|
||||
layout.style.text_font,
|
||||
@ -424,7 +454,7 @@ impl LayoutSink for TextRenderer {
|
||||
}
|
||||
|
||||
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(
|
||||
cursor,
|
||||
BOTTOM_LEFT,
|
||||
@ -432,7 +462,7 @@ impl LayoutSink for TextRenderer {
|
||||
layout.style.background_color,
|
||||
);
|
||||
} else {
|
||||
display::text(
|
||||
display::text_left(
|
||||
cursor,
|
||||
ELLIPSIS,
|
||||
layout.style.text_font,
|
||||
@ -454,23 +484,23 @@ pub mod trace {
|
||||
|
||||
impl LayoutSink for TraceSink<'_> {
|
||||
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) {
|
||||
self.0.string(&"-");
|
||||
self.0.string("-");
|
||||
}
|
||||
|
||||
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) {
|
||||
self.0.string(&ELLIPSIS);
|
||||
self.0.string(ELLIPSIS);
|
||||
}
|
||||
|
||||
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)]
|
||||
struct Span {
|
||||
/// How many characters from the input text this span is laying out.
|
||||
@ -603,7 +635,7 @@ impl Span {
|
||||
}
|
||||
found_any_whitespace = true;
|
||||
} else if span_width + char_width > max_width {
|
||||
// Return the last breakpoint.
|
||||
// Cannot fit on this line. Return the last breakpoint.
|
||||
return line;
|
||||
} else {
|
||||
let have_space_for_break =
|
||||
@ -625,7 +657,7 @@ impl Span {
|
||||
span_width += char_width;
|
||||
}
|
||||
|
||||
// The whole text is fitting.
|
||||
// The whole text is fitting on the current line.
|
||||
Self {
|
||||
length: text.len(),
|
||||
advance: Offset::x(span_width),
|
||||
|
@ -239,13 +239,13 @@ pub mod trace {
|
||||
impl<T: ParagraphSource> crate::trace::Trace for Paragraphs<T> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.string("component", "Paragraphs");
|
||||
t.in_list("paragraphs", &mut |par_list| {
|
||||
t.in_list("paragraphs", &|par_list| {
|
||||
Self::foreach_visible(
|
||||
&self.source,
|
||||
&self.visible,
|
||||
self.offset,
|
||||
&mut |layout, content| {
|
||||
par_list.in_list(&mut |par| {
|
||||
par_list.in_list(&|par| {
|
||||
layout.layout_text(
|
||||
content,
|
||||
&mut layout.initial_cursor(),
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::ui::{
|
||||
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},
|
||||
};
|
||||
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) {
|
||||
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) {
|
||||
|
@ -15,6 +15,9 @@ use crate::trezorhal::{
|
||||
},
|
||||
uzlib::UZLIB_WINDOW_SIZE,
|
||||
};
|
||||
#[cfg(feature = "dma2d")]
|
||||
use crate::ui::component::image::Image;
|
||||
|
||||
#[cfg(not(feature = "dma2d"))]
|
||||
use crate::ui::geometry::TOP_LEFT;
|
||||
|
||||
@ -23,12 +26,11 @@ use crate::{
|
||||
trezorhal::{buffers, display, time, uzlib::UzlibContext},
|
||||
ui::lerp::Lerp,
|
||||
};
|
||||
use core::slice;
|
||||
|
||||
#[cfg(feature = "dma2d")]
|
||||
use crate::ui::component::image::Image;
|
||||
// Reexports
|
||||
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 fn backlight() -> u16 {
|
||||
@ -58,6 +60,7 @@ pub fn fade_backlight_duration(target: u16, duration_ms: u32) {
|
||||
set_backlight(target as u16);
|
||||
}
|
||||
|
||||
/// Fill a whole rectangle with a specific color.
|
||||
pub fn rect_fill(r: Rect, fg_color: Color) {
|
||||
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());
|
||||
}
|
||||
|
||||
/// Draw a rectangle with rounded corners.
|
||||
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));
|
||||
display::bar_radius(
|
||||
r.x0,
|
||||
r.y0,
|
||||
r.width(),
|
||||
r.height(),
|
||||
fg_color.into(),
|
||||
bg_color.into(),
|
||||
radius,
|
||||
);
|
||||
if radius == 1 {
|
||||
rect_fill_rounded1(r, fg_color, bg_color);
|
||||
} else {
|
||||
assert!([2, 4, 8, 16].iter().any(|allowed| radius == *allowed));
|
||||
display::bar_radius(
|
||||
r.x0,
|
||||
r.y0,
|
||||
r.width(),
|
||||
r.height(),
|
||||
fg_color.into(),
|
||||
bg_color.into(),
|
||||
radius,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Used on T1 only.
|
||||
pub 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());
|
||||
let corners = [
|
||||
r.top_left(),
|
||||
r.top_right() - Offset::x(1),
|
||||
r.bottom_right() - Offset::uniform(1),
|
||||
r.bottom_left() - Offset::y(1),
|
||||
];
|
||||
for p in corners.iter() {
|
||||
display::bar(p.x, p.y, 1, 1, bg_color.into());
|
||||
/// Filling a rectangle with a rounding of 1 pixel - removing the corners.
|
||||
fn rect_fill_rounded1(r: Rect, fg_color: Color, bg_color: Color) {
|
||||
rect_fill(r, fg_color);
|
||||
rect_fill_corners(r, bg_color);
|
||||
}
|
||||
|
||||
/// Creating a rectangular outline with a given radius/rounding.
|
||||
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
|
||||
// to create the outline.
|
||||
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,
|
||||
font,
|
||||
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(
|
||||
baseline.x,
|
||||
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) {
|
||||
let w = font.text_width(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) {
|
||||
let w = font.text_width(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
|
||||
/// 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)]
|
||||
pub struct Rect {
|
||||
pub x0: i16,
|
||||
@ -304,10 +306,12 @@ impl Rect {
|
||||
self.bottom_left().center(self.bottom_right())
|
||||
}
|
||||
|
||||
/// Whether a `Point` is inside the `Rect`.
|
||||
pub const fn contains(&self, point: Point) -> bool {
|
||||
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 {
|
||||
Self {
|
||||
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 {
|
||||
Self {
|
||||
x0: self.x0 + insets.left,
|
||||
@ -335,24 +341,12 @@ impl Rect {
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn cut_from_left(&self, width: i16) -> Self {
|
||||
Self {
|
||||
x0: self.x0,
|
||||
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,
|
||||
}
|
||||
/// Move all the sides closer to the center by the same distance.
|
||||
pub const fn shrink(&self, size: i16) -> Self {
|
||||
self.inset(Insets::uniform(size))
|
||||
}
|
||||
|
||||
/// Split `Rect` into top and bottom, given the top one's `height`.
|
||||
pub const fn split_top(self, height: i16) -> (Self, Self) {
|
||||
let height = clamp(height, 0, self.height());
|
||||
|
||||
@ -367,10 +361,12 @@ impl Rect {
|
||||
(top, bottom)
|
||||
}
|
||||
|
||||
/// Split `Rect` into top and bottom, given the bottom one's `height`.
|
||||
pub const fn split_bottom(self, height: i16) -> (Self, Self) {
|
||||
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) {
|
||||
let width = clamp(width, 0, self.width());
|
||||
|
||||
@ -385,6 +381,7 @@ impl Rect {
|
||||
(left, right)
|
||||
}
|
||||
|
||||
/// Split `Rect` into left and right, given the right one's `width`.
|
||||
pub const fn split_right(self, width: i16) -> (Self, Self) {
|
||||
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 {
|
||||
Self {
|
||||
x0: self.x0 + offset.x,
|
||||
@ -414,6 +412,16 @@ impl Rect {
|
||||
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)]
|
||||
@ -538,7 +546,7 @@ impl Grid {
|
||||
let cell_height = (self.area.height() - spacing_height) / nrows;
|
||||
|
||||
// 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.
|
||||
let leftover_width = (self.area.width() - spacing_width) % ncols;
|
||||
let leftover_height = (self.area.height() - spacing_height) % nrows;
|
||||
|
@ -19,7 +19,7 @@ use crate::ui::{
|
||||
text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt},
|
||||
Event, EventCtx,
|
||||
},
|
||||
constant::{screen, BACKLIGHT_NORMAL, WIDTH},
|
||||
constant::{screen, WIDTH},
|
||||
display::{fade_backlight_duration, Color, Icon, TextOverlay},
|
||||
event::ButtonEvent,
|
||||
geometry::{LinearPlacement, Offset, Rect, CENTER},
|
||||
@ -31,7 +31,7 @@ use crate::ui::{
|
||||
theme::{bld_button_cancel, bld_button_default, BLD_BG, BLD_FG},
|
||||
},
|
||||
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},
|
||||
};
|
||||
|
@ -132,12 +132,12 @@ where
|
||||
ButtonContent::Text(text) => {
|
||||
let background_color = style.text_color.negate();
|
||||
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 {
|
||||
display::rect_fill(self.area, background_color)
|
||||
}
|
||||
|
||||
display::text(
|
||||
display::text_left(
|
||||
self.baseline,
|
||||
text.as_ref(),
|
||||
style.font,
|
||||
|
@ -83,7 +83,11 @@ where
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("Dialog");
|
||||
t.child("content", &self.content);
|
||||
self.left_btn.as_ref().map(|b| t.child("left", b));
|
||||
self.right_btn.as_ref().map(|b| t.child("right", b));
|
||||
if let Some(b) = self.left_btn.as_ref() {
|
||||
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) {
|
||||
display::text(
|
||||
display::text_left(
|
||||
self.area.bottom_left() - Offset::y(2),
|
||||
self.title.as_ref(),
|
||||
Font::BOLD,
|
||||
|
@ -160,8 +160,12 @@ impl<S: ParagraphStrType> crate::trace::Trace for ResultPopup<S> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("ResultPopup");
|
||||
t.child("text", &self.text);
|
||||
self.button.as_ref().map(|b| t.child("button", b));
|
||||
self.headline.as_ref().map(|h| t.child("headline", h));
|
||||
if let Some(b) = self.button.as_ref() {
|
||||
t.child("button", b)
|
||||
}
|
||||
if let Some(h) = self.headline.as_ref() {
|
||||
t.child("headline", h)
|
||||
}
|
||||
t.child("result_anim", &self.result_anim);
|
||||
}
|
||||
}
|
||||
|
@ -144,98 +144,3 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Confirm text."""
|
||||
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};
|
||||
|
||||
// Typical backlight values.
|
||||
pub const BACKLIGHT_NORMAL: u16 = 150;
|
||||
|
||||
// Color palette.
|
||||
pub const WHITE: Color = Color::rgb(255, 255, 255);
|
||||
pub const BLACK: Color = Color::rgb(0, 0, 0);
|
||||
|
@ -200,7 +200,7 @@ impl<T> Button<T> {
|
||||
let start_of_baseline = self.area.center()
|
||||
+ Offset::new(-width / 2, height / 2)
|
||||
+ Offset::y(Self::BASELINE_OFFSET);
|
||||
display::text(
|
||||
display::text_left(
|
||||
start_of_baseline,
|
||||
text,
|
||||
style.font,
|
||||
@ -575,7 +575,7 @@ impl IconText {
|
||||
}
|
||||
|
||||
if use_text {
|
||||
display::text(
|
||||
display::text_left(
|
||||
text_pos,
|
||||
self.text,
|
||||
style.font,
|
||||
|
@ -191,8 +191,13 @@ where
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("Frame");
|
||||
t.child("title", &self.title);
|
||||
self.subtitle.as_ref().map(|s| t.child("subtitle", s));
|
||||
self.button.as_ref().map(|b| t.child("button", b));
|
||||
t.child("content", &self.content);
|
||||
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::{
|
||||
trezorhal::bip39,
|
||||
ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
component::{text::common::TextBox, Component, Event, EventCtx},
|
||||
display,
|
||||
display::toif::Icon,
|
||||
geometry::{Offset, Rect, CENTER},
|
||||
model_tt::{
|
||||
component::{
|
||||
keyboard::{
|
||||
common::{paint_pending_marker, MultiTapKeyboard, TextBox},
|
||||
common::{paint_pending_marker, MultiTapKeyboard},
|
||||
mnemonic::{MnemonicInput, MnemonicInputMsg, MNEMONIC_KEY_COUNT},
|
||||
},
|
||||
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
|
||||
// to the bottom.
|
||||
let text_baseline = area.top_left().center(area.bottom_left()) + Offset::new(16, 8);
|
||||
display::text(
|
||||
display::text_left(
|
||||
text_baseline,
|
||||
text,
|
||||
style.font,
|
||||
@ -121,7 +121,7 @@ impl Component for Bip39Input {
|
||||
// Paint the rest of the suggested dictionary word.
|
||||
if let Some(word) = self.suggested_word.and_then(|w| w.get(text.len()..)) {
|
||||
let word_baseline = text_baseline + Offset::new(width, 0);
|
||||
display::text(
|
||||
display::text_left(
|
||||
word_baseline,
|
||||
word,
|
||||
style.font,
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::ui::{
|
||||
component::{base::ComponentExt, Child, Component, Event, EventCtx, Never},
|
||||
component::{
|
||||
base::ComponentExt, text::common::TextBox, Child, Component, Event, EventCtx, Never,
|
||||
},
|
||||
display,
|
||||
display::toif::Icon,
|
||||
geometry::{Grid, Offset, Rect},
|
||||
model_tt::component::{
|
||||
button::{Button, ButtonContent, ButtonMsg},
|
||||
keyboard::common::{paint_pending_marker, MultiTapKeyboard, TextBox},
|
||||
keyboard::common::{paint_pending_marker, MultiTapKeyboard},
|
||||
swipe::{Swipe, SwipeDirection},
|
||||
theme, ScrollBar,
|
||||
},
|
||||
@ -378,5 +380,6 @@ impl Component for Input {
|
||||
impl crate::trace::Trace for PassphraseKeyboard {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("PassphraseKeyboard");
|
||||
t.string("passphrase", self.passphrase());
|
||||
}
|
||||
}
|
||||
|
@ -468,5 +468,16 @@ where
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
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::{
|
||||
trezorhal::slip39,
|
||||
ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
component::{
|
||||
text::common::{TextBox, TextEdit},
|
||||
Component, Event, EventCtx,
|
||||
},
|
||||
display,
|
||||
display::toif::Icon,
|
||||
geometry::{Offset, Rect, CENTER},
|
||||
model_tt::{
|
||||
component::{
|
||||
keyboard::{
|
||||
common::{paint_pending_marker, MultiTapKeyboard, TextBox, TextEdit},
|
||||
common::{paint_pending_marker, MultiTapKeyboard},
|
||||
mnemonic::{MnemonicInput, MnemonicInputMsg, MNEMONIC_KEY_COUNT},
|
||||
},
|
||||
Button, ButtonContent, ButtonMsg,
|
||||
@ -156,7 +159,7 @@ impl Component for Slip39Input {
|
||||
.assert_if_debugging_ui("Text buffer is too small");
|
||||
}
|
||||
}
|
||||
display::text(
|
||||
display::text_left(
|
||||
text_baseline,
|
||||
text.as_str(),
|
||||
style.font,
|
||||
|
@ -494,7 +494,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate serde_json;
|
||||
use serde_json;
|
||||
|
||||
use crate::{
|
||||
trace::tests::trace,
|
||||
|
@ -9,8 +9,6 @@ pub const LOADER_OUTER: i16 = 60;
|
||||
pub const LOADER_INNER: i16 = 42;
|
||||
pub const LOADER_ICON_MAX_SIZE: i16 = 64;
|
||||
|
||||
pub const BACKLIGHT_NORMAL: i32 = 150;
|
||||
|
||||
pub const fn size() -> Offset {
|
||||
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 {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title).unwrap().try_into().unwrap();
|
||||
let description: StrBuffer = kwargs
|
||||
.get(Qstr::MP_QSTR_description)
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.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 title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.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 paragraphs = Paragraphs::new([
|
||||
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 {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let dry_run: bool = kwargs
|
||||
.get(Qstr::MP_QSTR_dry_run)
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
|
||||
let title = if dry_run {
|
||||
"SEED CHECK"
|
||||
} else {
|
||||
@ -1554,7 +1538,7 @@ extern "C" fn draw_welcome_screen() -> Obj {
|
||||
screen.place(constant::screen());
|
||||
display::sync();
|
||||
screen.paint();
|
||||
display::set_backlight(150); // BACKLIGHT_NORMAL
|
||||
display::set_backlight(theme::BACKLIGHT_NORMAL);
|
||||
Obj::const_none()
|
||||
}
|
||||
|
||||
@ -1575,8 +1559,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Disable animations, debug builds only."""
|
||||
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):
|
||||
/// """Get JPEG image dimensions."""
|
||||
/// def jpeg_info(data: bytes) -> tuple[int, int, int]:
|
||||
/// """Get JPEG image dimensions (width: int, height: int, mcu_height: int)."""
|
||||
Qstr::MP_QSTR_jpeg_info => obj_fn_1!(upy_jpeg_info).as_obj(),
|
||||
|
||||
/// def jpeg_test(data: bytes) -> bool:
|
||||
@ -1662,7 +1646,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// def show_spending_details(
|
||||
/// *,
|
||||
/// account: str,
|
||||
/// fee_rate: str | None = None,
|
||||
/// fee_rate: str | None,
|
||||
/// ) -> object:
|
||||
/// """Show metadata when for outgoing transaction."""
|
||||
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,
|
||||
/// value: str,
|
||||
/// description: str | None = None,
|
||||
/// subtitle: str | None = None,
|
||||
/// description: str | None,
|
||||
/// subtitle: str | None,
|
||||
/// verb: str | None = None,
|
||||
/// verb_cancel: str | None = None,
|
||||
/// info_button: bool = False,
|
||||
@ -1773,8 +1757,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// def show_simple(
|
||||
/// *,
|
||||
/// title: str | None,
|
||||
/// description: str,
|
||||
/// button: str | None = None,
|
||||
/// description: str = "",
|
||||
/// button: str = "",
|
||||
/// ) -> object:
|
||||
/// """Simple dialog with text and one button."""
|
||||
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,
|
||||
/// max_len: int,
|
||||
/// ) -> str | object:
|
||||
/// """Passphrase input keyboard."""
|
||||
/// """Passphrase input keyboard."""
|
||||
Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(),
|
||||
|
||||
/// def request_bip39(
|
||||
/// *,
|
||||
/// prompt: str,
|
||||
/// ) -> str:
|
||||
/// """BIP39 word input keyboard."""
|
||||
/// """BIP39 word input keyboard."""
|
||||
Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(),
|
||||
|
||||
/// def request_slip39(
|
||||
/// *,
|
||||
/// prompt: str,
|
||||
/// ) -> str:
|
||||
/// """SLIP39 word input keyboard."""
|
||||
/// """SLIP39 word input keyboard."""
|
||||
Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(),
|
||||
|
||||
/// def select_word(
|
||||
@ -1846,7 +1830,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// description: str,
|
||||
/// words: Iterable[str],
|
||||
/// ) -> 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`."""
|
||||
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,
|
||||
/// pages: Iterable[str],
|
||||
/// ) -> 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(),
|
||||
|
||||
/// def request_number(
|
||||
@ -1866,7 +1850,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// max_count: int,
|
||||
/// description: Callable[[int], str] | None = None,
|
||||
/// ) -> 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(),
|
||||
|
||||
/// def show_checklist(
|
||||
@ -1876,8 +1860,8 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// active: int,
|
||||
/// button: str,
|
||||
/// ) -> object:
|
||||
/// """Checklist of backup steps. Active index is highlighted, previous items have check
|
||||
/// mark nex to them."""
|
||||
/// """Checklist of backup steps. Active index is highlighted, previous items have check
|
||||
/// mark next to them."""
|
||||
Qstr::MP_QSTR_show_checklist => obj_fn_kw!(0, new_show_checklist).as_obj(),
|
||||
|
||||
/// def confirm_recovery(
|
||||
@ -1886,41 +1870,41 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// description: str,
|
||||
/// button: str,
|
||||
/// dry_run: bool,
|
||||
/// info_button: bool,
|
||||
/// info_button: bool = False,
|
||||
/// ) -> object:
|
||||
/// """Device recovery homescreen."""
|
||||
/// """Device recovery homescreen."""
|
||||
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),
|
||||
|
||||
/// def select_word_count(
|
||||
/// *,
|
||||
/// dry_run: bool,
|
||||
/// ) -> int | CANCELLED:
|
||||
/// """Select mnemonic word count from (12, 18, 20, 24, 33)."""
|
||||
/// ) -> int | str: # TT returns int
|
||||
/// """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(),
|
||||
|
||||
/// def show_group_share_success(
|
||||
/// *,
|
||||
/// lines: Iterable[str]
|
||||
/// ) -> 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(),
|
||||
|
||||
/// def show_remaining_shares(
|
||||
/// *,
|
||||
/// pages: Iterable[tuple[str, str]],
|
||||
/// ) -> 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(),
|
||||
|
||||
/// def show_progress(
|
||||
/// *,
|
||||
/// title: str,
|
||||
/// indeterminate: bool = False,
|
||||
/// description: str | None = None,
|
||||
/// description: str = "",
|
||||
/// ) -> 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
|
||||
/// 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(),
|
||||
|
||||
/// def show_progress_coinjoin(
|
||||
@ -1930,7 +1914,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// time_ms: int = 0,
|
||||
/// skip_first_paint: bool = False,
|
||||
/// ) -> 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."""
|
||||
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)]
|
||||
mod tests {
|
||||
extern crate serde_json;
|
||||
use serde_json;
|
||||
|
||||
use crate::{
|
||||
trace::tests::trace,
|
||||
|
Loading…
Reference in New Issue
Block a user