1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-30 15:05:43 +00:00

chore(core/rust): delete model_1 code - it should use model_r

[no changelog]
This commit is contained in:
grdddj 2022-12-31 13:36:29 +01:00 committed by matejcik
parent a480bf0f18
commit f8c432e955
18 changed files with 57 additions and 1062 deletions

View File

@ -133,22 +133,6 @@ core fw btconly production build:
- firmware-T2T1-btconly-production-*.*.*-$CI_COMMIT_SHORT_SHA.bin - firmware-T2T1-btconly-production-*.*.*-$CI_COMMIT_SHORT_SHA.bin
expire_in: 1 week expire_in: 1 week
core fw btconly t1 build:
stage: build
<<: *gitlab_caching
needs: []
variables:
BITCOIN_ONLY: "1"
TREZOR_MODEL: "1"
script:
- nix-shell --run "poetry run make -C core build_firmware"
- cp core/build/firmware/firmware.bin firmware-T1B1-btconly-t1-$CORE_VERSION-$CI_COMMIT_SHORT_SHA.bin
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA"
paths:
- firmware-T1B1-btconly-t1-*.*.*-$CI_COMMIT_SHORT_SHA.bin
expire_in: 1 week
# Non-frozen emulator build. This means you still need Python files # Non-frozen emulator build. This means you still need Python files
# present which get interpreted. # present which get interpreted.
core unix regular build: core unix regular build:
@ -289,22 +273,6 @@ core unix frozen debug build arm:
tags: tags:
- docker_darwin_arm - docker_darwin_arm
core unix frozen btconly debug t1 build:
stage: build
<<: *gitlab_caching
needs: []
variables:
BITCOIN_ONLY: "1"
TREZOR_MODEL: "1"
script:
- nix-shell --run "poetry run make -C core build_unix_frozen"
- mv core/build/unix/trezor-emu-core core/build/unix/trezor-emu-core-bitcoinonly
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA"
paths:
- core/build/unix # most of it needed by test_rust
expire_in: 1 week
core macos frozen regular build: core macos frozen regular build:
stage: build stage: build
<<: *gitlab_caching <<: *gitlab_caching

View File

@ -47,17 +47,6 @@ core unit asan test:
- nix-shell --run "poetry run make -C core clean build_unix | ts -s" - nix-shell --run "poetry run make -C core clean build_unix | ts -s"
- nix-shell --run "poetry run make -C core test_rust | ts -s" - nix-shell --run "poetry run make -C core test_rust | ts -s"
core unit t1 test:
stage: test
<<: *gitlab_caching
needs:
- core unix frozen btconly debug t1 build
variables:
BITCOIN_ONLY: "1"
TREZOR_MODEL: "1"
script:
- nix-shell --run "poetry run make -C core test_rust | ts -s"
# Device tests for Core. Running device tests and also comparing screens # Device tests for Core. Running device tests and also comparing screens
# with the expected UI result. # with the expected UI result.
# See artifacts for a comprehensive report of UI. # See artifacts for a comprehensive report of UI.

View File

@ -715,7 +715,9 @@ def cargo_build():
else: else:
profile = '' profile = ''
features = ['micropython', 'protobuf', f'model_t{TREZOR_MODEL.lower()}'] # T1 does not have its own Rust feature, it shares it with TR
model_feature = 'model_tr' if TREZOR_MODEL == '1' else f'model_t{TREZOR_MODEL.lower()}'
features = ['micropython', 'protobuf', model_feature]
if BITCOIN_ONLY == '1': if BITCOIN_ONLY == '1':
features.append('bitcoin_only') features.append('bitcoin_only')
features.append('ui') features.append('ui')

View File

@ -667,7 +667,9 @@ RUST_LIB = 'trezor_lib'
RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a' RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a'
def cargo_build(): def cargo_build():
features = ['micropython', 'protobuf', f'model_t{TREZOR_MODEL.lower()}'] # T1 does not have its own Rust feature, it shares it with TR
model_feature = 'model_tr' if TREZOR_MODEL == '1' else f'model_t{TREZOR_MODEL.lower()}'
features = ['micropython', 'protobuf', model_feature]
if BITCOIN_ONLY == '1': if BITCOIN_ONLY == '1':
features.append('bitcoin_only') features.append('bitcoin_only')
features.append('ui') features.append('ui')

View File

@ -9,7 +9,6 @@ build = "build.rs"
default = ["model_tt"] default = ["model_tt"]
bitcoin_only = [] bitcoin_only = []
model_tt = ["touch", "jpeg"] model_tt = ["touch", "jpeg"]
model_t1 = ["buttons"]
model_tr = ["buttons"] model_tr = ["buttons"]
micropython = [] micropython = []
protobuf = ["micropython"] protobuf = ["micropython"]

