1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-25 14:50:57 +00:00

core/ui: Implement multi-page confirmation screen.

This commit is contained in:
Andrew Kozlik 2019-08-08 15:59:05 +02:00
parent 1f58ee7ae9
commit 509a815f73
8 changed files with 91 additions and 10 deletions

Binary file not shown.

Binary file not shown.

View File

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

View File

@ -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.button import Button, ButtonCancel, ButtonConfirm
from trezor.ui.loader import Loader, LoaderDefault from trezor.ui.loader import Loader, LoaderDefault
if False: if False:
from typing import Optional from typing import Any, Optional, Tuple
from trezor.ui.button import ButtonContent, ButtonStyleType from trezor.ui.button import ButtonContent, ButtonStyleType
from trezor.ui.loader import LoaderStyleType from trezor.ui.loader import LoaderStyleType
@ -55,6 +57,7 @@ class Confirm(ui.Layout):
self.cancel = None self.cancel = None
def dispatch(self, event: int, x: int, y: int) -> None: def dispatch(self, event: int, x: int, y: int) -> None:
super().dispatch(event, x, y)
self.content.dispatch(event, x, y) self.content.dispatch(event, x, y)
if self.confirm is not None: if self.confirm is not None:
self.confirm.dispatch(event, x, y) self.confirm.dispatch(event, x, y)
@ -68,6 +71,82 @@ class Confirm(ui.Layout):
raise ui.Result(CANCELLED) 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): class HoldToConfirm(ui.Layout):
DEFAULT_CONFIRM = "Hold To Confirm" DEFAULT_CONFIRM = "Hold To Confirm"
DEFAULT_CONFIRM_STYLE = ButtonConfirm DEFAULT_CONFIRM_STYLE = ButtonConfirm

View File

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

View File

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

View File

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

View File

@ -64,5 +64,7 @@ ICON_LOCK = "trezor/res/lock.toif"
ICON_CLICK = "trezor/res/click.toif" ICON_CLICK = "trezor/res/click.toif"
ICON_BACK = "trezor/res/left.toif" ICON_BACK = "trezor/res/left.toif"
ICON_SWIPE = "trezor/res/swipe.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_CHECK = "trezor/res/check.toif"
ICON_SPACE = "trezor/res/space.toif" ICON_SPACE = "trezor/res/space.toif"