core/ui: Implement multi-page confirmation screen.

pull/394/head
Andrew Kozlik 5 years ago
parent 1f58ee7ae9
commit 509a815f73

@ -6,7 +6,7 @@ from trezorui import Display
from trezor import io, loop, res, utils
if False:
from typing import Any, Generator, Iterable, Tuple, TypeVar
from typing import Any, Generator, Tuple, TypeVar
Pos = Tuple[int, int]
Area = Tuple[int, int, int, int]
@ -276,7 +276,7 @@ class Layout(Component):
def __await__(self) -> Generator[Any, Any, ResultValue]:
return self.__iter__() # type: ignore
def create_tasks(self) -> Iterable[loop.Task]:
def create_tasks(self) -> Tuple[loop.Task, ...]:
"""
Called from `__iter__`. Creates and returns a sequence of tasks that
run this layout. Tasks are executed in parallel. When one of them

@ -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

@ -7,7 +7,7 @@ from trezor.ui.button import Button, ButtonClear, ButtonConfirm
from trezor.ui.swipe import SWIPE_HORIZONTAL, SWIPE_LEFT, Swipe
if False:
from typing import List, Iterable, Optional
from typing import Iterable, List, Optional, Tuple
from trezor.ui.button import ButtonContent, ButtonStyleStateType
SPACE = res.load(ui.ICON_SPACE)
@ -244,7 +244,7 @@ class PassphraseKeyboard(ui.Layout):
def on_confirm(self) -> None:
raise ui.Result(self.input.text)
def create_tasks(self) -> Iterable[loop.Task]:
def create_tasks(self) -> Tuple[loop.Task, ...]:
return self.handle_input(), self.handle_rendering(), self.handle_paging()

@ -1,7 +1,7 @@
from trezor import loop, ui
if False:
from typing import Iterable
from typing import Tuple
class Popup(ui.Layout):
@ -12,7 +12,7 @@ class Popup(ui.Layout):
def dispatch(self, event: int, x: int, y: int) -> None:
self.content.dispatch(event, x, y)
def create_tasks(self) -> Iterable[loop.Task]:
def create_tasks(self) -> Tuple[loop.Task, ...]:
return self.handle_input(), self.handle_rendering(), self.handle_timeout()
def handle_timeout(self) -> loop.Task: # type: ignore

@ -9,7 +9,7 @@ if __debug__:
from apps.debug import swipe_signal
if False:
from typing import Iterable, Sequence
from typing import Tuple, Sequence
def render_scrollbar(pages: int, page: int) -> None:
@ -91,7 +91,7 @@ class Paginated(ui.Layout):
self.on_change()
def create_tasks(self) -> Iterable[loop.Task]:
def create_tasks(self) -> Tuple[loop.Task, ...]:
return self.handle_input(), self.handle_rendering(), self.handle_paging()
def on_change(self) -> None:

@ -64,5 +64,7 @@ ICON_LOCK = "trezor/res/lock.toif"
ICON_CLICK = "trezor/res/click.toif"
ICON_BACK = "trezor/res/left.toif"
ICON_SWIPE = "trezor/res/swipe.toif"
ICON_SWIPE_LEFT = "trezor/res/swipe_left.toif"
ICON_SWIPE_RIGHT = "trezor/res/swipe_right.toif"
ICON_CHECK = "trezor/res/check.toif"
ICON_SPACE = "trezor/res/space.toif"

Loading…
Cancel
Save