View File

@ -1,12 +1,6 @@
//! Reexporting the `constant` module according to the //! Reexporting the `constant` module according to the
//! current feature (Trezor model) //! current feature (Trezor model)
#[cfg(all(
feature = "model_t1",
not(feature = "model_tr"),
not(feature = "model_tt")
))]
pub use super::model_t1::constant::*;
#[cfg(all(feature = "model_tr", not(feature = "model_tt")))] #[cfg(all(feature = "model_tr", not(feature = "model_tt")))]
pub use super::model_tr::constant::*; pub use super::model_tr::constant::*;
#[cfg(feature = "model_tt")] #[cfg(feature = "model_tt")]

View File

@ -13,8 +13,6 @@ mod util;
#[cfg(feature = "micropython")] #[cfg(feature = "micropython")]
pub mod layout; pub mod layout;
#[cfg(feature = "model_t1")]
pub mod model_t1;
#[cfg(feature = "model_tr")] #[cfg(feature = "model_tr")]
pub mod model_tr; pub mod model_tr;
#[cfg(feature = "model_tt")] #[cfg(feature = "model_tt")]

View File

@ -1,190 +0,0 @@
use crate::ui::{
component::{Component, Event, EventCtx},
display::{self, Color, Font},
event::{ButtonEvent, PhysicalButton},
geometry::{Offset, Point, Rect},
};
use super::theme;
pub enum ButtonMsg {
Clicked,
}
#[derive(Copy, Clone)]
pub enum ButtonPos {
Left,
Right,
}
impl ButtonPos {
fn hit(&self, b: &PhysicalButton) -> bool {
matches!(
(self, b),
(Self::Left, PhysicalButton::Left) | (Self::Right, PhysicalButton::Right)
)
}
}
pub struct Button<T> {
area: Rect,
pos: ButtonPos,
baseline: Point,
content: ButtonContent<T>,
styles: ButtonStyleSheet,
state: State,
}
impl<T: AsRef<str>> Button<T> {
pub fn new(pos: ButtonPos, content: ButtonContent<T>, styles: ButtonStyleSheet) -> Self {
Self {
pos,
content,
styles,
baseline: Point::zero(),
area: Rect::zero(),
state: State::Released,
}
}
pub fn with_text(pos: ButtonPos, text: T, styles: ButtonStyleSheet) -> Self {
Self::new(pos, ButtonContent::Text(text), styles)
}
pub fn with_icon(pos: ButtonPos, image: &'static [u8], styles: ButtonStyleSheet) -> Self {
Self::new(pos, ButtonContent::Icon(image), styles)
}
pub fn content(&self) -> &ButtonContent<T> {
&self.content
}
fn style(&self) -> &ButtonStyle {
match self.state {
State::Released => self.styles.normal,
State::Pressed => self.styles.active,
}
}
fn set(&mut self, ctx: &mut EventCtx, state: State) {
if self.state != state {
self.state = state;
ctx.request_paint();
}
}
fn placement(
area: Rect,
pos: ButtonPos,
content: &ButtonContent<T>,
styles: &ButtonStyleSheet,
) -> (Rect, Point) {
let border_width = if styles.normal.border_horiz { 2 } else { 0 };
let content_width = match content {
ButtonContent::Text(text) => styles.normal.font.text_width(text.as_ref()) - 1,
ButtonContent::Icon(_icon) => todo!(),
};
let button_width = content_width + 2 * border_width;
let area = match pos {
ButtonPos::Left => area.split_left(button_width).0,
ButtonPos::Right => area.split_right(button_width).1,
};
let start_of_baseline = area.bottom_left() + Offset::new(border_width, -2);
(area, start_of_baseline)
}
}
impl<T> Component for Button<T>
where
T: AsRef<str>,
{
type Msg = ButtonMsg;
fn place(&mut self, bounds: Rect) -> Rect {
let (area, baseline) = Self::placement(bounds, self.pos, &self.content, &self.styles);
self.area = area;
self.baseline = baseline;
self.area
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
match event {
Event::Button(ButtonEvent::ButtonPressed(which)) if self.pos.hit(&which) => {
self.set(ctx, State::Pressed);
}
Event::Button(ButtonEvent::ButtonReleased(which)) if self.pos.hit(&which) => {
if matches!(self.state, State::Pressed) {
self.set(ctx, State::Released);
return Some(ButtonMsg::Clicked);
}
}
_ => {}
};
None
}
fn paint(&mut self) {
let style = self.style();
match &self.content {
ButtonContent::Text(text) => {
let background_color = style.text_color.negate();
if style.border_horiz {
display::rect_fill_rounded1(self.area, background_color, theme::BG);
} else {
display::rect_fill(self.area, background_color)
}
display::text(
self.baseline,
text.as_ref(),
style.font,
style.text_color,
background_color,
);
}
ButtonContent::Icon(_image) => {
todo!();
}
}
}
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Button<T>
where
T: AsRef<str> + crate::trace::Trace,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Button");
match &self.content {
ButtonContent::Text(text) => t.field("text", text),
ButtonContent::Icon(_) => t.symbol("icon"),
}
t.close();
}
}
#[derive(PartialEq, Eq)]
enum State {
Released,
Pressed,
}
pub enum ButtonContent<T> {
Text(T),
Icon(&'static [u8]),
}
pub struct ButtonStyleSheet {
pub normal: &'static ButtonStyle,
pub active: &'static ButtonStyle,
}
pub struct ButtonStyle {
pub font: Font,
pub text_color: Color,
pub border_horiz: bool,
}

View File

@ -1,94 +0,0 @@
use super::button::{Button, ButtonMsg::Clicked};
use crate::ui::{
component::{Child, Component, Event, EventCtx},
display::Font,
geometry::Rect,
};
pub enum DialogMsg<T> {
Content(T),
LeftClicked,
RightClicked,
}
pub struct Dialog<T, U> {
content: Child<T>,
left_btn: Option<Child<Button<U>>>,
right_btn: Option<Child<Button<U>>>,
}
impl<T, U> Dialog<T, U>
where
T: Component,
U: AsRef<str>,
{
pub fn new(content: T, left: Option<Button<U>>, right: Option<Button<U>>) -> Self {
Self {
content: Child::new(content),
left_btn: left.map(Child::new),
right_btn: right.map(Child::new),
}
}
pub fn inner(&self) -> &T {
self.content.inner()
}
}
impl<T, U> Component for Dialog<T, U>
where
T: Component,
U: AsRef<str>,
{
type Msg = DialogMsg<T::Msg>;
fn place(&mut self, bounds: Rect) -> Rect {
let button_height = Font::BOLD.line_height() + 2;
let (content_area, button_area) = bounds.split_bottom(button_height);
self.content.place(content_area);
self.left_btn.as_mut().map(|b| b.place(button_area));
self.right_btn.as_mut().map(|b| b.place(button_area));
bounds
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
if let Some(msg) = self.content.event(ctx, event) {
Some(DialogMsg::Content(msg))
} else if let Some(Clicked) = self.left_btn.as_mut().and_then(|b| b.event(ctx, event)) {
Some(DialogMsg::LeftClicked)
} else if let Some(Clicked) = self.right_btn.as_mut().and_then(|b| b.event(ctx, event)) {
Some(DialogMsg::RightClicked)
} else {
None
}
}
fn paint(&mut self) {
self.content.paint();
if let Some(b) = self.left_btn.as_mut() {
b.paint();
}
if let Some(b) = self.right_btn.as_mut() {
b.paint();
}
}
}
#[cfg(feature = "ui_debug")]
impl<T, U> crate::trace::Trace for Dialog<T, U>
where
T: crate::trace::Trace,
U: crate::trace::Trace + AsRef<str>,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Dialog");
t.field("content", &self.content);
if let Some(label) = &self.left_btn {
t.field("left", label);
}
if let Some(label) = &self.right_btn {
t.field("right", label);
}
t.close();
}
}

