1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +00:00

feat(core): introduce trezorui_api

The new module is the place for type definitions of the interface
between rust and micropython world.

The goal is to replace `trezorui2` with `trezorui_api` without
duplicated definitions.
This commit is contained in:
obrusvit 2024-10-18 15:11:58 +02:00
parent af554458b5
commit c51f51d233
30 changed files with 316 additions and 402 deletions

View File

@ -165,6 +165,7 @@
#define MICROPY_PY_TREZORPROTO (1) #define MICROPY_PY_TREZORPROTO (1)
#define MICROPY_PY_TREZORTRANSLATE (1) #define MICROPY_PY_TREZORTRANSLATE (1)
#define MICROPY_PY_TREZORUI2 (1) #define MICROPY_PY_TREZORUI2 (1)
#define MICROPY_PY_TREZORUI_API (1)
#ifdef SYSTEM_VIEW #ifdef SYSTEM_VIEW
#define MP_PLAT_PRINT_STRN(str, len) segger_print(str, len) #define MP_PLAT_PRINT_STRN(str, len) segger_print(str, len)

View File

@ -214,6 +214,7 @@ extern const struct _mp_print_t mp_stderr_print;
#define MICROPY_PY_TREZORPROTO (1) #define MICROPY_PY_TREZORPROTO (1)
#define MICROPY_PY_TREZORTRANSLATE (1) #define MICROPY_PY_TREZORTRANSLATE (1)
#define MICROPY_PY_TREZORUI2 (1) #define MICROPY_PY_TREZORUI2 (1)
#define MICROPY_PY_TREZORUI_API (1)
#define MP_STATE_PORT MP_STATE_VM #define MP_STATE_PORT MP_STATE_VM

View File

@ -9,6 +9,7 @@ mp_obj_t protobuf_debug_msg_def_type();
extern mp_obj_module_t mp_module_trezorproto; extern mp_obj_module_t mp_module_trezorproto;
extern mp_obj_module_t mp_module_trezorui2; extern mp_obj_module_t mp_module_trezorui2;
extern mp_obj_module_t mp_module_trezorui_api;
extern mp_obj_module_t mp_module_trezortranslate; extern mp_obj_module_t mp_module_trezortranslate;
#ifdef TREZOR_EMULATOR #ifdef TREZOR_EMULATOR

View File

