parent
ca80a6e9bf
commit
b75dbe18e4
@ -0,0 +1,7 @@
|
|||||||
|
# Automatically generated by pb2py
|
||||||
|
# fmt: off
|
||||||
|
# isort:skip_file
|
||||||
|
|
||||||
|
IMMEDIATE = 0
|
||||||
|
NEXT_LAYOUT = 1
|
||||||
|
CURRENT_LAYOUT = 2
|
@ -1,42 +1,60 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor import log, workflow
|
import trezorui2
|
||||||
|
from trezor import log, ui, workflow
|
||||||
from trezor.enums import ButtonRequestType
|
from trezor.enums import ButtonRequestType
|
||||||
from trezor.messages import ButtonAck, ButtonRequest
|
from trezor.messages import ButtonAck, ButtonRequest
|
||||||
from trezor.wire import context
|
from trezor.wire import ActionCancelled, context
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Awaitable, Protocol, TypeVar
|
from typing import Awaitable, Callable, TypeVar
|
||||||
|
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
LayoutType = Awaitable
|
|
||||||
PropertyType = tuple[str | None, str | bytes | None]
|
PropertyType = tuple[str | None, str | bytes | None]
|
||||||
ExceptionType = BaseException | type[BaseException]
|
ExceptionType = BaseException | type[BaseException]
|
||||||
|
|
||||||
class ProgressLayout(Protocol):
|
InfoFunc = Callable[[], Awaitable[None]]
|
||||||
def report(self, value: int, description: str | None = None) -> None: ...
|
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
async def button_request(
|
|
||||||
|
async def _button_request(
|
||||||
br_type: str,
|
br_type: str,
|
||||||
code: ButtonRequestType = ButtonRequestType.Other,
|
code: ButtonRequestType = ButtonRequestType.Other,
|
||||||
pages: int | None = None,
|
pages: int = 0,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
workflow.close_others()
|
||||||
if __debug__:
|
if __debug__:
|
||||||
log.debug(__name__, "ButtonRequest.type=%s", br_type)
|
log.debug(__name__, "ButtonRequest.type=%s", br_type)
|
||||||
workflow.close_others()
|
await context.maybe_call(ButtonRequest(code=code, pages=pages or None), ButtonAck)
|
||||||
await context.maybe_call(ButtonRequest(code=code, pages=pages), ButtonAck)
|
|
||||||
|
|
||||||
|
|
||||||
async def interact(
|
async def interact(
|
||||||
layout: LayoutType[T],
|
layout_obj: ui.LayoutObj[T],
|
||||||
br_type: str,
|
br_type: str | None,
|
||||||
br_code: ButtonRequestType = ButtonRequestType.Other,
|
br_code: ButtonRequestType = ButtonRequestType.Other,
|
||||||
|
raise_on_cancel: ExceptionType | None = ActionCancelled,
|
||||||
) -> T:
|
) -> T:
|
||||||
pages = None
|
# shut down other workflows to prevent them from interfering with the current one
|
||||||
if hasattr(layout, "page_count") and layout.page_count() > 1: # type: ignore [Cannot access member "page_count" for type "LayoutType"]
|
workflow.close_others()
|
||||||
# We know for certain how many pages the layout will have
|
# start the layout
|
||||||
pages = layout.page_count() # type: ignore [Cannot access member "page_count" for type "LayoutType"]
|
layout = ui.Layout(layout_obj)
|
||||||
await button_request(br_type, br_code, pages)
|
layout.start()
|
||||||
return await context.wait(layout)
|
# send the button request
|
||||||
|
if br_type is not None:
|
||||||
|
await _button_request(br_type, br_code, layout_obj.page_count())
|
||||||
|
# wait for the layout result
|
||||||
|
result = await context.wait(layout.get_result())
|
||||||
|
# raise an exception if the user cancelled the action
|
||||||
|
if raise_on_cancel is not None and result is trezorui2.CANCELLED:
|
||||||
|
raise raise_on_cancel
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def raise_if_not_confirmed(
|
||||||
|
layout_obj: ui.LayoutObj[ui.UiResult],
|
||||||
|
br_type: str | None,
|
||||||
|
br_code: ButtonRequestType = ButtonRequestType.Other,
|
||||||
|
exc: ExceptionType = ActionCancelled,
|
||||||
|
) -> Awaitable[None]:
|
||||||
|
action = interact(layout_obj, br_type, br_code, exc)
|
||||||
|
return action # type: ignore [Type cannot be assigned to type "None"]
|
||||||
|
@ -1,6 +1,132 @@
|
|||||||
from trezor import utils
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if utils.UI_LAYOUT == "TT":
|
import storage.cache as storage_cache
|
||||||
from .tt.homescreen import * # noqa: F401,F403
|
import trezorui2
|
||||||
elif utils.UI_LAYOUT == "TR":
|
from trezor import TR, ui
|
||||||
from .tr.homescreen import * # noqa: F401,F403
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Any, Iterator
|
||||||
|
|
||||||
|
from trezor import loop
|
||||||
|
|
||||||
|
|
||||||
|
class HomescreenBase(ui.Layout):
|
||||||
|
RENDER_INDICATOR: object | None = None
|
||||||
|
|
||||||
|
def __init__(self, layout: Any) -> None:
|
||||||
|
super().__init__(layout=layout)
|
||||||
|
|
||||||
|
def _paint(self) -> None:
|
||||||
|
self.layout.paint()
|
||||||
|
ui.refresh()
|
||||||
|
|
||||||
|
def _first_paint(self) -> None:
|
||||||
|
if storage_cache.homescreen_shown is not self.RENDER_INDICATOR:
|
||||||
|
super()._first_paint()
|
||||||
|
storage_cache.homescreen_shown = self.RENDER_INDICATOR
|
||||||
|
# else:
|
||||||
|
# self._paint()
|
||||||
|
|
||||||
|
|
||||||
|
class Homescreen(HomescreenBase):
|
||||||
|
RENDER_INDICATOR = storage_cache.HOMESCREEN_ON
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
label: str | None,
|
||||||
|
notification: str | None,
|
||||||
|
notification_is_error: bool,
|
||||||
|
hold_to_lock: bool,
|
||||||
|
) -> None:
|
||||||
|
level = 1
|
||||||
|
if notification is not None:
|
||||||
|
notification = notification.rstrip("!")
|
||||||
|
if notification == TR.homescreen__title_coinjoin_authorized:
|
||||||
|
level = 3
|
||||||
|
elif notification == TR.homescreen__title_experimental_mode:
|
||||||
|
level = 2
|
||||||
|
elif notification_is_error:
|
||||||
|
level = 0
|
||||||
|
|
||||||
|
skip = storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
||||||
|
super().__init__(
|
||||||
|
layout=trezorui2.show_homescreen(
|
||||||
|
label=label,
|
||||||
|
notification=notification,
|
||||||
|
notification_level=level,
|
||||||
|
hold=hold_to_lock,
|
||||||
|
skip_first_paint=skip,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def usb_checker_task(self) -> None:
|
||||||
|
from trezor import io, loop
|
||||||
|
|
||||||
|
usbcheck = loop.wait(io.USB_CHECK)
|
||||||
|
while True:
|
||||||
|
is_connected = await usbcheck
|
||||||
|
self.layout.usb_event(is_connected)
|
||||||
|
self.layout.paint()
|
||||||
|
ui.refresh()
|
||||||
|
|
||||||
|
def create_tasks(self) -> Iterator[loop.Task]:
|
||||||
|
yield from super().create_tasks()
|
||||||
|
yield self.usb_checker_task()
|
||||||
|
|
||||||
|
|
||||||
|
class Lockscreen(HomescreenBase):
|
||||||
|
RENDER_INDICATOR = storage_cache.LOCKSCREEN_ON
|
||||||
|
BACKLIGHT_LEVEL = ui.style.BACKLIGHT_LOW
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
label: str | None,
|
||||||
|
bootscreen: bool = False,
|
||||||
|
coinjoin_authorized: bool = False,
|
||||||
|
) -> None:
|
||||||
|
self.bootscreen = bootscreen
|
||||||
|
if bootscreen:
|
||||||
|
self.BACKLIGHT_LEVEL = ui.style.BACKLIGHT_NORMAL
|
||||||
|
|
||||||
|
skip = (
|
||||||
|
not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
||||||
|
)
|
||||||
|
super().__init__(
|
||||||
|
layout=trezorui2.show_lockscreen(
|
||||||
|
label=label,
|
||||||
|
bootscreen=bootscreen,
|
||||||
|
skip_first_paint=skip,
|
||||||
|
coinjoin_authorized=coinjoin_authorized,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def get_result(self) -> Any:
|
||||||
|
result = await super().get_result()
|
||||||
|
if self.bootscreen:
|
||||||
|
self.request_complete_repaint()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class Busyscreen(HomescreenBase):
|
||||||
|
RENDER_INDICATOR = storage_cache.BUSYSCREEN_ON
|
||||||
|
|
||||||
|
def __init__(self, delay_ms: int) -> None:
|
||||||
|
skip = storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
||||||
|
super().__init__(
|
||||||
|
layout=trezorui2.show_progress_coinjoin(
|
||||||
|
title=TR.coinjoin__waiting_for_others,
|
||||||
|
indeterminate=True,
|
||||||
|
time_ms=delay_ms,
|
||||||
|
skip_first_paint=skip,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def get_result(self) -> Any:
|
||||||
|
from apps.base import set_homescreen
|
||||||
|
|
||||||
|
# Handle timeout.
|
||||||
|
result = await super().get_result()
|
||||||
|
assert result == trezorui2.CANCELLED
|
||||||
|
storage_cache.delete(storage_cache.APP_COMMON_BUSY_DEADLINE_MS)
|
||||||
|
set_homescreen()
|
||||||
|
return result
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,128 +0,0 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import storage.cache as storage_cache
|
|
||||||
import trezorui2
|
|
||||||
from trezor import TR, ui
|
|
||||||
|
|
||||||
from . import RustLayout
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from typing import Any, Tuple
|
|
||||||
|
|
||||||
from trezor import loop
|
|
||||||
|
|
||||||
|
|
||||||
class HomescreenBase(RustLayout):
|
|
||||||
RENDER_INDICATOR: object | None = None
|
|
||||||
|
|
||||||
def __init__(self, layout: Any) -> None:
|
|
||||||
super().__init__(layout=layout)
|
|
||||||
|
|
||||||
def _paint(self) -> None:
|
|
||||||
self.layout.paint()
|
|
||||||
ui.refresh()
|
|
||||||
|
|
||||||
def _first_paint(self) -> None:
|
|
||||||
if storage_cache.homescreen_shown is not self.RENDER_INDICATOR:
|
|
||||||
super()._first_paint()
|
|
||||||
storage_cache.homescreen_shown = self.RENDER_INDICATOR
|
|
||||||
else:
|
|
||||||
self._paint()
|
|
||||||
|
|
||||||
|
|
||||||
class Homescreen(HomescreenBase):
|
|
||||||
RENDER_INDICATOR = storage_cache.HOMESCREEN_ON
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
label: str | None,
|
|
||||||
notification: str | None,
|
|
||||||
notification_is_error: bool,
|
|
||||||
hold_to_lock: bool,
|
|
||||||
) -> None:
|
|
||||||
level = 1
|
|
||||||
if notification is not None:
|
|
||||||
if notification == TR.homescreen__title_experimental_mode:
|
|
||||||
level = 2
|
|
||||||
elif notification_is_error:
|
|
||||||
level = 0
|
|
||||||
|
|
||||||
skip = storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
|
||||||
super().__init__(
|
|
||||||
layout=trezorui2.show_homescreen(
|
|
||||||
label=label,
|
|
||||||
notification=notification,
|
|
||||||
notification_level=level,
|
|
||||||
hold=hold_to_lock,
|
|
||||||
skip_first_paint=skip,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def usb_checker_task(self) -> None:
|
|
||||||
from trezor import io, loop
|
|
||||||
|
|
||||||
usbcheck = loop.wait(io.USB_CHECK)
|
|
||||||
while True:
|
|
||||||
is_connected = await usbcheck
|
|
||||||
self.layout.usb_event(is_connected)
|
|
||||||
self.layout.paint()
|
|
||||||
ui.refresh()
|
|
||||||
|
|
||||||
def create_tasks(self) -> Tuple[loop.AwaitableTask, ...]:
|
|
||||||
return super().create_tasks() + (self.usb_checker_task(),)
|
|
||||||
|
|
||||||
|
|
||||||
class Lockscreen(HomescreenBase):
|
|
||||||
RENDER_INDICATOR = storage_cache.LOCKSCREEN_ON
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
label: str | None,
|
|
||||||
bootscreen: bool = False,
|
|
||||||
coinjoin_authorized: bool = False,
|
|
||||||
) -> None:
|
|
||||||
self.bootscreen = bootscreen
|
|
||||||
skip = (
|
|
||||||
not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
|
||||||
)
|
|
||||||
super().__init__(
|
|
||||||
layout=trezorui2.show_lockscreen(
|
|
||||||
label=label,
|
|
||||||
bootscreen=bootscreen,
|
|
||||||
skip_first_paint=skip,
|
|
||||||
coinjoin_authorized=coinjoin_authorized,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def __iter__(self) -> Any:
|
|
||||||
result = await super().__iter__()
|
|
||||||
if self.bootscreen:
|
|
||||||
self.request_complete_repaint()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class Busyscreen(HomescreenBase):
|
|
||||||
RENDER_INDICATOR = storage_cache.BUSYSCREEN_ON
|
|
||||||
|
|
||||||
def __init__(self, delay_ms: int) -> None:
|
|
||||||
from trezor import TR
|
|
||||||
|
|
||||||
skip = storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
|
||||||
super().__init__(
|
|
||||||
layout=trezorui2.show_progress_coinjoin(
|
|
||||||
title=TR.coinjoin__waiting_for_others,
|
|
||||||
indeterminate=True,
|
|
||||||
time_ms=delay_ms,
|
|
||||||
skip_first_paint=skip,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
async def __iter__(self) -> Any:
|
|
||||||
from apps.base import set_homescreen
|
|
||||||
|
|
||||||
# Handle timeout.
|
|
||||||
result = await super().__iter__()
|
|
||||||
assert result == trezorui2.CANCELLED
|
|
||||||
storage_cache.delete(storage_cache.APP_COMMON_BUSY_DEADLINE_MS)
|
|
||||||
set_homescreen()
|
|
||||||
return result
|
|
File diff suppressed because it is too large
Load Diff
@ -1,149 +0,0 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import storage.cache as storage_cache
|
|
||||||
from trezor import ui, utils
|
|
||||||
|
|
||||||
import trezorui2
|
|
||||||
from trezor import TR, ui
|
|
||||||
|
|
||||||
from . import RustLayout
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from typing import Any, Tuple
|
|
||||||
|
|
||||||
from trezor import loop
|
|
||||||
|
|
||||||
|
|
||||||
class HomescreenBase(RustLayout):
|
|
||||||
RENDER_INDICATOR: object | None = None
|
|
||||||
|
|
||||||
def __init__(self, layout: Any) -> None:
|
|
||||||
super().__init__(layout=layout)
|
|
||||||
|
|
||||||
def _paint(self) -> None:
|
|
||||||
self.layout.paint()
|
|
||||||
ui.refresh()
|
|
||||||
|
|
||||||
def _first_paint(self) -> None:
|
|
||||||
if storage_cache.homescreen_shown is not self.RENDER_INDICATOR:
|
|
||||||
super()._first_paint()
|
|
||||||
storage_cache.homescreen_shown = self.RENDER_INDICATOR
|
|
||||||
else:
|
|
||||||
self._paint()
|
|
||||||
|
|
||||||
if __debug__:
|
|
||||||
# In __debug__ mode, ignore {confirm,swipe,input}_signal.
|
|
||||||
def create_tasks(self) -> tuple[loop.AwaitableTask, ...]:
|
|
||||||
tasks = (
|
|
||||||
self.handle_timers(),
|
|
||||||
self.handle_click_signal(), # so we can receive debug events
|
|
||||||
)
|
|
||||||
if utils.USE_TOUCH:
|
|
||||||
tasks = tasks + (self.handle_touch(),)
|
|
||||||
if utils.USE_BUTTON:
|
|
||||||
tasks = tasks + (self.handle_button(),)
|
|
||||||
return tasks
|
|
||||||
|
|
||||||
|
|
||||||
class Homescreen(HomescreenBase):
|
|
||||||
RENDER_INDICATOR = storage_cache.HOMESCREEN_ON
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
label: str | None,
|
|
||||||
notification: str | None,
|
|
||||||
notification_is_error: bool,
|
|
||||||
hold_to_lock: bool,
|
|
||||||
) -> None:
|
|
||||||
level = 1
|
|
||||||
if notification is not None:
|
|
||||||
if notification == TR.homescreen__title_coinjoin_authorized:
|
|
||||||
level = 3
|
|
||||||
elif notification == TR.homescreen__title_experimental_mode:
|
|
||||||
level = 2
|
|
||||||
elif notification_is_error:
|
|
||||||
level = 0
|
|
||||||
|
|
||||||
skip = storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
|
||||||
super().__init__(
|
|
||||||
layout=trezorui2.show_homescreen(
|
|
||||||
label=label,
|
|
||||||
notification=notification,
|
|
||||||
notification_level=level,
|
|
||||||
hold=hold_to_lock,
|
|
||||||
skip_first_paint=skip,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def usb_checker_task(self) -> None:
|
|
||||||
from trezor import io, loop
|
|
||||||
|
|
||||||
usbcheck = loop.wait(io.USB_CHECK)
|
|
||||||
while True:
|
|
||||||
is_connected = await usbcheck
|
|
||||||
self.layout.usb_event(is_connected)
|
|
||||||
self.layout.paint()
|
|
||||||
ui.refresh()
|
|
||||||
|
|
||||||
def create_tasks(self) -> Tuple[loop.AwaitableTask, ...]:
|
|
||||||
return super().create_tasks() + (self.usb_checker_task(),)
|
|
||||||
|
|
||||||
|
|
||||||
class Lockscreen(HomescreenBase):
|
|
||||||
RENDER_INDICATOR = storage_cache.LOCKSCREEN_ON
|
|
||||||
BACKLIGHT_LEVEL = ui.style.BACKLIGHT_LOW
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
label: str | None,
|
|
||||||
bootscreen: bool = False,
|
|
||||||
coinjoin_authorized: bool = False,
|
|
||||||
) -> None:
|
|
||||||
self.bootscreen = bootscreen
|
|
||||||
if bootscreen:
|
|
||||||
self.BACKLIGHT_LEVEL = ui.style.BACKLIGHT_NORMAL
|
|
||||||
|
|
||||||
skip = (
|
|
||||||
not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
|
||||||
)
|
|
||||||
super().__init__(
|
|
||||||
layout=trezorui2.show_lockscreen(
|
|
||||||
label=label,
|
|
||||||
bootscreen=bootscreen,
|
|
||||||
skip_first_paint=skip,
|
|
||||||
coinjoin_authorized=coinjoin_authorized,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
async def __iter__(self) -> Any:
|
|
||||||
result = await super().__iter__()
|
|
||||||
if self.bootscreen:
|
|
||||||
self.request_complete_repaint()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class Busyscreen(HomescreenBase):
|
|
||||||
RENDER_INDICATOR = storage_cache.BUSYSCREEN_ON
|
|
||||||
|
|
||||||
def __init__(self, delay_ms: int) -> None:
|
|
||||||
from trezor import TR
|
|
||||||
|
|
||||||
skip = storage_cache.homescreen_shown is self.RENDER_INDICATOR
|
|
||||||
super().__init__(
|
|
||||||
layout=trezorui2.show_progress_coinjoin(
|
|
||||||
title=TR.coinjoin__waiting_for_others,
|
|
||||||
indeterminate=True,
|
|
||||||
time_ms=delay_ms,
|
|
||||||
skip_first_paint=skip,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
async def __iter__(self) -> Any:
|
|
||||||
from apps.base import set_homescreen
|
|
||||||
|
|
||||||
# Handle timeout.
|
|
||||||
result = await super().__iter__()
|
|
||||||
assert result == trezorui2.CANCELLED
|
|
||||||
storage_cache.delete(storage_cache.APP_COMMON_BUSY_DEADLINE_MS)
|
|
||||||
set_homescreen()
|
|
||||||
return result
|
|
Loading…
Reference in new issue