1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-15 20:19:23 +00:00

ui/passphrase: confirm button, visuals

This commit is contained in:
Jan Pochyla 2018-02-06 03:01:04 +01:00
parent 1c9380a9d9
commit deb64c3c43
2 changed files with 55 additions and 48 deletions

View File

@ -3,18 +3,13 @@ from trezor import res, ui, wire
async def request_passphrase_on_display(ctx): async def request_passphrase_on_display(ctx):
from trezor.messages.FailureType import ActionCancelled from trezor.messages.FailureType import ActionCancelled
from trezor.ui.confirm import ConfirmDialog, CONFIRMED from trezor.ui.passphrase import PassphraseKeyboard, CANCELLED
from trezor.ui.passphrase import PassphraseKeyboard
ui.display.clear() ui.display.clear()
keyboard = PassphraseKeyboard('Enter passphrase') passphrase = await PassphraseKeyboard('Enter passphrase')
if passphrase == CANCELLED:
while True:
result = await keyboard
if result:
print(result)
else:
raise wire.FailureError(ActionCancelled, 'Passphrase cancelled') raise wire.FailureError(ActionCancelled, 'Passphrase cancelled')
return passphrase
async def request_passphrase_on_host(ctx): async def request_passphrase_on_host(ctx):

View File

@ -7,8 +7,8 @@ from trezor.ui.swipe import SWIPE_HORIZONTAL, SWIPE_LEFT, SWIPE_RIGHT, Swipe
KEYBOARD_KEYS = ( KEYBOARD_KEYS = (
('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'), ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'),
('_', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz', '*#'), (' ', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz', '*#'),
('_', 'ABC', 'DEF', 'GHI', 'JKL', 'MNO', 'PQRS', 'TUV', 'WXYZ', '*#'), (' ', 'ABC', 'DEF', 'GHI', 'JKL', 'MNO', 'PQRS', 'TUV', 'WXYZ', '*#'),
('_', '.', '/', '!', '+', '-', '?', ',', ';', '$')) ('_', '.', '/', '!', '+', '-', '?', ',', ';', '$'))
@ -19,7 +19,7 @@ def digit_area(i):
def key_buttons(keys): def key_buttons(keys):
return [Button(digit_area(i), str(k)) for i, k in enumerate(keys)] return [Button(digit_area(i), k) for i, k in enumerate(keys)]
def render_scrollbar(page): def render_scrollbar(page):
@ -66,12 +66,16 @@ class Input(Button):
# input content # input content
display.text(tx, ty, t, text_style, fg_color, bg_color) display.text(tx, ty, t, text_style, fg_color, bg_color)
width = display.text_width(t, text_style)
if p: # pending marker if p: # pending marker
width = display.text_width(t, text_style)
pw = display.text_width(t[-1:], text_style) pw = display.text_width(t[-1:], text_style)
px = tx + width - pw display.bar(tx + width - pw, ty + 2, pw + 1, 3, fg_color)
display.bar(px, ty + 2, pw + 1, 3, fg_color) else: # cursor
display.bar(tx + width + 1, ty - 18, 2, 22, fg_color)
CANCELLED = const(0)
class PassphraseKeyboard(ui.Widget): class PassphraseKeyboard(ui.Widget):
@ -79,38 +83,39 @@ class PassphraseKeyboard(ui.Widget):
self.prompt = prompt self.prompt = prompt
self.page = page self.page = page
self.input = Input(ui.grid(0, n_x=1, n_y=6), '') self.input = Input(ui.grid(0, n_x=1, n_y=6), '')
self.back = Button(ui.grid(12), self.back = Button(ui.grid(12), res.load(ui.ICON_BACK), style=ui.BTN_CLEAR)
res.load(ui.ICON_BACK), self.done = Button(ui.grid(14), res.load(ui.ICON_CONFIRM), style=ui.BTN_CONFIRM)
style=ui.BTN_CLEAR)
self.keys = key_buttons(KEYBOARD_KEYS[self.page]) self.keys = key_buttons(KEYBOARD_KEYS[self.page])
self.pbutton = None # pending key button self.pbutton = None # pending key button
self.pindex = 0 # index of current pending char in pbutton self.pindex = 0 # index of current pending char in pbutton
self.onchange = None
def render(self): def render(self):
# passphrase or prompt
if self.input.content: if self.input.content:
# content and backspace
self.input.render() self.input.render()
self.back.render()
else: else:
# prompt
display.bar(0, 0, 240, 48, ui.BG) display.bar(0, 0, 240, 48, ui.BG)
display.text_center(ui.SCREEN // 2, 32, self.prompt, ui.BOLD, ui.GREY, ui.BG) display.text_center(ui.SCREEN // 2, 32, self.prompt, ui.BOLD, ui.GREY, ui.BG)
render_scrollbar(self.page)
# key buttons # buttons
self.back.render()
self.done.render()
for btn in self.keys: for btn in self.keys:
btn.render() btn.render()
render_scrollbar(self.page)
def touch(self, event, pos): def touch(self, event, pos):
content = self.input.content content = self.input.content
if self.back.touch(event, pos) == BTN_CLICKED: if self.back.touch(event, pos) == BTN_CLICKED:
if content:
# backspace, delete the last character of input # backspace, delete the last character of input
self.edit(content[:-1]) self.edit(content[:-1])
return return
else:
# cancel
return CANCELLED
if self.done.touch(event, pos) == BTN_CLICKED:
# confirm button, return the content
return content
for btn in self.keys: for btn in self.keys:
if btn.touch(event, pos) == BTN_CLICKED: if btn.touch(event, pos) == BTN_CLICKED:
# key press, add new char to input or cycle the pending button # key press, add new char to input or cycle the pending button
@ -124,37 +129,35 @@ class PassphraseKeyboard(ui.Widget):
return return
def edit(self, content, button=None, index=0): def edit(self, content, button=None, index=0):
if button and len(button.content) == 1:
# one-letter buttons are never pending
button = None
index = 0
self.pbutton = button self.pbutton = button
self.pindex = index self.pindex = index
self.input.edit(content, button is not None) self.input.edit(content, button is not None)
if self.onchange: if content:
self.onchange() self.back.enable()
else:
self.back.disable()
async def __iter__(self): async def __iter__(self):
self.edit(self.input.content) # init button state
while True: while True:
swipe = Swipe(directions=SWIPE_HORIZONTAL) change = self.change_page()
wait = loop.wait(swipe, self.show_page()) enter = self.enter_text()
wait = loop.wait(change, enter)
result = await wait result = await wait
if swipe in wait.finished: if enter in wait.finished:
if result == SWIPE_LEFT:
self.page = (self.page + 1) % len(KEYBOARD_KEYS)
else:
self.page = (self.page - 1) % len(KEYBOARD_KEYS)
self.keys = key_buttons(KEYBOARD_KEYS[self.page])
else:
return result return result
@ui.layout @ui.layout
async def show_page(self): async def enter_text(self):
timeout = loop.sleep(1000 * 1000 * 1) timeout = loop.sleep(1000 * 1000 * 1)
touch = loop.select(io.TOUCH) touch = loop.select(io.TOUCH)
wait_timeout = loop.wait(touch, timeout) wait_timeout = loop.wait(touch, timeout)
wait_touch = loop.wait(touch) wait_touch = loop.wait(touch)
content = None content = None
self.back.taint()
self.input.taint()
while content is None: while content is None:
self.render() self.render()
if self.pbutton is not None: if self.pbutton is not None:
@ -166,5 +169,14 @@ class PassphraseKeyboard(ui.Widget):
event, *pos = result event, *pos = result
content = self.touch(event, pos) content = self.touch(event, pos)
else: else:
# disable the pending buttons
self.edit(self.input.content) self.edit(self.input.content)
return content return content
async def change_page(self):
swipe = await Swipe(directions=SWIPE_HORIZONTAL)
if swipe == SWIPE_LEFT:
self.page = (self.page + 1) % len(KEYBOARD_KEYS)
else:
self.page = (self.page - 1) % len(KEYBOARD_KEYS)
self.keys = key_buttons(KEYBOARD_KEYS[self.page])