@ -701,6 +701,7 @@ static void _librust_qstrs(void) {
MP_QSTR_trace; MP_QSTR_trace;
MP_QSTR_trezorproto; MP_QSTR_trezorproto;
MP_QSTR_trezorui2; MP_QSTR_trezorui2;
MP_QSTR_trezorui_api;
MP_QSTR_tutorial; MP_QSTR_tutorial;
MP_QSTR_tutorial__continue; MP_QSTR_tutorial__continue;
MP_QSTR_tutorial__did_you_know; MP_QSTR_tutorial__did_you_know;

View File

@ -0,0 +1,133 @@
use crate::micropython::map::Map;
use crate::ui::layout::obj::ATTACH_TYPE_OBJ;
use crate::ui::layout::base::LAYOUT_STATE;
use crate::ui::backlight::BACKLIGHT_LEVELS_OBJ;
use crate::{
micropython::{macros::obj_module, module::Module, qstr::Qstr},
ui::layout::result::{CANCELLED, CONFIRMED, INFO},
};
#[no_mangle]
pub static mp_module_trezorui_api: Module = obj_module! {
/// from trezor import utils
///
/// T = TypeVar("T")
///
/// class LayoutObj(Generic[T]):
/// """Representation of a Rust-based layout object.
/// see `trezor::ui::layout::obj::LayoutObj`.
/// """
///
/// def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> LayoutState | None:
/// """Attach a timer setter function.
///
/// The layout object can call the timer setter with two arguments,
/// `token` and `duration_ms`. When `duration_ms` elapses, the layout object
/// expects a callback to `self.timer(token)`.
/// """
///
/// if utils.USE_TOUCH:
/// def touch_event(self, event: int, x: int, y: int) -> LayoutState | None:
/// """Receive a touch event `event` at coordinates `x`, `y`."""
///
/// if utils.USE_BUTTON:
/// def button_event(self, event: int, button: int) -> LayoutState | None:
/// """Receive a button event `event` for button `button`."""
///
/// def progress_event(self, value: int, description: str) -> LayoutState | None:
/// """Receive a progress event."""
///
/// def usb_event(self, connected: bool) -> LayoutState | None:
/// """Receive a USB connect/disconnect event."""
///
/// def timer(self, token: int) -> LayoutState | None:
/// """Callback for the timer set by `attach_timer_fn`.
///
/// This function should be called by the executor after the corresponding
/// duration elapses.
/// """
///
/// def paint(self) -> bool:
/// """Paint the layout object on screen.
///
/// Will only paint updated parts of the layout as required.
/// Returns True if any painting actually happened.
/// """
///
/// def request_complete_repaint(self) -> None:
/// """Request a complete repaint of the screen.
///
/// Does not repaint the screen, a subsequent call to `paint()` is required.
/// """
///
/// if __debug__:
/// def trace(self, tracer: Callable[[str], None]) -> None:
/// """Generate a JSON trace of the layout object.
///
/// The JSON can be emitted as a sequence of calls to `tracer`, each of
/// which is not necessarily a valid JSON chunk. The caller must
/// reassemble the chunks to get a sensible result.
/// """
///
/// def bounds(self) -> None:
/// """Paint bounds of individual components on screen."""
///
/// def page_count(self) -> int:
/// """Return the number of pages in the layout object."""
///
/// def button_request(self) -> tuple[int, str] | None:
/// """Return (code, type) of button request made during the last event or timer pass."""
///
/// def get_transition_out(self) -> AttachType:
/// """Return the transition type."""
///
/// def return_value(self) -> T:
/// """Retrieve the return value of the layout object."""
///
/// def __del__(self) -> None:
/// """Calls drop on contents of the root component."""
///
/// class UiResult:
/// """Result of a UI operation."""
/// pass
///
/// mock:global
Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui_api.to_obj(),
/// CONFIRMED: UiResult
Qstr::MP_QSTR_CONFIRMED => CONFIRMED.as_obj(),
/// CANCELLED: UiResult
Qstr::MP_QSTR_CANCELLED => CANCELLED.as_obj(),
/// INFO: UiResult
Qstr::MP_QSTR_INFO => INFO.as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
/// class AttachType:
/// INITIAL: ClassVar[int]
/// RESUME: ClassVar[int]
/// SWIPE_UP: ClassVar[int]
/// SWIPE_DOWN: ClassVar[int]
/// SWIPE_LEFT: ClassVar[int]
/// SWIPE_RIGHT: ClassVar[int]
Qstr::MP_QSTR_AttachType => ATTACH_TYPE_OBJ.as_obj(),
/// class LayoutState:
/// """Layout state."""
/// INITIAL: "ClassVar[LayoutState]"
/// ATTACHED: "ClassVar[LayoutState]"
/// TRANSITIONING: "ClassVar[LayoutState]"
/// DONE: "ClassVar[LayoutState]"
Qstr::MP_QSTR_LayoutState => LAYOUT_STATE.as_obj(),
};

View File

@ -2,3 +2,6 @@ pub mod common_c;
#[cfg(feature = "bootloader")] #[cfg(feature = "bootloader")]
pub mod bootloader_c; pub mod bootloader_c;
#[cfg(feature = "micropython")]
pub mod firmware_upy;

View File

@ -24,5 +24,7 @@ pub mod model_tr;
#[cfg(feature = "model_tt")] #[cfg(feature = "model_tt")]
pub mod model_tt; pub mod model_tt;
pub mod ui_features; pub mod ui_features;
#[cfg(feature = "micropython")]
pub mod ui_features_fw;
pub use ui_features::UIFeaturesCommon; pub use ui_features::UIFeaturesCommon;

View File

@ -1508,16 +1508,10 @@ extern "C" fn new_warning_hi_prio(n_args: usize, args: *const Obj, kwargs: *mut
#[no_mangle] #[no_mangle]
pub static mp_module_trezorui2: Module = obj_module! { pub static mp_module_trezorui2: Module = obj_module! {
/// from trezor import utils /// from trezor import utils
/// from trezorui_api import *
///
Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(), Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(),
/// CONFIRMED: UiResult
Qstr::MP_QSTR_CONFIRMED => CONFIRMED.as_obj(),
/// CANCELLED: UiResult
Qstr::MP_QSTR_CANCELLED => CANCELLED.as_obj(),
/// INFO: UiResult
Qstr::MP_QSTR_INFO => INFO.as_obj(),
/// def disable_animation(disable: bool) -> None: /// def disable_animation(disable: bool) -> None:
/// """Disable animations, debug builds only.""" /// """Disable animations, debug builds only."""
@ -2021,33 +2015,5 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// cancel_text: str | None = None, /// cancel_text: str | None = None,
/// ) -> LayoutObj[UiResult]: /// ) -> LayoutObj[UiResult]:
/// """Total summary and hold to confirm.""" /// """Total summary and hold to confirm."""
Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, new_confirm_summary).as_obj(), Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, flow::new_confirm_summary).as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
/// class AttachType:
/// INITIAL: ClassVar[int]
/// RESUME: ClassVar[int]
/// SWIPE_UP: ClassVar[int]
/// SWIPE_DOWN: ClassVar[int]
/// SWIPE_LEFT: ClassVar[int]
/// SWIPE_RIGHT: ClassVar[int]
Qstr::MP_QSTR_AttachType => ATTACH_TYPE_OBJ.as_obj(),
/// class LayoutState:
/// """Layout state."""
/// INITIAL: "ClassVar[LayoutState]"
/// ATTACHED: "ClassVar[LayoutState]"
/// TRANSITIONING: "ClassVar[LayoutState]"
/// DONE: "ClassVar[LayoutState]"
Qstr::MP_QSTR_LayoutState => LAYOUT_STATE.as_obj(),
}; };

View File

@ -13,6 +13,8 @@ pub mod flow;
#[cfg(feature = "micropython")] #[cfg(feature = "micropython")]
pub mod layout; pub mod layout;
pub mod screens; pub mod screens;
#[cfg(feature = "micropython")]
pub mod ui_features_fw;
pub struct ModelMercuryFeatures; pub struct ModelMercuryFeatures;

View File

