|
|
|
@ -1,9 +1,11 @@
|
|
|
|
|
from trezor import res, ui
|
|
|
|
|
from micropython import const
|
|
|
|
|
|
|
|
|
|
from trezor import loop, res, ui
|
|
|
|
|
from trezor.ui.button import Button, ButtonCancel, ButtonConfirm
|
|
|
|
|
from trezor.ui.loader import Loader, LoaderDefault
|
|
|
|
|
|
|
|
|
|
if False:
|
|
|
|
|
from typing import Optional
|
|
|
|
|
from typing import Any, Optional, Tuple
|
|
|
|
|
from trezor.ui.button import ButtonContent, ButtonStyleType
|
|
|
|
|
from trezor.ui.loader import LoaderStyleType
|
|
|
|
|
|
|
|
|
@ -55,6 +57,7 @@ class Confirm(ui.Layout):
|
|
|
|
|
self.cancel = None
|
|
|
|
|
|
|
|
|
|
def dispatch(self, event: int, x: int, y: int) -> None:
|
|
|
|
|
super().dispatch(event, x, y)
|
|
|
|
|
self.content.dispatch(event, x, y)
|
|
|
|
|
if self.confirm is not None:
|
|
|
|
|
self.confirm.dispatch(event, x, y)
|
|
|
|
@ -68,6 +71,82 @@ class Confirm(ui.Layout):
|
|
|
|
|
raise ui.Result(CANCELLED)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Pageable:
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
|
self._page = 0
|
|
|
|
|
|
|
|
|
|
def page(self) -> int:
|
|
|
|
|
return self._page
|
|
|
|
|
|
|
|
|
|
def page_count(self) -> int:
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
def is_first(self) -> bool:
|
|
|
|
|
return self._page == 0
|
|
|
|
|
|
|
|
|
|
def is_last(self) -> bool:
|
|
|
|
|
return self._page == self.page_count() - 1
|
|
|
|
|
|
|
|
|
|
def next(self) -> None:
|
|
|
|
|
self._page = min(self._page + 1, self.page_count() - 1)
|
|
|
|
|
|
|
|
|
|
def prev(self) -> None:
|
|
|
|
|
self._page = max(self._page - 1, 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ConfirmPageable(Confirm):
|
|
|
|
|
def __init__(self, pageable: Pageable, *args: Any, **kwargs: Any):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
self.pageable = pageable
|
|
|
|
|
|
|
|
|
|
async def handle_paging(self) -> None:
|
|
|
|
|
from trezor.ui.swipe import SWIPE_HORIZONTAL, SWIPE_LEFT, SWIPE_RIGHT, Swipe
|
|
|
|
|
|
|
|
|
|
if self.pageable.is_first():
|
|
|
|
|
directions = SWIPE_LEFT
|
|
|
|
|
elif self.pageable.is_last():
|
|
|
|
|
directions = SWIPE_RIGHT
|
|
|
|
|
else:
|
|
|
|
|
directions = SWIPE_HORIZONTAL
|
|
|
|
|
|
|
|
|
|
swipe = await Swipe(directions)
|
|
|
|
|
|
|
|
|
|
if swipe == SWIPE_LEFT:
|
|
|
|
|
self.pageable.next()
|
|
|
|
|
else:
|
|
|
|
|
self.pageable.prev()
|
|
|
|
|
|
|
|
|
|
self.content.repaint = True
|
|
|
|
|
if self.confirm is not None:
|
|
|
|
|
self.confirm.repaint = True
|
|
|
|
|
if self.cancel is not None:
|
|
|
|
|
self.cancel.repaint = True
|
|
|
|
|
|
|
|
|
|
def create_tasks(self) -> Tuple[loop.Task, ...]:
|
|
|
|
|
tasks = super().create_tasks()
|
|
|
|
|
if self.pageable.page_count() > 1:
|
|
|
|
|
return tasks + (self.handle_paging(),)
|
|
|
|
|
else:
|
|
|
|
|
return tasks
|
|
|
|
|
|
|
|
|
|
def on_render(self) -> None:
|
|
|
|
|
PULSE_PERIOD = const(1200000)
|
|
|
|
|
|
|
|
|
|
super().on_render()
|
|
|
|
|
|
|
|
|
|
if not self.pageable.is_first():
|
|
|
|
|
t = ui.pulse(PULSE_PERIOD)
|
|
|
|
|
c = ui.blend(ui.GREY, ui.DARK_GREY, t)
|
|
|
|
|
icon = res.load(ui.ICON_SWIPE_RIGHT)
|
|
|
|
|
ui.display.icon(18, 68, icon, c, ui.BG)
|
|
|
|
|
|
|
|
|
|
if not self.pageable.is_last():
|
|
|
|
|
t = ui.pulse(PULSE_PERIOD, PULSE_PERIOD // 2)
|
|
|
|
|
c = ui.blend(ui.GREY, ui.DARK_GREY, t)
|
|
|
|
|
icon = res.load(ui.ICON_SWIPE_LEFT)
|
|
|
|
|
ui.display.icon(205, 68, icon, c, ui.BG)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HoldToConfirm(ui.Layout):
|
|
|
|
|
DEFAULT_CONFIRM = "Hold To Confirm"
|
|
|
|
|
DEFAULT_CONFIRM_STYLE = ButtonConfirm
|
|
|
|
|