View File

@ -1,79 +0,0 @@
use super::theme;
use crate::ui::{
component::{Child, Component, Event, EventCtx},
display::{self, Font},
geometry::{Insets, Offset, Rect},
};
pub struct Frame<T, U> {
area: Rect,
title: U,
content: Child<T>,
}
impl<T, U> Frame<T, U>
where
T: Component,
U: AsRef<str>,
{
pub fn new(title: U, content: T) -> Self {
Self {
title,
area: Rect::zero(),
content: Child::new(content),
}
}
pub fn inner(&self) -> &T {
self.content.inner()
}
}
impl<T, U> Component for Frame<T, U>
where
T: Component,
U: AsRef<str>,
{
type Msg = T::Msg;
fn place(&mut self, bounds: Rect) -> Rect {
const TITLE_SPACE: i16 = 4;
let (title_area, content_area) = bounds.split_top(Font::BOLD.line_height());
let content_area = content_area.inset(Insets::top(TITLE_SPACE));
self.area = title_area;
self.content.place(content_area);
bounds
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
self.content.event(ctx, event)
}
fn paint(&mut self) {
display::text(
self.area.bottom_left() - Offset::y(2),
self.title.as_ref(),
Font::BOLD,
theme::FG,
theme::BG,
);
display::dotted_line(self.area.bottom_left(), self.area.width(), theme::FG);
self.content.paint();
}
}
#[cfg(feature = "ui_debug")]
impl<T, U> crate::trace::Trace for Frame<T, U>
where
T: crate::trace::Trace,
U: crate::trace::Trace + AsRef<str>,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Frame");
t.field("title", &self.title);
t.field("content", &self.content);
t.close();
}
}

