core/management: fix various reset/backup/recovery ui bugs

pull/263/head
Jan Pochyla 5 years ago
parent 989fb1491f
commit 4d0fe4d064

@ -140,14 +140,14 @@ async def _confirm_word(ctx, share_index, numbered_share_words):
return selected_word == checked_word return selected_word == checked_word
async def _show_confirmation_success(ctx, share_index): async def _show_confirmation_success(ctx, share_index, num_of_shares=None):
if share_index is None: if share_index is None or num_of_shares is None or share_index == num_of_shares - 1:
text = Text("Recovery seed", ui.ICON_RESET) text = Text("Recovery seed", ui.ICON_RESET)
text.bold("Recovery seed") text.bold("Recovery seed")
text.bold("checked successfully.") text.bold("checked successfully.")
else: else:
text = Text("Recovery share #%s" % (share_index + 1), ui.ICON_RESET) text = Text("Recovery share #%s" % (share_index + 1), ui.ICON_RESET)
text.bold("Seed share #%s" % (share_index + 1)) text.bold("Recovery share #%s" % (share_index + 1))
text.bold("checked successfully.") text.bold("checked successfully.")
text.normal("Let's continue with") text.normal("Let's continue with")
text.normal("share #%s." % (share_index + 2)) text.normal("share #%s." % (share_index + 2))
@ -176,9 +176,6 @@ async def _show_confirmation_failure(ctx, share_index):
async def bip39_show_and_confirm_mnemonic(ctx, mnemonic: str): async def bip39_show_and_confirm_mnemonic(ctx, mnemonic: str):
words = mnemonic.split() words = mnemonic.split()
# require confirmation of the mnemonic safety
await bip39_show_backup_warning(ctx)
while True: while True:
# display paginated mnemonic on the screen # display paginated mnemonic on the screen
await _bip39_show_mnemonic(ctx, words) await _bip39_show_mnemonic(ctx, words)
@ -246,11 +243,15 @@ async def slip39_show_checklist_set_shares(ctx):
checklist = Checklist("Backup checklist", ui.ICON_RESET) checklist = Checklist("Backup checklist", ui.ICON_RESET)
checklist.add("Set number of shares") checklist.add("Set number of shares")
checklist.add("Set the threshold") checklist.add("Set the threshold")
checklist.add(("Write down and check", "all seed shares")) checklist.add(("Write down and check", "all backup shares"))
checklist.select(0) checklist.select(0)
checklist.process() checklist.process()
return await confirm( return await confirm(
ctx, checklist, ButtonRequestType.ResetDevice, cancel=None, confirm="Set shares" ctx,
checklist,
ButtonRequestType.ResetDevice,
cancel=None,
confirm="Set share count",
) )
@ -258,7 +259,7 @@ async def slip39_show_checklist_set_threshold(ctx, num_of_shares):
checklist = Checklist("Backup checklist", ui.ICON_RESET) checklist = Checklist("Backup checklist", ui.ICON_RESET)
checklist.add("Set number of shares") checklist.add("Set number of shares")
checklist.add("Set the threshold") checklist.add("Set the threshold")
checklist.add(("Write down and check", "all seed shares")) checklist.add(("Write down and check", "all backup shares"))
checklist.select(1) checklist.select(1)
checklist.process() checklist.process()
return await confirm( return await confirm(
@ -274,7 +275,7 @@ async def slip39_show_checklist_show_shares(ctx, num_of_shares, threshold):
checklist = Checklist("Backup checklist", ui.ICON_RESET) checklist = Checklist("Backup checklist", ui.ICON_RESET)
checklist.add("Set number of shares") checklist.add("Set number of shares")
checklist.add("Set the threshold") checklist.add("Set the threshold")
checklist.add(("Write down and check", "all seed shares")) checklist.add(("Write down and check", "all backup shares"))
checklist.select(2) checklist.select(2)
checklist.process() checklist.process()
return await confirm( return await confirm(
@ -282,7 +283,7 @@ async def slip39_show_checklist_show_shares(ctx, num_of_shares, threshold):
checklist, checklist,
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
cancel=None, cancel=None,
confirm="Show seed shares", confirm="Show backup shares",
) )
@ -293,15 +294,6 @@ async def slip39_prompt_number_of_shares(ctx):
while True: while True:
shares = ShamirNumInput(ShamirNumInput.SET_SHARES, count, min_count, max_count) shares = ShamirNumInput(ShamirNumInput.SET_SHARES, count, min_count, max_count)
info = InfoConfirm(
"Shares are parts of "
"the recovery seed, "
"each containing 20 "
"words. You can later set "
"how many shares you "
"need to recover your "
"wallet."
)
confirmed = await confirm( confirmed = await confirm(
ctx, ctx,
shares, shares,
@ -315,13 +307,22 @@ async def slip39_prompt_number_of_shares(ctx):
if confirmed: if confirmed:
break break
else: else:
info = InfoConfirm(
"Shares are parts of "
"the recovery seed, "
"each containing 20 "
"words. You can later set "
"how many shares you "
"need to recover your "
"wallet."
)
await info await info
return count return count
async def slip39_prompt_threshold(ctx, num_of_shares): async def slip39_prompt_threshold(ctx, num_of_shares):
count = num_of_shares // 2 count = num_of_shares // 2 + 1
min_count = 2 min_count = 2
max_count = num_of_shares max_count = num_of_shares
@ -329,14 +330,6 @@ async def slip39_prompt_threshold(ctx, num_of_shares):
shares = ShamirNumInput( shares = ShamirNumInput(
ShamirNumInput.SET_THRESHOLD, count, min_count, max_count ShamirNumInput.SET_THRESHOLD, count, min_count, max_count
) )
info = InfoConfirm(
"Threshold sets number "
"shares that you need "
"to recover your wallet. "
"i.e. Set it to %s and "
"you'll need any %s shares "
"of the total number." % (count, count)
)
confirmed = await confirm( confirmed = await confirm(
ctx, ctx,
shares, shares,
@ -350,6 +343,14 @@ async def slip39_prompt_threshold(ctx, num_of_shares):
if confirmed: if confirmed:
break break
else: else:
info = InfoConfirm(
"Threshold sets number "
"shares that you need "
"to recover your wallet. "
"i.e. Set it to %s and "
"you'll need any %s shares "
"of the total number." % (count, count)
)
await info await info
return count return count
@ -364,7 +365,7 @@ async def slip39_show_and_confirm_shares(ctx, shares):
# make the user confirm 2 words from the share # make the user confirm 2 words from the share
if await _confirm_share_words(ctx, index, share_words): if await _confirm_share_words(ctx, index, share_words):
await _show_confirmation_success(ctx, index) await _show_confirmation_success(ctx, index, len(shares))
break # this share is confirmed, go to next one break # this share is confirmed, go to next one
else: else:
await _show_confirmation_failure(ctx, index) await _show_confirmation_failure(ctx, index)
@ -374,17 +375,17 @@ async def _slip39_show_share_words(ctx, share_index, share_words):
first, chunks, last = _slip39_split_share_into_pages(share_words) first, chunks, last = _slip39_split_share_into_pages(share_words)
if share_index is None: if share_index is None:
header_title = "Recovery share #%s" % (share_index + 1)
else:
header_title = "Recovery seed" header_title = "Recovery seed"
else:
header_title = "Recovery share #%s" % (share_index + 1)
header_icon = ui.ICON_RESET header_icon = ui.ICON_RESET
pages = [] # ui page components pages = [] # ui page components
shares_words_check = [] # check we display correct data shares_words_check = [] # check we display correct data
# first page # first page
text = Text(header_title, header_icon) text = Text(header_title, header_icon)
text.normal("Write down %s words" % len(share_words)) text.bold("Write down %s words" % len(share_words))
text.normal("onto paper booklet:") text.bold("onto paper booklet:")
text.br_half() text.br_half()
for index, word in first: for index, word in first:
text.mono("%s. %s" % (index + 1, word)) text.mono("%s. %s" % (index + 1, word))
@ -406,8 +407,8 @@ async def _slip39_show_share_words(ctx, share_index, share_words):
text.mono("%s. %s" % (index + 1, word)) text.mono("%s. %s" % (index + 1, word))
shares_words_check.append(word) shares_words_check.append(word)
text.br_half() text.br_half()
text.normal("I confirm that I wrote") text.bold("I confirm that I wrote")
text.normal("down all %s words." % len(share_words)) text.bold("down all %s words." % len(share_words))
pages.append(text) pages.append(text)
# pagination # pagination
@ -469,7 +470,13 @@ class ShamirNumInput(ui.Control):
# render the counter # render the counter
if self.step is ShamirNumInput.SET_SHARES: if self.step is ShamirNumInput.SET_SHARES:
ui.display.text( ui.display.text(
12, 130, "%s people or locations" % count, ui.BOLD, ui.FG, ui.BG 12,
130,
"%s people or locations" % count,
ui.BOLD,
ui.FG,
ui.BG,
ui.WIDTH - 12,
) )
ui.display.text( ui.display.text(
12, 156, "will each host one share.", ui.NORMAL, ui.FG, ui.BG 12, 156, "will each host one share.", ui.NORMAL, ui.FG, ui.BG
@ -479,7 +486,13 @@ class ShamirNumInput(ui.Control):
12, 130, "For recovery you'll need", ui.NORMAL, ui.FG, ui.BG 12, 130, "For recovery you'll need", ui.NORMAL, ui.FG, ui.BG
) )
ui.display.text( ui.display.text(
12, 156, "any %s of shares." % count, ui.BOLD, ui.FG, ui.BG 12,
156,
"any %s of shares." % count,
ui.BOLD,
ui.FG,
ui.BG,
ui.WIDTH - 12,
) )
self.repaint = False self.repaint = False
@ -490,11 +503,14 @@ class ShamirNumInput(ui.Control):
class MnemonicWordSelect(ui.Layout): class MnemonicWordSelect(ui.Layout):
NUM_OF_CHOICES = 3 NUM_OF_CHOICES = 3
MODE_CHECK = object()
MODE_RECOVERY = object()
def __init__(self, words, share_index, word_index): def __init__(self, words, share_index, word_index, mode):
self.words = words self.words = words
self.share_index = share_index self.share_index = share_index
self.word_index = word_index self.word_index = word_index
self.mode = mode
self.buttons = [] self.buttons = []
for i, word in enumerate(words): for i, word in enumerate(words):
area = ui.grid(i + 2, n_x=1) area = ui.grid(i + 2, n_x=1)
@ -502,9 +518,15 @@ class MnemonicWordSelect(ui.Layout):
btn.on_click = self.select(word) btn.on_click = self.select(word)
self.buttons.append(btn) self.buttons.append(btn)
if share_index is None: if share_index is None:
self.text = Text("Recovery seed") if self.mode is MnemonicWordSelect.MODE_CHECK:
self.text = Text("Check seed")
else: # self.mode is MnemonicWordSelect.MODE_RECOVERY
self.text = Text("Recovery seed")
else: else:
self.text = Text("Recovery share #%s" % (share_index + 1)) if self.mode is MnemonicWordSelect.MODE_CHECK:
self.text = Text("Check share #%s" % (share_index + 1))
else: # self.mode is MnemonicWordSelect.MODE_RECOVERY
self.text = Text("Recovery share #%s" % (share_index + 1))
self.text.normal("Choose the %s word:" % utils.format_ordinal(word_index + 1)) self.text.normal("Choose the %s word:" % utils.format_ordinal(word_index + 1))
def dispatch(self, event, x, y): def dispatch(self, event, x, y):

@ -186,9 +186,13 @@ class Label(ui.Control):
tx = ax + aw // 2 tx = ax + aw // 2
ty = ay + ah // 2 + 8 ty = ay + ah // 2 + 8
if align is LABEL_LEFT: if align is LABEL_LEFT:
ui.display.text_left(tx, ty, self.content, self.style, ui.FG, ui.BG) ui.display.text_left(tx, ty, self.content, self.style, ui.FG, ui.BG, aw)
elif align is LABEL_CENTER: elif align is LABEL_CENTER:
ui.display.text_center(tx, ty, self.content, self.style, ui.FG, ui.BG) ui.display.text_center(
tx, ty, self.content, self.style, ui.FG, ui.BG, aw
)
elif align is LABEL_RIGHT: elif align is LABEL_RIGHT:
ui.display.text_right(tx, ty, self.content, self.style, ui.FG, ui.BG) ui.display.text_right(
tx, ty, self.content, self.style, ui.FG, ui.BG, aw
)
self.repaint = False self.repaint = False

Loading…
Cancel
Save