diff --git a/core/src/trezor/ui/layouts/tt.py b/core/src/trezor/ui/layouts/tt.py index 616737682..8c3299b27 100644 --- a/core/src/trezor/ui/layouts/tt.py +++ b/core/src/trezor/ui/layouts/tt.py @@ -5,7 +5,7 @@ from trezor.enums import ButtonRequestType from trezor.ui.container import Container from trezor.ui.loader import LoaderDanger from trezor.ui.qr import Qr -from trezor.utils import chunks +from trezor.utils import chunks, chunks_intersperse from ..components.common import break_path_to_lines from ..components.common.confirm import is_confirmed, raise_if_cancelled @@ -33,10 +33,9 @@ if False: NoReturn, ) - from ..components.common.text import TextContent - ExceptionType = Union[BaseException, Type[BaseException]] + __all__ = ( "confirm_action", "confirm_reset_device", @@ -148,15 +147,15 @@ async def confirm_reset_device(ctx: wire.GenericContext, prompt: str) -> None: # TODO cleanup @ redesign async def confirm_backup(ctx: wire.GenericContext) -> bool: - text1 = Text("Success", ui.ICON_CONFIRM, ui.GREEN) - text1.bold("New wallet created", "successfully!") + text1 = Text("Success", ui.ICON_CONFIRM, ui.GREEN, new_lines=False) + text1.bold("New wallet created successfully!\n") text1.br_half() - text1.normal("You should back up your", "new wallet right now.") + text1.normal("You should back up your new wallet right now.") - text2 = Text("Warning", ui.ICON_WRONG, ui.RED) - text2.bold("Are you sure you want", "to skip the backup?") + text2 = Text("Warning", ui.ICON_WRONG, ui.RED, new_lines=False) + text2.bold("Are you sure you want to skip the backup?\n") text2.br_half() - text2.normal("You can back up your", "Trezor once, at any time.") + text2.normal("You can back up your Trezor once, at any time.") if is_confirmed( await interact( @@ -207,7 +206,7 @@ def _show_qr( def _split_address(address: str) -> Iterator[str]: - return chunks(address, MONO_CHARS_PER_LINE) + return chunks_intersperse(address, MONO_CHARS_PER_LINE) def _truncate_hex( @@ -225,7 +224,7 @@ def _truncate_hex( ) else: hex_data = hex_data[: (width * lines - 3)] + "..." - return chunks(hex_data, width) + return chunks_intersperse(hex_data, width) def _show_address( @@ -233,9 +232,9 @@ def _show_address( desc: str, network: str | None = None, ) -> Confirm: - text = Text(desc, ui.ICON_RECEIVE, ui.GREEN) + text = Text(desc, ui.ICON_RECEIVE, ui.GREEN, new_lines=False) if network is not None: - text.normal("%s network" % network) + text.normal("%s network\n" % network) text.mono(*_split_address(address)) return Confirm(text, cancel="QR", cancel_style=ButtonDefault) @@ -243,8 +242,8 @@ def _show_address( def _show_xpub(xpub: str, desc: str, cancel: str) -> Paginated: pages: list[ui.Component] = [] - for lines in chunks(list(chunks(xpub, 16)), 5): - text = Text(desc, ui.ICON_RECEIVE, ui.GREEN) + for lines in chunks(list(chunks_intersperse(xpub, 16)), TEXT_MAX_LINES * 2): + text = Text(desc, ui.ICON_RECEIVE, ui.GREEN, new_lines=False) text.mono(*lines) pages.append(text) @@ -440,8 +439,8 @@ async def confirm_output( address: str, amount: str, ) -> None: - text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN) - text.normal(amount + " to") + text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN, new_lines=False) + text.normal(amount + " to\n") text.mono(*_split_address(address)) await raise_if_cancelled( interact(ctx, Confirm(text), "confirm_output", ButtonRequestType.ConfirmOutput) @@ -453,9 +452,9 @@ async def confirm_decred_sstx_submission( address: str, amount: str, ) -> None: - text = Text("Purchase ticket", ui.ICON_SEND, ui.GREEN) + text = Text("Purchase ticket", ui.ICON_SEND, ui.GREEN, new_lines=False) text.normal(amount) - text.normal("with voting rights to") + text.normal("\nwith voting rights to\n") text.mono(*_split_address(address)) await raise_if_cancelled( interact( @@ -500,10 +499,10 @@ async def confirm_hex( async def confirm_total( ctx: wire.GenericContext, total_amount: str, fee_amount: str ) -> None: - text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN) - text.normal("Total amount:") + text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN, new_lines=False) + text.normal("Total amount:\n") text.bold(total_amount) - text.normal("including fee:") + text.normal("\nincluding fee:\n") text.bold(fee_amount) await raise_if_cancelled( interact(ctx, HoldToConfirm(text), "confirm_total", ButtonRequestType.SignTx) @@ -513,10 +512,10 @@ async def confirm_total( async def confirm_joint_total( ctx: wire.GenericContext, spending_amount: str, total_amount: str ) -> None: - text = Text("Joint transaction", ui.ICON_SEND, ui.GREEN) - text.normal("You are contributing:") + text = Text("Joint transaction", ui.ICON_SEND, ui.GREEN, new_lines=False) + text.normal("You are contributing:\n") text.bold(spending_amount) - text.normal("to the total amount:") + text.normal("\nto the total amount:\n") text.bold(total_amount) await raise_if_cancelled( interact( @@ -545,8 +544,8 @@ async def confirm_metadata( async def confirm_replacement( ctx: wire.GenericContext, description: str, txid: str ) -> None: - text = Text(description, ui.ICON_SEND, ui.GREEN) - text.normal("Confirm transaction ID:") + text = Text(description, ui.ICON_SEND, ui.GREEN, new_lines=False) + text.normal("Confirm transaction ID:\n") text.mono(*_truncate_hex(txid, TEXT_MAX_LINES - 1)) await raise_if_cancelled( interact(ctx, Confirm(text), "confirm_replacement", ButtonRequestType.SignTx) @@ -560,19 +559,19 @@ async def confirm_modify_output( amount_change: str, amount_new: str, ) -> None: - page1 = Text("Modify amount", ui.ICON_SEND, ui.GREEN) - page1.normal("Address:") + page1 = Text("Modify amount", ui.ICON_SEND, ui.GREEN, new_lines=False) + page1.normal("Address:\n") page1.br_half() page1.mono(*_split_address(address)) - page2 = Text("Modify amount", ui.ICON_SEND, ui.GREEN) + page2 = Text("Modify amount", ui.ICON_SEND, ui.GREEN, new_lines=False) if sign < 0: - page2.normal("Decrease amount by:") + page2.normal("Decrease amount by:\n") else: - page2.normal("Increase amount by:") + page2.normal("Increase amount by:\n") page2.bold(amount_change) page2.br_half() - page2.normal("New amount:") + page2.normal("\nNew amount:\n") page2.bold(amount_new) await raise_if_cancelled( @@ -591,17 +590,18 @@ async def confirm_modify_fee( user_fee_change: str, total_fee_new: str, ) -> None: - text = Text("Modify fee", ui.ICON_SEND, ui.GREEN) + text = Text("Modify fee", ui.ICON_SEND, ui.GREEN, new_lines=False) if sign == 0: - text.normal("Your fee did not change.") + text.normal("Your fee did not change.\n") else: if sign < 0: - text.normal("Decrease your fee by:") + text.normal("Decrease your fee by:\n") else: - text.normal("Increase your fee by:") + text.normal("Increase your fee by:\n") text.bold(user_fee_change) + text.br() text.br_half() - text.normal("Transaction fee:") + text.normal("Transaction fee:\n") text.bold(total_fee_new) await raise_if_cancelled( interact(ctx, HoldToConfirm(text), "modify_fee", ButtonRequestType.SignTx) @@ -626,15 +626,11 @@ async def confirm_coinjoin( async def confirm_sign_identity( ctx: wire.GenericContext, proto: str, identity: str, challenge_visual: str | None ) -> None: - lines: list[TextContent] = [] + text = Text("Sign %s" % proto, new_lines=False) if challenge_visual: - lines.append(challenge_visual) - - lines.append(ui.MONO) - lines.extend(chunks(identity, 18)) - - text = Text("Sign %s" % proto) - text.normal(*lines) + text.normal(challenge_visual) + text.br() + text.mono(*chunks_intersperse(identity, 18)) await raise_if_cancelled( interact(ctx, Confirm(text), "sign_identity", ButtonRequestType.Other) ) @@ -648,8 +644,8 @@ async def confirm_signverify( font = ui.MONO br_type = "verify_message" - text = Text(header) - text.bold("Confirm address:") + text = Text(header, new_lines=False) + text.bold("Confirm address:\n") text.mono(*_split_address(address)) await raise_if_cancelled( interact(ctx, Confirm(text), br_type, ButtonRequestType.Other) diff --git a/core/src/trezor/utils.py b/core/src/trezor/utils.py index 2f2852359..e15e2de37 100644 --- a/core/src/trezor/utils.py +++ b/core/src/trezor/utils.py @@ -113,6 +113,18 @@ def chunks(items: Chunkable, size: int) -> Iterator[Chunkable]: yield items[i : i + size] +def chunks_intersperse( + items: Chunkable, size: int, sep: str = "\n" +) -> Iterator[Chunkable]: + first = True + for i in range(0, len(items), size): + if not first: + yield sep + else: + first = False + yield items[i : i + size] + + if False: class HashContext(Protocol): diff --git a/tests/click_tests/test_autolock.py b/tests/click_tests/test_autolock.py index 4e1efb759..a237fec18 100644 --- a/tests/click_tests/test_autolock.py +++ b/tests/click_tests/test_autolock.py @@ -79,7 +79,7 @@ def test_autolock_interrupts_signing(device_handler): assert "1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1" in layout.text.replace(" ", "") layout = debug.click(buttons.OK, wait=True) - assert "Total amount: 0.0039 BTC" in layout.text + assert "Total amount: 0.0039 BTC" in layout.text # wait for autolock to kick in time.sleep(10.1)