View File

@ -1,11 +0,0 @@
mod button;
mod dialog;
mod frame;
mod page;
use super::theme;
pub use button::{Button, ButtonContent, ButtonMsg, ButtonPos, ButtonStyle, ButtonStyleSheet};
pub use dialog::{Dialog, DialogMsg};
pub use frame::Frame;
pub use page::ButtonPage;

View File

@ -1,227 +0,0 @@
use crate::ui::{
component::{Component, ComponentExt, Event, EventCtx, Never, Pad, PageMsg, Paginate},
display::{self, Color, Font},
geometry::{Insets, Offset, Point, Rect},
};
use super::{theme, Button, ButtonMsg, ButtonPos};
pub struct ButtonPage<T> {
content: T,
scrollbar: ScrollBar,
pad: Pad,
prev: Button<&'static str>,
next: Button<&'static str>,
cancel: Button<&'static str>,
confirm: Button<&'static str>,
}
impl<T> ButtonPage<T>
where
T: Paginate,
T: Component,
{
pub fn new(content: T, background: Color) -> Self {
Self {
content,
scrollbar: ScrollBar::vertical(),
pad: Pad::with_background(background),
prev: Button::with_text(ButtonPos::Left, "BACK", theme::button_cancel()),
next: Button::with_text(ButtonPos::Right, "NEXT", theme::button_default()),
cancel: Button::with_text(ButtonPos::Left, "CANCEL", theme::button_cancel()),
confirm: Button::with_text(ButtonPos::Right, "CONFIRM", theme::button_default()),
}
}
fn change_page(&mut self, ctx: &mut EventCtx, page: usize) {
// Change the page in the content, clear the background under it and make sure
// it gets completely repainted.
self.content.change_page(page);
self.content.request_complete_repaint(ctx);
self.pad.clear();
}
}
impl<T> Component for ButtonPage<T>
where
T: Component,
T: Paginate,
{
type Msg = PageMsg<T::Msg, bool>;
fn place(&mut self, bounds: Rect) -> Rect {
let button_height = Font::BOLD.line_height() + 2;
let (content_area, button_area) = bounds.split_bottom(button_height);
let (content_area, scrollbar_area) = content_area.split_right(ScrollBar::WIDTH);
let content_area = content_area.inset(Insets::top(1));
self.pad.place(bounds);
self.content.place(content_area);
let page_count = self.content.page_count();
self.scrollbar.set_count_and_active_page(page_count, 0);
self.scrollbar.place(scrollbar_area);
self.prev.place(button_area);
self.next.place(button_area);
self.cancel.place(button_area);
self.confirm.place(button_area);
bounds
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
ctx.set_page_count(self.scrollbar.page_count);
if self.scrollbar.has_previous_page() {
if let Some(ButtonMsg::Clicked) = self.prev.event(ctx, event) {
// Scroll up.
self.scrollbar.go_to_previous_page();
self.change_page(ctx, self.scrollbar.active_page);
return None;
}
} else if let Some(ButtonMsg::Clicked) = self.cancel.event(ctx, event) {
return Some(PageMsg::Controls(false));
}
if self.scrollbar.has_next_page() {
if let Some(ButtonMsg::Clicked) = self.next.event(ctx, event) {
// Scroll down.
self.scrollbar.go_to_next_page();
self.change_page(ctx, self.scrollbar.active_page);
return None;
}
} else if let Some(ButtonMsg::Clicked) = self.confirm.event(ctx, event) {
return Some(PageMsg::Controls(true));
}
if let Some(msg) = self.content.event(ctx, event) {
return Some(PageMsg::Content(msg));
}
None
}
fn paint(&mut self) {
self.pad.paint();
self.content.paint();
self.scrollbar.paint();
if self.scrollbar.has_previous_page() {
self.prev.paint();
} else {
self.cancel.paint();
}
if self.scrollbar.has_next_page() {
self.next.paint();
} else {
self.confirm.paint();
}
}
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for ButtonPage<T>
where
T: crate::trace::Trace,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("ButtonPage");
t.field("active_page", &self.scrollbar.active_page);
t.field("page_count", &self.scrollbar.page_count);
t.field("content", &self.content);
t.close();
}
}
pub struct ScrollBar {
area: Rect,
page_count: usize,
active_page: usize,
}
impl ScrollBar {
pub const WIDTH: i16 = 8;
pub const DOT_SIZE: Offset = Offset::new(4, 4);
pub const DOT_INTERVAL: i16 = 6;
pub fn vertical() -> Self {
Self {
area: Rect::zero(),
page_count: 0,
active_page: 0,
}
}
pub fn set_count_and_active_page(&mut self, page_count: usize, active_page: usize) {
self.page_count = page_count;
self.active_page = active_page;
}
pub fn has_next_page(&self) -> bool {
self.active_page < self.page_count - 1
}
pub fn has_previous_page(&self) -> bool {
self.active_page > 0
}
pub fn go_to_next_page(&mut self) {
self.active_page = self.active_page.saturating_add(1).min(self.page_count - 1);
}
pub fn go_to_previous_page(&mut self) {
self.active_page = self.active_page.saturating_sub(1);
}
fn paint_dot(&self, active: bool, top_left: Point) {
let sides = [
Rect::from_top_left_and_size(top_left + Offset::x(1), Offset::new(2, 1)),
Rect::from_top_left_and_size(top_left + Offset::y(1), Offset::new(1, 2)),
Rect::from_top_left_and_size(
top_left + Offset::new(1, Self::DOT_SIZE.y - 1),
Offset::new(2, 1),
),
Rect::from_top_left_and_size(
top_left + Offset::new(Self::DOT_SIZE.x - 1, 1),
Offset::new(1, 2),
),
];
for side in sides {
display::rect_fill(side, theme::FG)
}
if active {
display::rect_fill(
Rect::from_top_left_and_size(top_left, Self::DOT_SIZE).inset(Insets::uniform(1)),
theme::FG,
)
}
}
}
impl Component for ScrollBar {
type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect {
self.area = bounds;
self.area
}
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
None
}
fn paint(&mut self) {
let count = self.page_count as i16;
let interval = {
let available_height = self.area.height();
let naive_height = count * Self::DOT_INTERVAL;
if naive_height > available_height {
available_height / count
} else {
Self::DOT_INTERVAL
}
};
let mut dot = Point::new(
self.area.center().x - Self::DOT_SIZE.x / 2,
self.area.center().y - (count / 2) * interval,
);
for i in 0..self.page_count {
self.paint_dot(i == self.active_page, dot);
dot.y += interval
}
}
}

