From 6ded531f8fe666bde8a800d4a4a902555dae813c Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Wed, 10 Feb 2021 18:36:08 +0100 Subject: [PATCH] refactor(core): convert apps.common.sdcard to layouts --- core/src/apps/common/sdcard.py | 113 +++++++++++++-------- core/src/apps/management/sd_protect.py | 28 ++---- core/src/trezor/ui/layouts/tt.py | 130 +++++++++++++++++++------ 3 files changed, 180 insertions(+), 91 deletions(-) diff --git a/core/src/apps/common/sdcard.py b/core/src/apps/common/sdcard.py index 569c24b95..e52815a3a 100644 --- a/core/src/apps/common/sdcard.py +++ b/core/src/apps/common/sdcard.py @@ -1,9 +1,7 @@ import storage.sd_salt from storage.sd_salt import SD_CARD_HOT_SWAPPABLE from trezor import fatfs, sdcard, ui, wire -from trezor.ui.components.tt.text import Text - -from apps.common.confirm import confirm, hold_to_confirm +from trezor.ui.layouts import confirm_action, show_error if False: from typing import Optional @@ -14,60 +12,95 @@ class SdCardUnavailable(wire.ProcessError): async def _wrong_card_dialog(ctx: wire.GenericContext) -> bool: - text = Text("SD card protection", ui.ICON_WRONG) - text.bold("Wrong SD card.") - text.br_half() if SD_CARD_HOT_SWAPPABLE: - text.normal("Please insert the", "correct SD card for", "this device.") - btn_confirm: Optional[str] = "Retry" - btn_cancel = "Abort" + return await confirm_action( + ctx, + "warning_wrong_sd", + "SD card protection", + action="Wrong SD card.", + description="Please insert the correct SD card for this device.", + verb="Retry", + verb_cancel="Abort", + icon=ui.ICON_WRONG, + larger_vspace=True, + ) else: - text.normal("Please unplug the", "device and insert the", "correct SD card.") - btn_confirm = None - btn_cancel = "Close" - - return await confirm(ctx, text, confirm=btn_confirm, cancel=btn_cancel) + return await show_error( + ctx, + "warning_wrong_sd", + header="SD card protection", + subheader="Wrong SD card.", + content="Please unplug the\ndevice and insert the correct SD card.", + ) async def insert_card_dialog(ctx: wire.GenericContext) -> bool: - text = Text("SD card protection", ui.ICON_WRONG) - text.bold("SD card required.") - text.br_half() if SD_CARD_HOT_SWAPPABLE: - text.normal("Please insert your", "SD card.") - btn_confirm: Optional[str] = "Retry" - btn_cancel = "Abort" + return await confirm_action( + ctx, + "warning_no_sd", + "SD card protection", + action="SD card required.", + description="Please insert your SD card.", + verb="Retry", + verb_cancel="Abort", + icon=ui.ICON_WRONG, + larger_vspace=True, + ) else: - text.normal("Please unplug the", "device and insert your", "SD card.") - btn_confirm = None - btn_cancel = "Close" - - return await confirm(ctx, text, confirm=btn_confirm, cancel=btn_cancel) + return await show_error( + ctx, + "warning_no_sd", + header="SD card protection", + subheader="SD card required.", + content="Please unplug the\ndevice and insert your SD card.", + ) async def format_card_dialog(ctx: wire.GenericContext) -> bool: # Format card? yes/no - text = Text("SD card error", ui.ICON_WRONG, ui.RED) - text.bold("Unknown filesystem.") - text.br_half() - text.normal("Use a different card or") - text.normal("format the SD card to") - text.normal("the FAT32 filesystem.") - if not await confirm(ctx, text, confirm="Format", cancel="Cancel"): + if not await confirm_action( + ctx, + "warning_format_sd", + "SD card error", + action="Unknown filesystem.", + description="Use a different card or format the SD card to the FAT32 filesystem.", + icon=ui.ICON_WRONG, + icon_color=ui.RED, + verb="Format", + verb_cancel="Cancel", + larger_vspace=True, + ): return False # Confirm formatting - text = Text("Format SD card", ui.ICON_WIPE, ui.RED) - text.normal("Do you really want to", "format the SD card?") - text.br_half() - text.bold("All data on the SD card", "will be lost.") - return await hold_to_confirm(ctx, text, confirm="Format SD card") + return await confirm_action( + ctx, + "confirm_format_sd", + "Format SD card", + action="All data on the SD card will be lost.", + description="Do you really want to format the SD card?", + reverse=True, + verb="Format SD card", + icon=ui.ICON_WIPE, + icon_color=ui.RED, + hold=True, + larger_vspace=True, + ) async def sd_problem_dialog(ctx: wire.GenericContext) -> bool: - text = Text("SD card problem", ui.ICON_WRONG, ui.RED) - text.normal("There was a problem", "accessing the SD card.") - return await confirm(ctx, text, confirm="Retry", cancel="Abort") + return await confirm_action( + ctx, + "warning_sd_retry", + "SD card problem", + action=None, + description="There was a problem accessing the SD card.", + icon=ui.ICON_WRONG, + icon_color=ui.RED, + verb="Retry", + verb_cancel="Abort", + ) async def ensure_sdcard( diff --git a/core/src/apps/management/sd_protect.py b/core/src/apps/management/sd_protect.py index eb477ef0a..a113bcae5 100644 --- a/core/src/apps/management/sd_protect.py +++ b/core/src/apps/management/sd_protect.py @@ -1,13 +1,11 @@ import storage.device import storage.sd_salt -from trezor import config, ui, wire +from trezor import config, wire from trezor.crypto import random from trezor.messages import SdProtectOperationType from trezor.messages.Success import Success -from trezor.ui.components.tt.text import Text -from trezor.ui.layouts import require, show_success +from trezor.ui.layouts import confirm_action, require, show_success -from apps.common.confirm import require_confirm from apps.common.request_pin import ( error_pin_invalid, request_pin, @@ -167,24 +165,14 @@ async def sd_protect_refresh(ctx: wire.Context, msg: SdProtect) -> Success: def require_confirm_sd_protect(ctx: wire.Context, msg: SdProtect) -> Awaitable[None]: if msg.operation == SdProtectOperationType.ENABLE: - text = Text("SD card protection", ui.ICON_CONFIG) - text.normal( - "Do you really want to", "secure your device with", "SD card protection?" - ) + text = "Do you really want to secure your device with SD card protection?" elif msg.operation == SdProtectOperationType.DISABLE: - text = Text("SD card protection", ui.ICON_CONFIG) - text.normal( - "Do you really want to", "remove SD card", "protection from your", "device?" - ) + text = "Do you really want to remove SD card protection from your device?" elif msg.operation == SdProtectOperationType.REFRESH: - text = Text("SD card protection", ui.ICON_CONFIG) - text.normal( - "Do you really want to", - "replace the current", - "SD card secret with a", - "newly generated one?", - ) + text = "Do you really want to replace the current\nSD card secret with a newly generated one?" else: raise wire.ProcessError("Unknown operation") - return require_confirm(ctx, text) + return require( + confirm_action(ctx, "set_sd", "SD card protection", description=text) + ) diff --git a/core/src/trezor/ui/layouts/tt.py b/core/src/trezor/ui/layouts/tt.py index e25cf2560..bf0002952 100644 --- a/core/src/trezor/ui/layouts/tt.py +++ b/core/src/trezor/ui/layouts/tt.py @@ -24,7 +24,7 @@ from ..constants.tt import ( from .common import interact if False: - from typing import Any, Iterator, List, Sequence, Union, Optional + from typing import Any, Iterator, List, Sequence, Union, Optional, Awaitable from trezor import wire from trezor.messages.ButtonRequest import EnumTypeButtonRequestType @@ -37,6 +37,7 @@ __all__ = ( "confirm_backup", "confirm_path_warning", "show_address", + "show_error", "show_pubkey", "show_success", "show_xpub", @@ -57,24 +58,45 @@ async def confirm_action( ctx: wire.GenericContext, br_type: str, title: str, - action: str, + action: str = None, description: str = None, - verb: Union[str, bytes] = Confirm.DEFAULT_CONFIRM, - verb_cancel: Union[str, bytes] = Confirm.DEFAULT_CANCEL, - icon: str = None, + verb: Union[str, bytes, None] = Confirm.DEFAULT_CONFIRM, + verb_cancel: Union[str, bytes, None] = Confirm.DEFAULT_CANCEL, + hold: bool = False, + icon: str = None, # TODO cleanup @ redesign + icon_color: int = None, # TODO cleanup @ redesign + reverse: bool = False, # TODO cleanup @ redesign + larger_vspace: bool = False, # TODO cleanup @ redesign br_code: EnumTypeButtonRequestType = ButtonRequestType.Other, **kwargs: Any, ) -> bool: - text = Text(title, icon if icon is not None else ui.ICON_DEFAULT, new_lines=False) - text.bold(action) - text.br() - if description: + text = Text( + title, + icon if icon is not None else ui.ICON_DEFAULT, + icon_color if icon_color is not None else ui.ORANGE_ICON, + new_lines=False, + ) + + if reverse and description is not None: text.normal(description) + elif action is not None: + text.bold(action) + + if action is not None and description is not None: + text.br() + if larger_vspace: + text.br_half() + if reverse and action is not None: + text.bold(action) + elif description is not None: + text.normal(description) + + cls = HoldToConfirm if hold else Confirm return is_confirmed( await interact( ctx, - Confirm(text, confirm=verb, cancel=verb_cancel), + cls(text, confirm=verb, cancel=verb_cancel), br_type, br_code, ) @@ -289,14 +311,19 @@ async def show_pubkey( ) -async def show_warning( +async def _show_modal( ctx: wire.GenericContext, br_type: str, + br_code: EnumTypeButtonRequestType, + header: str, + subheader: Optional[str], content: str, - subheader: Optional[str] = None, - button: str = "Try again", + button_confirm: Optional[str], + button_cancel: Optional[str], + icon: str, + icon_color: int, ) -> bool: - text = Text("Warning", ui.ICON_WRONG, ui.RED, new_lines=False) + text = Text(header, icon, icon_color, new_lines=False) if subheader: text.bold(subheader) text.br() @@ -305,33 +332,74 @@ async def show_warning( return is_confirmed( await interact( ctx, - Confirm(text, confirm=button, cancel=None), + Confirm(text, confirm=button_confirm, cancel=button_cancel), br_type, - ButtonRequestType.Warning, + br_code, ) ) -async def show_success( +def show_error( + ctx: wire.GenericContext, + br_type: str, + content: str, + header: str = "Error", + subheader: Optional[str] = None, + button: str = "Close", +) -> Awaitable[bool]: + return _show_modal( + ctx, + br_type=br_type, + br_code=ButtonRequestType.Other, + header=header, + subheader=subheader, + content=content, + button_confirm=None, + button_cancel=button, + icon=ui.ICON_WRONG, + icon_color=ui.ORANGE_ICON, + ) + + +def show_warning( + ctx: wire.GenericContext, + br_type: str, + content: str, + subheader: Optional[str] = None, + button: str = "Try again", +) -> Awaitable[bool]: + return _show_modal( + ctx, + br_type=br_type, + br_code=ButtonRequestType.Warning, + header="Warning", + subheader=subheader, + content=content, + button_confirm=button, + button_cancel=None, + icon=ui.ICON_WRONG, + icon_color=ui.RED, + ) + + +def show_success( ctx: wire.GenericContext, br_type: str, content: str, subheader: Optional[str] = None, button: str = "Continue", -) -> bool: - text = Text("Success", ui.ICON_CONFIRM, ui.GREEN, new_lines=False) - if subheader: - text.bold(subheader) - text.br() - text.br_half() - text.normal(content) - return is_confirmed( - await interact( - ctx, - Confirm(text, confirm=button, cancel=None), - br_type, - ButtonRequestType.Success, - ) +) -> Awaitable[bool]: + return _show_modal( + ctx, + br_type=br_type, + br_code=ButtonRequestType.Success, + header="Success", + subheader=subheader, + content=content, + button_confirm=button, + button_cancel=None, + icon=ui.ICON_CONFIRM, + icon_color=ui.GREEN, )