From a3aae9c23425b11a3f1d2850bf4bac59a7b32e7e Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Mon, 22 Apr 2019 00:44:55 +0200 Subject: [PATCH] xmr.ui: improves UX of the monero app Based on the testing feedback I've made slight modifications to the UI. Main points: - running on the full brightness during the process (previously dimmed, felt broken) - overlaying layout fix after transaction confirmation --- core/src/apps/monero/layout/confirms.py | 53 +++++++++++-------- core/src/apps/monero/signing/state.py | 3 ++ .../signing/step_01_init_transaction.py | 9 ++-- .../apps/monero/signing/step_02_set_input.py | 4 +- .../signing/step_03_inputs_permutation.py | 2 +- .../apps/monero/signing/step_04_input_vini.py | 2 +- .../monero/signing/step_05_all_inputs_set.py | 2 +- .../apps/monero/signing/step_06_set_output.py | 5 +- .../monero/signing/step_07_all_outputs_set.py | 2 +- .../apps/monero/signing/step_09_sign_input.py | 2 +- 10 files changed, 48 insertions(+), 36 deletions(-) diff --git a/core/src/apps/monero/layout/confirms.py b/core/src/apps/monero/layout/confirms.py index b2abb37b9..ac47f04f5 100644 --- a/core/src/apps/monero/layout/confirms.py +++ b/core/src/apps/monero/layout/confirms.py @@ -42,7 +42,7 @@ async def require_confirm_tx_key(ctx, export_key=False): return await require_confirm(ctx, content, ButtonRequestType.SignTx) -async def require_confirm_transaction(ctx, tsx_data, network_type): +async def require_confirm_transaction(ctx, state, tsx_data, network_type): """ Ask for confirmation from user. """ @@ -70,10 +70,7 @@ async def require_confirm_transaction(ctx, tsx_data, network_type): await _require_confirm_payment_id(ctx, tsx_data.payment_id) await _require_confirm_fee(ctx, tsx_data.fee) - - text = Text("Signing transaction", ui.ICON_SEND, icon_color=ui.BLUE) - text.normal("Signing...") - text.render() + await transaction_step(state, 0) async def _require_confirm_output(ctx, dst, network_type, payment_id): @@ -119,46 +116,60 @@ async def _require_confirm_fee(ctx, fee): await require_hold_to_confirm(ctx, content, ButtonRequestType.ConfirmOutput) -@ui.layout -async def transaction_step(ctx, step, sub_step=None, sub_step_total=None): +@ui.layout_no_slide +async def transaction_step(state, step, sub_step=None): info = [] - if step == 100: - info = ["Processing inputs", "%d/%d" % (sub_step + 1, sub_step_total)] + if step == 0: + info = ["Signing..."] + elif step == 100: + info = ["Processing inputs", "%d/%d" % (sub_step + 1, state.input_count)] elif step == 200: - info = ["Sorting"] + info = ["Sorting..."] elif step == 300: - info = [ - "Processing inputs", - "phase 2", - "%d/%d" % (sub_step + 1, sub_step_total), - ] + info = ["Hashing inputs", "%d/%d" % (sub_step + 1, state.input_count)] + elif step == 350: + info = ["Processing..."] elif step == 400: - info = ["Processing outputs", "%d/%d" % (sub_step + 1, sub_step_total)] + info = ["Processing outputs", "%d/%d" % (sub_step + 1, state.output_count)] elif step == 500: info = ["Postprocessing..."] elif step == 600: - info = ["Signing inputs", "%d/%d" % (sub_step + 1, sub_step_total)] + info = ["Signing inputs", "%d/%d" % (sub_step + 1, state.input_count)] else: info = ["Processing..."] + state.progress_cur += 1 + + ui.display.clear() text = Text("Signing transaction", ui.ICON_SEND, icon_color=ui.BLUE) - text.normal(*info) text.render() + p = int(1000.0 * state.progress_cur / state.progress_total) + ui.display.loader(p, -4, ui.WHITE, ui.BG) + ui.display.text_center(ui.WIDTH // 2, 210, info[0], ui.NORMAL, ui.FG, ui.BG) + if len(info) > 1: + ui.display.text_center(ui.WIDTH // 2, 235, info[1], ui.NORMAL, ui.FG, ui.BG) + ui.display.refresh() + -@ui.layout +@ui.layout_no_slide async def keyimage_sync_step(ctx, current, total_num): if current is None: return + ui.display.clear() text = Text("Syncing", ui.ICON_SEND, icon_color=ui.BLUE) - text.normal("%d/%d" % (current + 1, total_num)) text.render() + p = (int(1000.0 * (current + 1) / total_num)) if total_num > 0 else 0 + ui.display.loader(p, 18, ui.WHITE, ui.BG) + ui.display.refresh() + -@ui.layout +@ui.layout_no_slide async def live_refresh_step(ctx, current): if current is None: return + ui.display.clear() text = Text("Refreshing", ui.ICON_SEND, icon_color=ui.BLUE) text.normal("%d" % current) text.render() diff --git a/core/src/apps/monero/signing/state.py b/core/src/apps/monero/signing/state.py index d608d226a..22c240d87 100644 --- a/core/src/apps/monero/signing/state.py +++ b/core/src/apps/monero/signing/state.py @@ -68,6 +68,9 @@ class State: self.input_count = 0 self.output_count = 0 + self.progress_total = 0 + self.progress_cur = 0 + self.output_change = None self.fee = 0 diff --git a/core/src/apps/monero/signing/step_01_init_transaction.py b/core/src/apps/monero/signing/step_01_init_transaction.py index 9778e53c2..989d16f18 100644 --- a/core/src/apps/monero/signing/step_01_init_transaction.py +++ b/core/src/apps/monero/signing/step_01_init_transaction.py @@ -36,16 +36,19 @@ async def init_transaction( state.mem_trace(1) + state.input_count = tsx_data.num_inputs + state.output_count = len(tsx_data.outputs) + state.progress_total = 4 + 3 * state.input_count + state.output_count + state.progress_cur = 0 + # Ask for confirmation await confirms.require_confirm_transaction( - state.ctx, tsx_data, state.creds.network_type + state.ctx, state, tsx_data, state.creds.network_type ) gc.collect() state.mem_trace(3) # Basic transaction parameters - state.input_count = tsx_data.num_inputs - state.output_count = len(tsx_data.outputs) state.output_change = tsx_data.change_dts state.mixin = tsx_data.mixin state.fee = tsx_data.fee diff --git a/core/src/apps/monero/signing/step_02_set_input.py b/core/src/apps/monero/signing/step_02_set_input.py index af6282326..ce408e83c 100644 --- a/core/src/apps/monero/signing/step_02_set_input.py +++ b/core/src/apps/monero/signing/step_02_set_input.py @@ -32,9 +32,7 @@ async def set_input(state: State, src_entr: MoneroTransactionSourceEntry): state.current_input_index += 1 - await confirms.transaction_step( - state.ctx, state.STEP_INP, state.current_input_index, state.input_count - ) + await confirms.transaction_step(state, state.STEP_INP, state.current_input_index) if state.current_input_index >= state.input_count: raise ValueError("Too many inputs") diff --git a/core/src/apps/monero/signing/step_03_inputs_permutation.py b/core/src/apps/monero/signing/step_03_inputs_permutation.py index cbd19c36b..14f538fb7 100644 --- a/core/src/apps/monero/signing/step_03_inputs_permutation.py +++ b/core/src/apps/monero/signing/step_03_inputs_permutation.py @@ -21,7 +21,7 @@ async def tsx_inputs_permutation(state: State, permutation: list): MoneroTransactionInputsPermutationAck, ) - await transaction_step(state.ctx, state.STEP_PERM) + await transaction_step(state, state.STEP_PERM) """ Set permutation on the inputs - sorted by key image on host. diff --git a/core/src/apps/monero/signing/step_04_input_vini.py b/core/src/apps/monero/signing/step_04_input_vini.py index 874bc09e7..2c88f7965 100644 --- a/core/src/apps/monero/signing/step_04_input_vini.py +++ b/core/src/apps/monero/signing/step_04_input_vini.py @@ -33,7 +33,7 @@ async def input_vini( ) await confirms.transaction_step( - state.ctx, state.STEP_VINI, state.current_input_index + 1, state.input_count + state, state.STEP_VINI, state.current_input_index + 1 ) if state.current_input_index >= state.input_count: raise ValueError("Too many inputs") diff --git a/core/src/apps/monero/signing/step_05_all_inputs_set.py b/core/src/apps/monero/signing/step_05_all_inputs_set.py index 86b55271c..dac0d28ad 100644 --- a/core/src/apps/monero/signing/step_05_all_inputs_set.py +++ b/core/src/apps/monero/signing/step_05_all_inputs_set.py @@ -12,7 +12,7 @@ from apps.monero.xmr import crypto async def all_inputs_set(state: State): state.mem_trace(0) - await confirms.transaction_step(state.ctx, state.STEP_ALL_IN) + await confirms.transaction_step(state, state.STEP_ALL_IN) from trezor.messages.MoneroTransactionAllInputsSetAck import ( MoneroTransactionAllInputsSetAck, diff --git a/core/src/apps/monero/signing/step_06_set_output.py b/core/src/apps/monero/signing/step_06_set_output.py index d0ecc55cf..6f0e30f16 100644 --- a/core/src/apps/monero/signing/step_06_set_output.py +++ b/core/src/apps/monero/signing/step_06_set_output.py @@ -23,10 +23,7 @@ async def set_output( # Progress update only for master message (skip for offloaded BP msg) if not is_offloaded_bp: await confirms.transaction_step( - state.ctx, - state.STEP_OUT, - state.current_output_index + 1, - state.output_count, + state, state.STEP_OUT, state.current_output_index + 1 ) state.mem_trace(1, True) diff --git a/core/src/apps/monero/signing/step_07_all_outputs_set.py b/core/src/apps/monero/signing/step_07_all_outputs_set.py index e5708a7d9..e836aaae0 100644 --- a/core/src/apps/monero/signing/step_07_all_outputs_set.py +++ b/core/src/apps/monero/signing/step_07_all_outputs_set.py @@ -18,7 +18,7 @@ from apps.monero.xmr import crypto async def all_outputs_set(state: State): state.mem_trace(0) - await confirms.transaction_step(state.ctx, state.STEP_ALL_OUT) + await confirms.transaction_step(state, state.STEP_ALL_OUT) state.mem_trace(1) _validate(state) diff --git a/core/src/apps/monero/signing/step_09_sign_input.py b/core/src/apps/monero/signing/step_09_sign_input.py index 0a7639e4e..8b71e146c 100644 --- a/core/src/apps/monero/signing/step_09_sign_input.py +++ b/core/src/apps/monero/signing/step_09_sign_input.py @@ -48,7 +48,7 @@ async def sign_input( :return: Generated signature MGs[i] """ await confirms.transaction_step( - state.ctx, state.STEP_SIGN, state.current_input_index + 1, state.input_count + state, state.STEP_SIGN, state.current_input_index + 1 ) state.current_input_index += 1