View File

@ -1,14 +0,0 @@
use crate::ui::geometry::{Offset, Point, Rect};
pub const WIDTH: i16 = 128;
pub const HEIGHT: i16 = 64;
pub const LINE_SPACE: i16 = 1;
pub const FONT_BPP: i16 = 1;
pub const fn size() -> Offset {
Offset::new(WIDTH, HEIGHT)
}
pub const fn screen() -> Rect {
Rect::from_top_left_and_size(Point::zero(), size())
}

View File

@ -1,244 +0,0 @@
use core::convert::TryInto;
use crate::{
error::Error,
micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr, util},
ui::{
component::{
base::Component,
paginated::{PageMsg, Paginate},
text::paragraphs::{Paragraph, Paragraphs},
FormattedText,
},
layout::{
obj::{ComponentMsgObj, LayoutObj},
result::{CANCELLED, CONFIRMED},
util::upy_disable_animation,
},
},
};
use super::{
component::{Button, ButtonPage, ButtonPos, Frame},
theme,
};
impl<T> ComponentMsgObj for ButtonPage<T>
where
T: Component + Paginate,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
PageMsg::Content(_) => Err(Error::TypeError),
PageMsg::Controls(true) => Ok(CONFIRMED.as_obj()),
PageMsg::Controls(false) => Ok(CANCELLED.as_obj()),
PageMsg::GoBack => unreachable!(),
}
}
}
impl<T, U> ComponentMsgObj for Frame<T, U>
where
T: ComponentMsgObj,
U: AsRef<str>,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
self.inner().msg_try_into_obj(msg)
}
}
extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let action: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
let description: Option<StrBuffer> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let verb: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_verb)?.try_into_option()?;
let verb_cancel: Option<StrBuffer> =
kwargs.get(Qstr::MP_QSTR_verb_cancel)?.try_into_option()?;
let reverse: bool = kwargs.get(Qstr::MP_QSTR_reverse)?.try_into()?;
let format = match (&action, &description, reverse) {
(Some(_), Some(_), false) => "{bold}{action}\n\r{normal}{description}",
(Some(_), Some(_), true) => "{normal}{description}\n\r{bold}{action}",
(Some(_), None, _) => "{bold}{action}",
(None, Some(_), _) => "{normal}{description}",
_ => "",
};
let _left = verb_cancel
.map(|label| Button::with_text(ButtonPos::Left, label, theme::button_cancel()));
let _right =
verb.map(|label| Button::with_text(ButtonPos::Right, label, theme::button_default()));
let obj = LayoutObj::new(Frame::new(
title,
ButtonPage::new(
FormattedText::new(theme::TEXT_NORMAL, theme::FORMATTED, format)
.with("action", action.unwrap_or_default())
.with("description", description.unwrap_or_default()),
theme::BG,
),
))?;
Ok(obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_text(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: StrBuffer = kwargs.get(Qstr::MP_QSTR_data)?.try_into()?;
let description: Option<StrBuffer> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let obj = LayoutObj::new(Frame::new(
title,
ButtonPage::new(
Paragraphs::new([
Paragraph::new(&theme::TEXT_NORMAL, description.unwrap_or_default()),
Paragraph::new(&theme::TEXT_BOLD, data),
]),
theme::BG,
),
))?;
Ok(obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
#[no_mangle]
pub static mp_module_trezorui2: Module = obj_module! {
Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(),
/// CONFIRMED: object
Qstr::MP_QSTR_CONFIRMED => CONFIRMED.as_obj(),
/// CANCELLED: object
Qstr::MP_QSTR_CANCELLED => CANCELLED.as_obj(),
/// def disable_animation(disable: bool) -> None:
/// """Disable animations, debug builds only."""
Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(),
/// def confirm_action(
/// *,
/// title: str,
/// action: str | None = None,
/// description: str | None = None,
/// verb: str | None = None,
/// verb_cancel: str | None = None,
/// hold: bool | None = None,
/// reverse: bool = False,
/// ) -> object:
/// """Confirm action."""
Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(),
/// def confirm_text(
/// *,
/// title: str,
/// data: str,
/// description: str | None,
/// ) -> object:
/// """Confirm text."""
Qstr::MP_QSTR_confirm_text => obj_fn_kw!(0, new_confirm_text).as_obj(),
};
#[cfg(test)]
mod tests {
use crate::{
trace::Trace,
ui::{
component::Component,
model_t1::{
component::{Dialog, DialogMsg},
constant,
},
},
};
use super::*;
fn trace(val: &impl Trace) -> String {
let mut t = Vec::new();
val.trace(&mut t);
String::from_utf8(t).unwrap()
}
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 > > >"#
)
}
}

View File

@ -1,6 +0,0 @@
pub mod component;
pub mod constant;
pub mod theme;
#[cfg(feature = "micropython")]
pub mod layout;

View File

@ -1,55 +0,0 @@
use crate::ui::{
component::text::{formatted::FormattedFonts, TextStyle},
display::{Color, Font},
};
use super::component::{ButtonStyle, ButtonStyleSheet};
// Color palette.
pub const WHITE: Color = Color::rgb(255, 255, 255);
pub const BLACK: Color = Color::rgb(0, 0, 0);
pub const GREY_LIGHT: Color = WHITE; // Word/page break characters.
pub const FG: Color = WHITE; // Default foreground (text & icon) color.
pub const BG: Color = BLACK; // Default background color.
pub fn button_default() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
font: Font::BOLD,
text_color: BG,
border_horiz: true,
},
active: &ButtonStyle {
font: Font::BOLD,
text_color: FG,
border_horiz: true,
},
}
}
pub fn button_cancel() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
font: Font::BOLD,
text_color: FG,
border_horiz: false,
},
active: &ButtonStyle {
font: Font::BOLD,
text_color: BG,
border_horiz: false,
},
}
}
pub const TEXT_NORMAL: TextStyle = TextStyle::new(Font::NORMAL, FG, BG, FG, FG);
pub const TEXT_DEMIBOLD: TextStyle = TextStyle::new(Font::DEMIBOLD, FG, BG, FG, FG);
pub const TEXT_BOLD: TextStyle = TextStyle::new(Font::BOLD, FG, BG, FG, FG);
pub const TEXT_MONO: TextStyle = TextStyle::new(Font::MONO, FG, BG, FG, FG);
pub const FORMATTED: FormattedFonts = FormattedFonts {
normal: Font::NORMAL,
demibold: Font::DEMIBOLD,
bold: Font::BOLD,
mono: Font::MONO,
};