@ -30,7 +30,6 @@ use crate::{
translations::TR, translations::TR,
trezorhal::model, trezorhal::model,
ui::{ ui::{
backlight::BACKLIGHT_LEVELS_OBJ,
component::{ component::{
base::Component, base::Component,
connect::Connect, connect::Connect,
@ -47,8 +46,7 @@ use crate::{
}, },
geometry, geometry,
layout::{ layout::{
base::LAYOUT_STATE, obj::{ComponentMsgObj, LayoutObj},
obj::{ComponentMsgObj, LayoutObj, ATTACH_TYPE_OBJ},
result::{CANCELLED, CONFIRMED, INFO}, result::{CANCELLED, CONFIRMED, INFO},
util::{upy_disable_animation, ConfirmBlob, RecoveryType}, util::{upy_disable_animation, ConfirmBlob, RecoveryType},
}, },
@ -1651,17 +1649,11 @@ extern "C" fn new_show_wait_text(message: Obj) -> Obj {
#[no_mangle] #[no_mangle]
pub static mp_module_trezorui2: Module = obj_module! { pub static mp_module_trezorui2: Module = obj_module! {
/// from trezor import utils
/// from trezorui_api import *
///
Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(), Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(),
/// CONFIRMED: UiResult
Qstr::MP_QSTR_CONFIRMED => CONFIRMED.as_obj(),
/// CANCELLED: UiResult
Qstr::MP_QSTR_CANCELLED => CANCELLED.as_obj(),
/// INFO: UiResult
Qstr::MP_QSTR_INFO => INFO.as_obj(),
/// def disable_animation(disable: bool) -> None: /// def disable_animation(disable: bool) -> None:
/// """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(),
@ -2082,32 +2074,4 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def show_wait_text(message: str, /) -> None: /// def show_wait_text(message: str, /) -> None:
/// """Show single-line text in the middle of the screen.""" /// """Show single-line text in the middle of the screen."""
Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(), Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
/// class AttachType:
/// INITIAL: ClassVar[int]
/// RESUME: ClassVar[int]
/// SWIPE_UP: ClassVar[int]
/// SWIPE_DOWN: ClassVar[int]
/// SWIPE_LEFT: ClassVar[int]
/// SWIPE_RIGHT: ClassVar[int]
Qstr::MP_QSTR_AttachType => ATTACH_TYPE_OBJ.as_obj(),
/// class LayoutState:
/// """Layout state."""
/// INITIAL: "ClassVar[LayoutState]"
/// ATTACHED: "ClassVar[LayoutState]"
/// TRANSITIONING: "ClassVar[LayoutState]"
/// DONE: "ClassVar[LayoutState]"
Qstr::MP_QSTR_LayoutState => LAYOUT_STATE.as_obj(),
}; };

View File

@ -30,7 +30,6 @@ use crate::{
translations::TR, translations::TR,
trezorhal::model, trezorhal::model,
ui::{ ui::{
backlight::BACKLIGHT_LEVELS_OBJ,
component::{ component::{
base::ComponentExt, base::ComponentExt,
connect::Connect, connect::Connect,
@ -50,8 +49,7 @@ use crate::{
}, },
geometry, geometry,
layout::{ layout::{
base::LAYOUT_STATE, obj::{ComponentMsgObj, LayoutObj},
obj::{ComponentMsgObj, LayoutObj, ATTACH_TYPE_OBJ},
result::{CANCELLED, CONFIRMED, INFO}, result::{CANCELLED, CONFIRMED, INFO},
util::{upy_disable_animation, ConfirmBlob, PropsList, RecoveryType}, util::{upy_disable_animation, ConfirmBlob, PropsList, RecoveryType},
}, },
@ -1653,98 +1651,8 @@ extern "C" fn new_show_wait_text(message: Obj) -> Obj {
#[no_mangle] #[no_mangle]
pub static mp_module_trezorui2: Module = obj_module! { pub static mp_module_trezorui2: Module = obj_module! {
/// from trezor import utils /// from trezor import utils
/// from trezorui_api import *
/// ///
/// T = TypeVar("T")
///
/// class LayoutObj(Generic[T]):
/// """Representation of a Rust-based layout object.
/// see `trezor::ui::layout::obj::LayoutObj`.
/// """
///
/// def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> LayoutState | None:
/// """Attach a timer setter function.
///
/// The layout object can call the timer setter with two arguments,
/// `token` and `duration_ms`. When `duration_ms` elapses, the layout object
/// expects a callback to `self.timer(token)`.
/// """
///
/// if utils.USE_TOUCH:
/// def touch_event(self, event: int, x: int, y: int) -> LayoutState | None:
/// """Receive a touch event `event` at coordinates `x`, `y`."""
///
/// if utils.USE_BUTTON:
/// def button_event(self, event: int, button: int) -> LayoutState | None:
/// """Receive a button event `event` for button `button`."""
///
/// def progress_event(self, value: int, description: str) -> LayoutState | None:
/// """Receive a progress event."""
///
/// def usb_event(self, connected: bool) -> LayoutState | None:
/// """Receive a USB connect/disconnect event."""
///
/// def timer(self, token: int) -> LayoutState | None:
/// """Callback for the timer set by `attach_timer_fn`.
///
/// This function should be called by the executor after the corresponding
/// duration elapses.
/// """
///
/// def paint(self) -> bool:
/// """Paint the layout object on screen.
///
/// Will only paint updated parts of the layout as required.
/// Returns True if any painting actually happened.
/// """
///
/// def request_complete_repaint(self) -> None:
/// """Request a complete repaint of the screen.
///
/// Does not repaint the screen, a subsequent call to `paint()` is required.
/// """
///
/// if __debug__:
/// def trace(self, tracer: Callable[[str], None]) -> None:
/// """Generate a JSON trace of the layout object.
///
/// The JSON can be emitted as a sequence of calls to `tracer`, each of
/// which is not necessarily a valid JSON chunk. The caller must
/// reassemble the chunks to get a sensible result.
/// """
///
/// def bounds(self) -> None:
/// """Paint bounds of individual components on screen."""
///
/// def page_count(self) -> int:
/// """Return the number of pages in the layout object."""
///
/// def button_request(self) -> tuple[int, str] | None:
/// """Return (code, type) of button request made during the last event or timer pass."""
///
/// def get_transition_out(self) -> AttachType:
/// """Return the transition type."""
///
/// def return_value(self) -> T:
/// """Retrieve the return value of the layout object."""
///
/// def __del__(self) -> None:
/// """Calls drop on contents of the root component."""
///
/// class UiResult:
/// """Result of an UI operation."""
/// pass
///
/// mock:global
Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(),
/// CONFIRMED: UiResult
Qstr::MP_QSTR_CONFIRMED => CONFIRMED.as_obj(),
/// CANCELLED: UiResult
Qstr::MP_QSTR_CANCELLED => CANCELLED.as_obj(),
/// INFO: UiResult
Qstr::MP_QSTR_INFO => INFO.as_obj(),
/// def disable_animation(disable: bool) -> None: /// def disable_animation(disable: bool) -> None:
/// """Disable animations, debug builds only.""" /// """Disable animations, debug builds only."""
@ -2182,34 +2090,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def show_wait_text(message: str, /) -> LayoutObj[None]: /// def show_wait_text(message: str, /) -> LayoutObj[None]:
/// """Show single-line text in the middle of the screen.""" /// """Show single-line text in the middle of the screen."""
Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(), Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(),
/// class BacklightLevels:
/// """Backlight levels. Values dynamically update based on user settings."""
/// MAX: ClassVar[int]
/// NORMAL: ClassVar[int]
/// LOW: ClassVar[int]
/// DIM: ClassVar[int]
/// NONE: ClassVar[int]
///
/// mock:global
Qstr::MP_QSTR_BacklightLevels => BACKLIGHT_LEVELS_OBJ.as_obj(),
/// class AttachType:
/// INITIAL: ClassVar[int]
/// RESUME: ClassVar[int]
/// SWIPE_UP: ClassVar[int]
/// SWIPE_DOWN: ClassVar[int]
/// SWIPE_LEFT: ClassVar[int]
/// SWIPE_RIGHT: ClassVar[int]
Qstr::MP_QSTR_AttachType => ATTACH_TYPE_OBJ.as_obj(),
/// class LayoutState:
/// """Layout state."""
/// INITIAL: "ClassVar[LayoutState]"
/// ATTACHED: "ClassVar[LayoutState]"
/// TRANSITIONING: "ClassVar[LayoutState]"
/// DONE: "ClassVar[LayoutState]"
Qstr::MP_QSTR_LayoutState => LAYOUT_STATE.as_obj(),
}; };
#[cfg(test)] #[cfg(test)]

View File

@ -25,6 +25,10 @@
MP_REGISTER_MODULE(MP_QSTR_trezorui2, mp_module_trezorui2); MP_REGISTER_MODULE(MP_QSTR_trezorui2, mp_module_trezorui2);
#endif #endif
#if MICROPY_PY_TREZORUI_API
MP_REGISTER_MODULE(MP_QSTR_trezorui_api, mp_module_trezorui_api);
#endif
#if MICROPY_PY_TREZORPROTO #if MICROPY_PY_TREZORPROTO
MP_REGISTER_MODULE(MP_QSTR_trezorproto, mp_module_trezorproto); MP_REGISTER_MODULE(MP_QSTR_trezorproto, mp_module_trezorproto);
#endif #endif

View File

@ -1,8 +1,6 @@
from typing import * from typing import *
from trezor import utils from trezor import utils
CONFIRMED: UiResult from trezorui_api import *
CANCELLED: UiResult
INFO: UiResult
# rust/src/ui/model_mercury/layout.rs # rust/src/ui/model_mercury/layout.rs
@ -554,38 +552,8 @@ def flow_confirm_summary(
cancel_text: str | None = None, cancel_text: str | None = None,
) -> LayoutObj[UiResult]: ) -> LayoutObj[UiResult]:
"""Total summary and hold to confirm.""" """Total summary and hold to confirm."""
from trezor import utils
from trezorui_api import *
# rust/src/ui/model_mercury/layout.rs
class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings."""
MAX: ClassVar[int]
NORMAL: ClassVar[int]
LOW: ClassVar[int]
DIM: ClassVar[int]
NONE: ClassVar[int]
# rust/src/ui/model_mercury/layout.rs
class AttachType:
INITIAL: ClassVar[int]
RESUME: ClassVar[int]
SWIPE_UP: ClassVar[int]
SWIPE_DOWN: ClassVar[int]
SWIPE_LEFT: ClassVar[int]
SWIPE_RIGHT: ClassVar[int]
# rust/src/ui/model_mercury/layout.rs
class LayoutState:
"""Layout state."""
INITIAL: "ClassVar[LayoutState]"
ATTACHED: "ClassVar[LayoutState]"
TRANSITIONING: "ClassVar[LayoutState]"
DONE: "ClassVar[LayoutState]"
CONFIRMED: UiResult
CANCELLED: UiResult
INFO: UiResult
# rust/src/ui/model_tr/layout.rs # rust/src/ui/model_tr/layout.rs
@ -1050,102 +1018,8 @@ def confirm_firmware_update(
# rust/src/ui/model_tr/layout.rs # rust/src/ui/model_tr/layout.rs
def show_wait_text(message: str, /) -> None: def show_wait_text(message: str, /) -> None:
"""Show single-line text in the middle of the screen.""" """Show single-line text in the middle of the screen."""
# rust/src/ui/model_tr/layout.rs
class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings."""
MAX: ClassVar[int]
NORMAL: ClassVar[int]
LOW: ClassVar[int]
DIM: ClassVar[int]
NONE: ClassVar[int]
# rust/src/ui/model_tr/layout.rs
class AttachType:
INITIAL: ClassVar[int]
RESUME: ClassVar[int]
SWIPE_UP: ClassVar[int]
SWIPE_DOWN: ClassVar[int]
SWIPE_LEFT: ClassVar[int]
SWIPE_RIGHT: ClassVar[int]
# rust/src/ui/model_tr/layout.rs
class LayoutState:
"""Layout state."""
INITIAL: "ClassVar[LayoutState]"
ATTACHED: "ClassVar[LayoutState]"
TRANSITIONING: "ClassVar[LayoutState]"
DONE: "ClassVar[LayoutState]"
from trezor import utils from trezor import utils
T = TypeVar("T") from trezorui_api import *
# rust/src/ui/model_tt/layout.rs
class LayoutObj(Generic[T]):
"""Representation of a Rust-based layout object.
see `trezor::ui::layout::obj::LayoutObj`.
"""
def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> LayoutState | None:
"""Attach a timer setter function.
The layout object can call the timer setter with two arguments,
`token` and `duration_ms`. When `duration_ms` elapses, the layout object
expects a callback to `self.timer(token)`.
"""
if utils.USE_TOUCH:
def touch_event(self, event: int, x: int, y: int) -> LayoutState | None:
"""Receive a touch event `event` at coordinates `x`, `y`."""
if utils.USE_BUTTON:
def button_event(self, event: int, button: int) -> LayoutState | None:
"""Receive a button event `event` for button `button`."""
def progress_event(self, value: int, description: str) -> LayoutState | None:
"""Receive a progress event."""
def usb_event(self, connected: bool) -> LayoutState | None:
"""Receive a USB connect/disconnect event."""
def timer(self, token: int) -> LayoutState | None:
"""Callback for the timer set by `attach_timer_fn`.
This function should be called by the executor after the corresponding
duration elapses.
"""
def paint(self) -> bool:
"""Paint the layout object on screen.
Will only paint updated parts of the layout as required.
Returns True if any painting actually happened.
"""
def request_complete_repaint(self) -> None:
"""Request a complete repaint of the screen.
Does not repaint the screen, a subsequent call to `paint()` is required.
"""
if __debug__:
def trace(self, tracer: Callable[[str], None]) -> None:
"""Generate a JSON trace of the layout object.
The JSON can be emitted as a sequence of calls to `tracer`, each of
which is not necessarily a valid JSON chunk. The caller must
reassemble the chunks to get a sensible result.
"""
def bounds(self) -> None:
"""Paint bounds of individual components on screen."""
def page_count(self) -> int:
"""Return the number of pages in the layout object."""
def button_request(self) -> tuple[int, str] | None:
"""Return (code, type) of button request made during the last event or timer pass."""
def get_transition_out(self) -> AttachType:
"""Return the transition type."""
def return_value(self) -> T:
"""Retrieve the return value of the layout object."""
def __del__(self) -> None:
"""Calls drop on contents of the root component."""
# rust/src/ui/model_tt/layout.rs
class UiResult:
"""Result of an UI operation."""
pass
CONFIRMED: UiResult
CANCELLED: UiResult
INFO: UiResult
# rust/src/ui/model_tt/layout.rs # rust/src/ui/model_tt/layout.rs
@ -1626,32 +1500,3 @@ def confirm_firmware_update(
# rust/src/ui/model_tt/layout.rs # rust/src/ui/model_tt/layout.rs
def show_wait_text(message: str, /) -> LayoutObj[None]: def show_wait_text(message: str, /) -> LayoutObj[None]:
"""Show single-line text in the middle of the screen.""" """Show single-line text in the middle of the screen."""
# rust/src/ui/model_tt/layout.rs
class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings."""
MAX: ClassVar[int]
NORMAL: ClassVar[int]
LOW: ClassVar[int]
DIM: ClassVar[int]
NONE: ClassVar[int]
# rust/src/ui/model_tt/layout.rs
class AttachType:
INITIAL: ClassVar[int]
RESUME: ClassVar[int]
SWIPE_UP: ClassVar[int]
SWIPE_DOWN: ClassVar[int]
SWIPE_LEFT: ClassVar[int]
SWIPE_RIGHT: ClassVar[int]
# rust/src/ui/model_tt/layout.rs
class LayoutState:
"""Layout state."""
INITIAL: "ClassVar[LayoutState]"
ATTACHED: "ClassVar[LayoutState]"
TRANSITIONING: "ClassVar[LayoutState]"
DONE: "ClassVar[LayoutState]"

View File

@ -0,0 +1,97 @@
from typing import *
from trezor import utils
T = TypeVar("T")
# rust/src/ui/api/firmware_upy.rs
class LayoutObj(Generic[T]):
"""Representation of a Rust-based layout object.
see `trezor::ui::layout::obj::LayoutObj`.
"""
def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> LayoutState | None:
"""Attach a timer setter function.
The layout object can call the timer setter with two arguments,
`token` and `duration_ms`. When `duration_ms` elapses, the layout object
expects a callback to `self.timer(token)`.
"""
if utils.USE_TOUCH:
def touch_event(self, event: int, x: int, y: int) -> LayoutState | None:
"""Receive a touch event `event` at coordinates `x`, `y`."""
if utils.USE_BUTTON:
def button_event(self, event: int, button: int) -> LayoutState | None:
"""Receive a button event `event` for button `button`."""
def progress_event(self, value: int, description: str) -> LayoutState | None:
"""Receive a progress event."""
def usb_event(self, connected: bool) -> LayoutState | None:
"""Receive a USB connect/disconnect event."""
def timer(self, token: int) -> LayoutState | None:
"""Callback for the timer set by `attach_timer_fn`.
This function should be called by the executor after the corresponding
duration elapses.
"""
def paint(self) -> bool:
"""Paint the layout object on screen.
Will only paint updated parts of the layout as required.
Returns True if any painting actually happened.
"""
def request_complete_repaint(self) -> None:
"""Request a complete repaint of the screen.
Does not repaint the screen, a subsequent call to `paint()` is required.
"""
if __debug__:
def trace(self, tracer: Callable[[str], None]) -> None:
"""Generate a JSON trace of the layout object.
The JSON can be emitted as a sequence of calls to `tracer`, each of
which is not necessarily a valid JSON chunk. The caller must
reassemble the chunks to get a sensible result.
"""
def bounds(self) -> None:
"""Paint bounds of individual components on screen."""
def page_count(self) -> int:
"""Return the number of pages in the layout object."""
def button_request(self) -> tuple[int, str] | None:
"""Return (code, type) of button request made during the last event or timer pass."""
def get_transition_out(self) -> AttachType:
"""Return the transition type."""
def return_value(self) -> T:
"""Retrieve the return value of the layout object."""
def __del__(self) -> None:
"""Calls drop on contents of the root component."""
# rust/src/ui/api/firmware_upy.rs
class UiResult:
"""Result of a UI operation."""
pass
CONFIRMED: UiResult
CANCELLED: UiResult
INFO: UiResult
# rust/src/ui/api/firmware_upy.rs
class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings."""
MAX: ClassVar[int]
NORMAL: ClassVar[int]
LOW: ClassVar[int]
DIM: ClassVar[int]
NONE: ClassVar[int]
# rust/src/ui/api/firmware_upy.rs
class AttachType:
INITIAL: ClassVar[int]
RESUME: ClassVar[int]
SWIPE_UP: ClassVar[int]
SWIPE_DOWN: ClassVar[int]
SWIPE_LEFT: ClassVar[int]
SWIPE_RIGHT: ClassVar[int]
# rust/src/ui/api/firmware_upy.rs
class LayoutState:
"""Layout state."""
INITIAL: "ClassVar[LayoutState]"
ATTACHED: "ClassVar[LayoutState]"
TRANSITIONING: "ClassVar[LayoutState]"
DONE: "ClassVar[LayoutState]"

View File

@ -8,7 +8,7 @@ if __debug__:
from micropython import const from micropython import const
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui_api
from storage import debug as storage from storage import debug as storage
from trezor import io, log, loop, ui, utils, wire, workflow from trezor import io, log, loop, ui, utils, wire, workflow
from trezor.enums import DebugWaitType, MessageType from trezor.enums import DebugWaitType, MessageType
@ -195,11 +195,11 @@ if __debug__:
assert isinstance(ui.CURRENT_LAYOUT, ui.Layout) assert isinstance(ui.CURRENT_LAYOUT, ui.Layout)
if button == DebugButton.NO: if button == DebugButton.NO:
ui.CURRENT_LAYOUT._emit_message(trezorui2.CANCELLED) ui.CURRENT_LAYOUT._emit_message(trezorui_api.CANCELLED)
elif button == DebugButton.YES: elif button == DebugButton.YES:
ui.CURRENT_LAYOUT._emit_message(trezorui2.CONFIRMED) ui.CURRENT_LAYOUT._emit_message(trezorui_api.CONFIRMED)
elif button == DebugButton.INFO: elif button == DebugButton.INFO:
ui.CURRENT_LAYOUT._emit_message(trezorui2.INFO) ui.CURRENT_LAYOUT._emit_message(trezorui_api.INFO)
else: else:
raise RuntimeError("Invalid DebugButton") raise RuntimeError("Invalid DebugButton")

View File

@ -8,12 +8,12 @@ import trezorui2
from trezor import io, log, loop, utils, wire, workflow from trezor import io, log, loop, utils, wire, workflow
from trezor.messages import ButtonAck, ButtonRequest from trezor.messages import ButtonAck, ButtonRequest
from trezor.wire import context from trezor.wire import context
from trezorui2 import BacklightLevels, LayoutState from trezorui_api import BacklightLevels, LayoutState
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Callable, Generator, Generic, Iterator, TypeVar from typing import Any, Callable, Generator, Generic, Iterator, TypeVar
from trezorui2 import AttachType, LayoutObj, UiResult # noqa: F401 from trezorui_api import AttachType, LayoutObj, UiResult # noqa: F401
T = TypeVar("T", covariant=True) T = TypeVar("T", covariant=True)

View File

@ -1,6 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import ui, utils, workflow from trezor import ui, utils, workflow
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.messages import ButtonAck, ButtonRequest from trezor.messages import ButtonAck, ButtonRequest
@ -52,7 +53,7 @@ async def interact(
# wait for the layout result # wait for the layout result
result = await layout.get_result() result = await layout.get_result()
# raise an exception if the user cancelled the action # raise an exception if the user cancelled the action
if raise_on_cancel is not None and result is trezorui2.CANCELLED: if raise_on_cancel is not None and result is trezorui_api.CANCELLED:
raise raise_on_cancel raise raise_on_cancel
return result return result
@ -93,13 +94,13 @@ async def with_info(
first_br = next_br first_br = next_br
if result is trezorui2.CONFIRMED: if result is trezorui_api.CONFIRMED:
return return
elif result is trezorui2.INFO: elif result is trezorui_api.INFO:
info_result = await interact( info_result = await interact(
info_layout, next_br, br_code, raise_on_cancel=None info_layout, next_br, br_code, raise_on_cancel=None
) )
if info_layout_can_confirm and info_result is trezorui2.CONFIRMED: if info_layout_can_confirm and info_result is trezorui_api.CONFIRMED:
return return
else: else:
# no matter what the info layout returns, we always go back to the main layout # no matter what the info layout returns, we always go back to the main layout
@ -108,7 +109,7 @@ async def with_info(
raise RuntimeError # unexpected result raise RuntimeError # unexpected result
def draw_simple(layout: trezorui2.LayoutObj[Any]) -> None: def draw_simple(layout: trezorui_api.LayoutObj[Any]) -> None:
# Simple drawing not supported for layouts that set timers. # Simple drawing not supported for layouts that set timers.
def dummy_set_timer(token: int, duration: int) -> None: def dummy_set_timer(token: int, duration: int) -> None:
raise RuntimeError raise RuntimeError

View File

@ -2,6 +2,7 @@ from typing import TYPE_CHECKING
import storage.cache as storage_cache import storage.cache as storage_cache
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui from trezor import TR, ui
if TYPE_CHECKING: if TYPE_CHECKING:
@ -126,7 +127,7 @@ class Busyscreen(HomescreenBase):
# Handle timeout. # Handle timeout.
result = await super().get_result() result = await super().get_result()
assert result == trezorui2.CANCELLED assert result == trezorui_api.CANCELLED
storage_cache.delete(storage_cache.APP_COMMON_BUSY_DEADLINE_MS) storage_cache.delete(storage_cache.APP_COMMON_BUSY_DEADLINE_MS)
set_homescreen() set_homescreen()
return result return result

View File

@ -1,6 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui, utils from trezor import TR, ui, utils
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.wire import ActionCancelled from trezor.wire import ActionCancelled
@ -17,9 +18,9 @@ if TYPE_CHECKING:
BR_CODE_OTHER = ButtonRequestType.Other # global_import_cache BR_CODE_OTHER = ButtonRequestType.Other # global_import_cache
CONFIRMED = trezorui2.CONFIRMED CONFIRMED = trezorui_api.CONFIRMED
CANCELLED = trezorui2.CANCELLED CANCELLED = trezorui_api.CANCELLED
INFO = trezorui2.INFO INFO = trezorui_api.INFO
def confirm_action( def confirm_action(

View File

@ -1,4 +1,5 @@
import trezorui2 import trezorui2
import trezorui_api
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -20,7 +21,7 @@ async def confirm_fido(
) )
result = await interact(confirm, "confirm_fido", ButtonRequestType.Other) result = await interact(confirm, "confirm_fido", ButtonRequestType.Other)
if __debug__ and result is trezorui2.CONFIRMED: if __debug__ and result is trezorui_api.CONFIRMED:
# debuglink will directly inject a CONFIRMED message which we need to handle # debuglink will directly inject a CONFIRMED message which we need to handle
# by playing back a click to the Rust layout and getting out the selected number # by playing back a click to the Rust layout and getting out the selected number
# that way # that way
@ -51,4 +52,4 @@ async def confirm_fido_reset() -> bool:
prompt_screen=True, prompt_screen=True,
) )
) )
return (await confirm.get_result()) is trezorui2.CONFIRMED return (await confirm.get_result()) is trezorui_api.CONFIRMED

View File

@ -1,15 +1,16 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR from trezor import TR
from trezor.enums import ButtonRequestType, RecoveryType from trezor.enums import ButtonRequestType, RecoveryType
from ..common import interact from ..common import interact
from . import raise_if_not_confirmed from . import raise_if_not_confirmed
CONFIRMED = trezorui2.CONFIRMED # global_import_cache CONFIRMED = trezorui_api.CONFIRMED # global_import_cache
CANCELLED = trezorui2.CANCELLED # global_import_cache CANCELLED = trezorui_api.CANCELLED # global_import_cache
INFO = trezorui2.INFO # global_import_cache INFO = trezorui_api.INFO # global_import_cache
if TYPE_CHECKING: if TYPE_CHECKING:
from apps.management.recovery_device.layout import RemainingSharesInfo from apps.management.recovery_device.layout import RemainingSharesInfo

View File

@ -1,6 +1,7 @@
from typing import Awaitable, Callable, Sequence from typing import Awaitable, Callable, Sequence
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui from trezor import TR, ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.wire import ActionCancelled from trezor.wire import ActionCancelled
@ -8,7 +9,7 @@ from trezor.wire import ActionCancelled
from ..common import interact from ..common import interact
from . import raise_if_not_confirmed, show_success from . import raise_if_not_confirmed, show_success
CONFIRMED = trezorui2.CONFIRMED # global_import_cache CONFIRMED = trezorui_api.CONFIRMED # global_import_cache
def show_share_words( def show_share_words(
@ -172,7 +173,7 @@ async def _prompt_number(
# so use the initial one # so use the initial one
return count return count
if result is not trezorui2.CANCELLED: if result is not trezorui_api.CANCELLED:
assert isinstance(result, int) assert isinstance(result, int)
return result return result
else: else:

View File

@ -1,6 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui, utils from trezor import TR, ui, utils
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.wire import ActionCancelled from trezor.wire import ActionCancelled
@ -13,9 +14,9 @@ if TYPE_CHECKING:
from ..common import ExceptionType, PropertyType from ..common import ExceptionType, PropertyType
CONFIRMED = trezorui2.CONFIRMED CONFIRMED = trezorui_api.CONFIRMED
CANCELLED = trezorui2.CANCELLED CANCELLED = trezorui_api.CANCELLED
INFO = trezorui2.INFO INFO = trezorui_api.INFO
BR_CODE_OTHER = ButtonRequestType.Other # global_import_cache BR_CODE_OTHER = ButtonRequestType.Other # global_import_cache
@ -1128,7 +1129,7 @@ def error_popup(
*, *,
button: str = "", button: str = "",
timeout_ms: int = 0, timeout_ms: int = 0,
) -> trezorui2.LayoutObj[trezorui2.UiResult]: ) -> trezorui_api.LayoutObj[trezorui_api.UiResult]:
if button: if button:
raise NotImplementedError("Button not implemented") raise NotImplementedError("Button not implemented")

View File

@ -1,4 +1,5 @@
import trezorui2 import trezorui2
import trezorui_api
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -24,7 +25,7 @@ async def confirm_fido(
# For the usage in device tests, assuming CONFIRMED (sent by debuglink) # For the usage in device tests, assuming CONFIRMED (sent by debuglink)
# is choosing the first credential. # is choosing the first credential.
if __debug__ and result is trezorui2.CONFIRMED: if __debug__ and result is trezorui_api.CONFIRMED:
return 0 return 0
raise RuntimeError # should not get here, cancellation is handled by `interact` raise RuntimeError # should not get here, cancellation is handled by `interact`
@ -40,4 +41,4 @@ async def confirm_fido_reset() -> bool:
verb_cancel="", verb_cancel="",
verb=TR.buttons__confirm, verb=TR.buttons__confirm,
) )
return (await ui.Layout(confirm).get_result()) is trezorui2.CONFIRMED return (await ui.Layout(confirm).get_result()) is trezorui_api.CONFIRMED

View File

@ -1,6 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui from trezor import TR, ui
from trezor.enums import ButtonRequestType, RecoveryType from trezor.enums import ButtonRequestType, RecoveryType
@ -137,7 +138,7 @@ async def continue_recovery(
ButtonRequestType.RecoveryHomepage, ButtonRequestType.RecoveryHomepage,
raise_on_cancel=None, raise_on_cancel=None,
) )
if result is trezorui2.CONFIRMED: if result is trezorui_api.CONFIRMED:
return True return True
try: try:

View File

@ -3,11 +3,12 @@ from typing import TYPE_CHECKING
import trezorui2 import trezorui2
from trezor import TR from trezor import TR
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
import trezorui_api
from ..common import interact, raise_if_not_confirmed from ..common import interact, raise_if_not_confirmed
from . import confirm_action, show_success, show_warning from . import confirm_action, show_success, show_warning
CONFIRMED = trezorui2.CONFIRMED # global_import_cache CONFIRMED = trezorui_api.CONFIRMED # global_import_cache
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Awaitable, Sequence from typing import Awaitable, Sequence
@ -268,7 +269,7 @@ def show_intro_backup(single_share: bool, num_of_words: int | None) -> Awaitable
) )
def show_warning_backup() -> Awaitable[trezorui2.UiResult]: def show_warning_backup() -> Awaitable[trezorui_api.UiResult]:
return show_warning( return show_warning(
"backup_warning", "backup_warning",
TR.words__title_remember, TR.words__title_remember,
@ -295,7 +296,7 @@ def show_reset_warning(
subheader: str | None = None, subheader: str | None = None,
button: str | None = None, button: str | None = None,
br_code: ButtonRequestType = ButtonRequestType.Warning, br_code: ButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[trezorui2.UiResult]: ) -> Awaitable[trezorui_api.UiResult]:
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
return show_warning( return show_warning(

View File

@ -1,6 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui, utils from trezor import TR, ui, utils
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.wire import ActionCancelled from trezor.wire import ActionCancelled
@ -15,9 +16,9 @@ if TYPE_CHECKING:
BR_CODE_OTHER = ButtonRequestType.Other # global_import_cache BR_CODE_OTHER = ButtonRequestType.Other # global_import_cache
CONFIRMED = trezorui2.CONFIRMED CONFIRMED = trezorui_api.CONFIRMED
CANCELLED = trezorui2.CANCELLED CANCELLED = trezorui_api.CANCELLED
INFO = trezorui2.INFO INFO = trezorui_api.INFO
def confirm_action( def confirm_action(

View File

@ -1,4 +1,5 @@
import trezorui2 import trezorui2
import trezorui_api
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -20,7 +21,7 @@ async def confirm_fido(
) )
result = await interact(confirm, "confirm_fido", ButtonRequestType.Other) result = await interact(confirm, "confirm_fido", ButtonRequestType.Other)
if __debug__ and result is trezorui2.CONFIRMED: if __debug__ and result is trezorui_api.CONFIRMED:
# debuglink will directly inject a CONFIRMED message which we need to handle # debuglink will directly inject a CONFIRMED message which we need to handle
# by playing back a click to the Rust layout and getting out the selected number # by playing back a click to the Rust layout and getting out the selected number
# that way # that way
@ -32,7 +33,7 @@ async def confirm_fido(
msg = confirm.touch_event(io.TOUCH_END, 220, 220) msg = confirm.touch_event(io.TOUCH_END, 220, 220)
if confirm.paint(): if confirm.paint():
ui.refresh() ui.refresh()
assert msg is trezorui2.LayoutState.DONE assert msg is trezorui_api.LayoutState.DONE
retval = confirm.return_value() retval = confirm.return_value()
assert isinstance(retval, int) assert isinstance(retval, int)
return retval return retval
@ -59,4 +60,4 @@ async def confirm_fido_reset() -> bool:
reverse=True, reverse=True,
) )
) )
return (await confirm.get_result()) is trezorui2.CONFIRMED return (await confirm.get_result()) is trezorui_api.CONFIRMED

View File

@ -1,6 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR, ui from trezor import TR, ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -54,7 +55,7 @@ def show_remaining_shares(
groups: set[tuple[str, ...]], groups: set[tuple[str, ...]],
shares_remaining: list[int], shares_remaining: list[int],
group_threshold: int, group_threshold: int,
) -> Awaitable[trezorui2.UiResult]: ) -> Awaitable[trezorui_api.UiResult]:
from trezor import strings from trezor import strings
from trezor.crypto.slip39 import MAX_SHARE_COUNT from trezor.crypto.slip39 import MAX_SHARE_COUNT
@ -161,9 +162,9 @@ async def continue_recovery(
raise_on_cancel=None, raise_on_cancel=None,
) )
if result is trezorui2.CONFIRMED: if result is trezorui_api.CONFIRMED:
return True return True
elif result is trezorui2.INFO and remaining_shares_info is not None: elif result is trezorui_api.INFO and remaining_shares_info is not None:
await show_remaining_shares(*remaining_shares_info) await show_remaining_shares(*remaining_shares_info)
else: else:
try: try:

View File

@ -1,12 +1,13 @@
from typing import Awaitable, Callable, Sequence from typing import Awaitable, Callable, Sequence
import trezorui2 import trezorui2
import trezorui_api
from trezor import TR from trezor import TR
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from ..common import interact, raise_if_not_confirmed from ..common import interact, raise_if_not_confirmed
CONFIRMED = trezorui2.CONFIRMED # global_import_cache CONFIRMED = trezorui_api.CONFIRMED # global_import_cache
def _split_share_into_pages(share_words: Sequence[str], per_page: int = 4) -> list[str]: def _split_share_into_pages(share_words: Sequence[str], per_page: int = 4) -> list[str]:
@ -323,7 +324,7 @@ def show_intro_backup(single_share: bool, num_of_words: int | None) -> Awaitable
) )
def show_warning_backup() -> Awaitable[trezorui2.UiResult]: def show_warning_backup() -> Awaitable[trezorui_api.UiResult]:
return interact( return interact(
trezorui2.show_info( trezorui2.show_info(
title=TR.reset__never_make_digital_copy, title=TR.reset__never_make_digital_copy,
@ -351,7 +352,7 @@ def show_reset_warning(
subheader: str | None = None, subheader: str | None = None,
button: str | None = None, button: str | None = None,
br_code: ButtonRequestType = ButtonRequestType.Warning, br_code: ButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[trezorui2.UiResult]: ) -> Awaitable[trezorui_api.UiResult]:
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
return interact( return interact(
trezorui2.show_warning( trezorui2.show_warning(