mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-11 07:50:57 +00:00
core/ui: Implement multi-page confirmation screen.
This commit is contained in:
parent
1f58ee7ae9
commit
509a815f73
BIN
core/src/trezor/res/swipe_left.toif
Normal file
BIN
core/src/trezor/res/swipe_left.toif
Normal file
Binary file not shown.
BIN
core/src/trezor/res/swipe_right.toif
Normal file
BIN
core/src/trezor/res/swipe_right.toif
Normal file
Binary file not shown.
@ -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…
Reference in New Issue
Block a user