View File

@ -3,37 +3,6 @@ CONFIRMED: object
CANCELLED: object CANCELLED: object
# rust/src/ui/model_t1/layout.rs
def disable_animation(disable: bool) -> None:
"""Disable animations, debug builds only."""
# rust/src/ui/model_t1/layout.rs
def confirm_action(
*,
title: str,
action: str | None = None,
description: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
hold: bool | None = None,
reverse: bool = False,
) -> object:
"""Confirm action."""
# rust/src/ui/model_t1/layout.rs
def confirm_text(
*,
title: str,
data: str,
description: str | None,
) -> object:
"""Confirm text."""
CONFIRMED: object
CANCELLED: object
# rust/src/ui/model_tr/layout.rs # rust/src/ui/model_tr/layout.rs
def disable_animation(disable: bool) -> None: def disable_animation(disable: bool) -> None:
"""Disable animations, debug builds only.""" """Disable animations, debug builds only."""

View File

@ -54,7 +54,7 @@ or contain `[no changelog]` in the commit message.
## BUILD stage - [build.yml](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml) ## BUILD stage - [build.yml](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml)
All builds are published as artifacts so they can be downloaded and used. All builds are published as artifacts so they can be downloaded and used.
Consists of **27 jobs** below: Consists of **25 jobs** below:
### [core fw regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L20) ### [core fw regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L20)
Build of Core into firmware. Regular version. Build of Core into firmware. Regular version.
@ -74,72 +74,68 @@ Build of Core into firmware. Bitcoin-only version.
### [core fw btconly production build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L117) ### [core fw btconly production build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L117)
### [core fw btconly t1 build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L136) ### [core unix regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L138)
### [core unix regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L154)
Non-frozen emulator build. This means you still need Python files Non-frozen emulator build. This means you still need Python files
present which get interpreted. present which get interpreted.
### [core unix regular asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L166) ### [core unix regular asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L150)
### [core unix frozen regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L185) ### [core unix frozen regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L169)
Build of Core into UNIX emulator. Something you can run on your laptop. Build of Core into UNIX emulator. Something you can run on your laptop.
Frozen version. That means you do not need any other files to run it, Frozen version. That means you do not need any other files to run it,
it is just a single binary file that you can execute directly. it is just a single binary file that you can execute directly.
### [core unix frozen btconly debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L202) ### [core unix frozen btconly debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L186)
Build of Core into UNIX emulator. Something you can run on your laptop. Build of Core into UNIX emulator. Something you can run on your laptop.
Frozen version. That means you do not need any other files to run it, Frozen version. That means you do not need any other files to run it,
it is just a single binary file that you can execute directly. it is just a single binary file that you can execute directly.
See [Emulator](../core/emulator/index.md) for more info. See [Emulator](../core/emulator/index.md) for more info.
Debug mode enabled, Bitcoin-only version. Debug mode enabled, Bitcoin-only version.
### [core unix frozen btconly debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L218) ### [core unix frozen btconly debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L202)
### [core unix frozen debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L241) ### [core unix frozen debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L225)
Build of Core into UNIX emulator. Something you can run on your laptop. Build of Core into UNIX emulator. Something you can run on your laptop.
Frozen version. That means you do not need any other files to run it, Frozen version. That means you do not need any other files to run it,
it is just a single binary file that you can execute directly. it is just a single binary file that you can execute directly.
**Are you looking for a Trezor T emulator? This is most likely it.** **Are you looking for a Trezor T emulator? This is most likely it.**
### [core unix frozen debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L254) ### [core unix frozen debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L238)
### [core unix frozen debug build arm](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L270) ### [core unix frozen debug build arm](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L254)
### [core unix frozen btconly debug t1 build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L292) ### [core macos frozen regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L276)
### [core macos frozen regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L308) ### [crypto build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L301)
### [crypto build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L333)
Build of our cryptographic library, which is then incorporated into the other builds. Build of our cryptographic library, which is then incorporated into the other builds.
### [legacy fw regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L362) ### [legacy fw regular build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L330)
### [legacy fw regular debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L378) ### [legacy fw regular debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L346)
### [legacy fw btconly build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L395) ### [legacy fw btconly build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L363)
### [legacy fw btconly debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L414) ### [legacy fw btconly debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L382)
### [legacy emu regular debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L435) ### [legacy emu regular debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L403)
Regular version (not only Bitcoin) of above. Regular version (not only Bitcoin) of above.
**Are you looking for a Trezor One emulator? This is most likely it.** **Are you looking for a Trezor One emulator? This is most likely it.**
### [legacy emu regular debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L450) ### [legacy emu regular debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L418)
### [legacy emu regular debug build arm](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L468) ### [legacy emu regular debug build arm](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L436)
### [legacy emu btconly debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L494) ### [legacy emu btconly debug build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L462)
Build of Legacy into UNIX emulator. Use keyboard arrows to emulate button presses. Build of Legacy into UNIX emulator. Use keyboard arrows to emulate button presses.
Bitcoin-only version. Bitcoin-only version.
### [legacy emu btconly debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L511) ### [legacy emu btconly debug asan build](https://github.com/trezor/trezor-firmware/blob/master/ci/build.yml#L479)
--- ---
## TEST stage - [test.yml](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml) ## TEST stage - [test.yml](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml)
All the tests run test cases on the freshly built emulators from the previous `BUILD` stage. All the tests run test cases on the freshly built emulators from the previous `BUILD` stage.
Consists of **34 jobs** below: Consists of **33 jobs** below:
### [core unit python test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L15) ### [core unit python test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L15)
Python unit tests, checking core functionality. Python unit tests, checking core functionality.
@ -149,80 +145,78 @@ Rust unit tests.
### [core unit asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L33) ### [core unit asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L33)
### [core unit t1 test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L50) ### [core device test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L54)
### [core device test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L65)
Device tests for Core. Running device tests and also comparing screens Device tests for Core. Running device tests and also comparing screens
with the expected UI result. with the expected UI result.
See artifacts for a comprehensive report of UI. See artifacts for a comprehensive report of UI.
See [docs/tests/ui-tests](../tests/ui-tests.md) for more info. See [docs/tests/ui-tests](../tests/ui-tests.md) for more info.
### [core device asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L94) ### [core device asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L83)
### [core btconly device test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L113) ### [core btconly device test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L102)
Device tests excluding altcoins, only for BTC. Device tests excluding altcoins, only for BTC.
### [core btconly device asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L133) ### [core btconly device asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L122)
### [core monero test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L154) ### [core monero test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L143)
Monero tests. Monero tests.
### [core monero asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L173) ### [core monero asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L162)
### [core u2f test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L195) ### [core u2f test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L184)
Tests for U2F and HID. Tests for U2F and HID.
### [core u2f asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L214) ### [core u2f asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L203)
### [core fido2 test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L232) ### [core fido2 test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L221)
FIDO2 device tests. FIDO2 device tests.
### [core fido2 asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L255) ### [core fido2 asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L244)
### [core click test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L275) ### [core click test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L264)
Click tests. Click tests.
See [docs/tests/click-tests](../tests/click-tests.md) for more info. See [docs/tests/click-tests](../tests/click-tests.md) for more info.
### [core click asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L292) ### [core click asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L281)
### [core upgrade test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L313) ### [core upgrade test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L302)
Upgrade tests. Upgrade tests.
See [docs/tests/upgrade-tests](../tests/upgrade-tests.md) for more info. See [docs/tests/upgrade-tests](../tests/upgrade-tests.md) for more info.
### [core upgrade asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L332) ### [core upgrade asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L321)
### [core persistence test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L354) ### [core persistence test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L343)
Persistence tests. Persistence tests.
### [core persistence asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L370) ### [core persistence asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L359)
### [core hwi test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L388) ### [core hwi test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L377)
### [crypto test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L406) ### [crypto test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L395)
### [legacy device test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L437) ### [legacy device test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L426)
### [legacy asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L464) ### [legacy asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L453)
### [legacy btconly test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L476) ### [legacy btconly test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L465)
### [legacy btconly asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L496) ### [legacy btconly asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L485)
### [legacy upgrade test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L511) ### [legacy upgrade test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L500)
### [legacy upgrade asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L530) ### [legacy upgrade asan test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L519)
### [legacy hwi test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L551) ### [legacy hwi test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L540)
### [python test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L570) ### [python test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L559)
### [python support test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L589) ### [python support test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L578)
### [storage test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L599) ### [storage test](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L588)
### [core unix memory profiler](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L623) ### [core unix memory profiler](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L612)
### [connect test core](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L647) ### [connect test core](https://github.com/trezor/trezor-firmware/blob/master/ci/test.yml#L636)
--- ---
## TEST-HW stage - [test-hw.yml](https://github.com/trezor/trezor-firmware/blob/master/ci/test-hw.yml) ## TEST-HW stage - [test-hw.yml](https://github.com/trezor/trezor-firmware/blob/master/ci/test-hw.yml)