Skip to content

Commit

Permalink
feat(core/ui): unify progress.py code between models, implement stora…
Browse files Browse the repository at this point in the history
…ge translations

fixes #3520
  • Loading branch information
matejcik committed Mar 15, 2024
1 parent df1ca72 commit cb29467
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 183 deletions.
4 changes: 4 additions & 0 deletions core/embed/rust/librust_qstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@ static void _librust_qstrs(void) {
MP_QSTR_sign_message__verify_address;
MP_QSTR_skip_first_paint;
MP_QSTR_spending_amount;
MP_QSTR_storage_msg__processing;
MP_QSTR_storage_msg__starting;
MP_QSTR_storage_msg__verifying_pin;
MP_QSTR_storage_msg__wrong_pin;
MP_QSTR_subprompt;
MP_QSTR_subtitle;
MP_QSTR_text_mono;
Expand Down
12 changes: 12 additions & 0 deletions core/embed/rust/src/translations/generated/translated_string.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 14 additions & 10 deletions core/embed/rust/src/ui/model_tr/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1571,18 +1571,22 @@ extern "C" fn new_show_group_share_success(

extern "C" fn new_show_progress(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)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?;
let description: StrBuffer =
kwargs.get_or(Qstr::MP_QSTR_description, StrBuffer::empty())?;
let title: Option<StrBuffer> = kwargs
.get(Qstr::MP_QSTR_title)
.and_then(Obj::try_into_option)
.unwrap_or(None);

let mut progress =
Progress::new(indeterminate, description).with_update_description(StrBuffer::alloc);
if let Some(title) = title {
progress = progress.with_title(title);
};

// Description updates are received as &str and we need to provide a way to
// convert them to StrBuffer.
let obj = LayoutObj::new(
Progress::new(indeterminate, description)
.with_title(title)
.with_update_description(StrBuffer::alloc),
)?;
let obj = LayoutObj::new(progress)?;
Ok(obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
Expand Down Expand Up @@ -2074,9 +2078,9 @@ pub static mp_module_trezorui2: Module = obj_module! {

/// def show_progress(
/// *,
/// title: str,
/// description: str,
/// indeterminate: bool = False,
/// description: str = "",
/// title: str | None = None,
/// ) -> LayoutObj[UiResult]:
/// """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
Expand Down
18 changes: 13 additions & 5 deletions core/embed/rust/src/ui/model_tt/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1547,10 +1547,18 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:

extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let indeterminate: bool = kwargs.get_or(Qstr::MP_QSTR_indeterminate, false)?;
let description: StrBuffer =
kwargs.get_or(Qstr::MP_QSTR_description, StrBuffer::empty())?;
let title: Option<StrBuffer> = kwargs
.get(Qstr::MP_QSTR_title)
.and_then(Obj::try_into_option)
.unwrap_or(None);

let (title, description) = if let Some(title) = title {
(title, description)
} else {
(description, StrBuffer::empty())
};

// Description updates are received as &str and we need to provide a way to
// convert them to StrBuffer.
Expand Down Expand Up @@ -2130,9 +2138,9 @@ pub static mp_module_trezorui2: Module = obj_module! {

/// def show_progress(
/// *,
/// title: str,
/// description: str,
/// indeterminate: bool = False,
/// description: str = "",
/// title: str | None = None,
/// ) -> LayoutObj[UiResult]:
/// """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
Expand Down
8 changes: 4 additions & 4 deletions core/mocks/generated/trezorui2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,9 @@ def show_group_share_success(
# rust/src/ui/model_tr/layout.rs
def show_progress(
*,
title: str,
description: str,
indeterminate: bool = False,
description: str = "",
title: str | None = None,
) -> LayoutObj[UiResult]:
"""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
Expand Down Expand Up @@ -917,9 +917,9 @@ def show_remaining_shares(
# rust/src/ui/model_tt/layout.rs
def show_progress(
*,
title: str,
description: str,
indeterminate: bool = False,
description: str = "",
title: str | None = None,
) -> LayoutObj[UiResult]:
"""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
Expand Down
4 changes: 4 additions & 0 deletions core/mocks/trezortranslate_keys.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,10 @@ class TR:
stellar__value_sha256: str = "Value (SHA-256):"
stellar__wanna_clean_value_key_template: str = "Do you want to clear value key {0}?"
stellar__your_account: str = " your account"
storage_msg__processing: str = "PROCESSING"
storage_msg__starting: str = "STARTING UP"
storage_msg__verifying_pin: str = "VERIFYING PIN"
storage_msg__wrong_pin: str = "WRONG PIN"
tezos__baker_address: str = "Baker address:"
tezos__balance: str = "Balance:"
tezos__ballot: str = "Ballot:"
Expand Down
4 changes: 0 additions & 4 deletions core/src/all_modules.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/src/apps/management/authenticate_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async def authenticate_device(msg: AuthenticateDevice) -> AuthenticityProof:
write_compact_size(h, len(msg.challenge))
h.extend(msg.challenge)

spinner = progress("", description=TR.progress__authenticity_check)
spinner = progress(TR.progress__authenticity_check)
spinner.report(0)

try:
Expand Down
2 changes: 1 addition & 1 deletion core/src/apps/management/change_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def report(value: int) -> None:
nonlocal loader
if loader is None:
workflow.close_others()
loader = progress("", TR.language__progress)
loader = progress(TR.language__progress)
loader.report(value)

if msg.data_length == 0:
Expand Down
2 changes: 1 addition & 1 deletion core/src/apps/management/reset_device/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async def reset_device(msg: ResetDevice) -> Success:
await confirm_reset_device(title)

# Rendering empty loader so users do not feel a freezing screen
render_empty_loader(TR.progress__processing, "")
render_empty_loader(config.StorageMessage.PROCESSING_MSG)

# wipe storage to make sure the device is in a clear state
storage.reset()
Expand Down
18 changes: 12 additions & 6 deletions core/src/trezor/pin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from typing import TYPE_CHECKING

from . import config

if TYPE_CHECKING:
from typing import Any
from typing import Any, Container

from trezor.ui.layouts.common import ProgressLayout

Expand All @@ -11,21 +13,23 @@
_started_with_empty_loader = False
keepalive_callback: Any = None

_ignore_loader_messages: tuple[str, ...] = ()
_ignore_loader_messages: Container[config.StorageMessage] = ()


def ignore_nonpin_loader_messages() -> None:
global _ignore_loader_messages
# TODO: handle translation of those (in C)
_ignore_loader_messages = ("Processing", "Starting up")
_ignore_loader_messages = (
config.StorageMessage.PROCESSING_MSG,
config.StorageMessage.STARTING_MSG,
)


def allow_all_loader_messages() -> None:
global _ignore_loader_messages
_ignore_loader_messages = ()


def render_empty_loader(message: str, description: str) -> None:
def render_empty_loader(message: config.StorageMessage, description: str = "") -> None:
"""Render empty loader to prevent the screen appear to be frozen."""
from trezor.ui.layouts.progress import pin_progress

Expand All @@ -38,7 +42,9 @@ def render_empty_loader(message: str, description: str) -> None:
_started_with_empty_loader = True


def show_pin_timeout(seconds: int, progress: int, message: str) -> bool:
def show_pin_timeout(
seconds: int, progress: int, message: config.StorageMessage
) -> bool:
from trezor import TR
from trezor.ui.layouts.progress import pin_progress

Expand Down
106 changes: 101 additions & 5 deletions core/src/trezor/ui/layouts/progress.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,102 @@
from trezor import utils
from typing import TYPE_CHECKING

if utils.UI_LAYOUT == "TT":
from .tt.progress import * # noqa: F401,F403
elif utils.UI_LAYOUT == "TR":
from .tr.progress import * # noqa: F401,F403
import trezorui2
from trezor import TR, config, ui, utils

if TYPE_CHECKING:
from typing import Any

from .common import ProgressLayout


def _storage_message_to_str(message: config.StorageMessage | None) -> str | None:
from trezor import TR

if message is None:
return None

if message == config.StorageMessage.NO_MSG:
return ""
if message == config.StorageMessage.VERIFYING_PIN_MSG:
return TR.storage_msg__verifying_pin
if message == config.StorageMessage.PROCESSING_MSG:
return TR.storage_msg__processing
if message == config.StorageMessage.STARTING_MSG:
return TR.storage_msg__starting
if message == config.StorageMessage.WRONG_PIN_MSG:
return TR.storage_msg__wrong_pin
raise RuntimeError # unknown message


class RustProgress:
def __init__(
self,
layout: Any,
):
self.layout = layout
ui.backlight_fade(ui.style.BACKLIGHT_DIM)
self.layout.attach_timer_fn(self.set_timer)
self.layout.paint()
ui.refresh()
ui.backlight_fade(ui.style.BACKLIGHT_NORMAL)

def set_timer(self, token: int, deadline: int) -> None:
raise RuntimeError # progress layouts should not set timers

def report(self, value: int, description: str | None = None):
msg = self.layout.progress_event(value, description or "")
assert msg is None
self.layout.paint()
ui.refresh()


def progress(
description: str | None = None,
title: str | None = None,
indeterminate: bool = False,
) -> ProgressLayout:
if description is None:
description = TR.progress__please_wait # def_arg

if title is not None:
title = title.upper()
elif not utils.MODEL_IS_T2B1:
# on TT, uppercase the description which ends up on top of the screen
# when no title is set
description = description.upper()

return RustProgress(
layout=trezorui2.show_progress(
description=description,
title=title,
indeterminate=indeterminate,
)
)


def bitcoin_progress(message: str) -> ProgressLayout:
return progress(message)


def coinjoin_progress(message: str) -> ProgressLayout:
return RustProgress(
layout=trezorui2.show_progress_coinjoin(
title=message, indeterminate=False
)
)


def pin_progress(title: config.StorageMessage, description: str) -> ProgressLayout:
return progress(description=description, title=_storage_message_to_str(title))


if not utils.BITCOIN_ONLY:

def monero_keyimage_sync_progress() -> ProgressLayout:
return progress(TR.progress__syncing)

def monero_live_refresh_progress() -> ProgressLayout:
return progress(TR.progress__refreshing, indeterminate=True)

def monero_transaction_progress_inner() -> ProgressLayout:
return progress(TR.progress__signing_transaction)
Loading

0 comments on commit cb29467

Please sign in to comment.