From 4dd5b75cfa3b6d7914f9f178cbaa0a51488ed1e8 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 8 Nov 2021 17:09:26 +0100 Subject: [PATCH] anastasis-webui: ui tweaks --- .../pages/home/AuthenticationEditorScreen.tsx | 296 +++++++++++------- .../pages/home/ContinentSelectionScreen.tsx | 6 +- .../anastasis-webui/src/pages/home/index.tsx | 2 +- 3 files changed, 191 insertions(+), 113 deletions(-) diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx index a71220c55..6e3ca2941 100644 --- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx @@ -1,53 +1,62 @@ -import { AuthMethod } from "anastasis-core"; +import { AuthMethod, ReducerStateBackup } from "anastasis-core"; import { ComponentChildren, Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useAnastasisContext } from "../../context/anastasis"; -import { authMethods, AuthMethodSetupProps, AuthMethodWithRemove, KnownAuthMethods } from "./authMethod"; +import { + authMethods, + AuthMethodSetupProps, + AuthMethodWithRemove, + KnownAuthMethods, +} from "./authMethod"; import { AnastasisClientFrame } from "./index"; - - -const getKeys = Object.keys as (obj: T) => Array +const getKeys = Object.keys as (obj: T) => Array; export function AuthenticationEditorScreen(): VNode { - const [noProvidersAck, setNoProvidersAck] = useState(false) - const [selectedMethod, setSelectedMethod] = useState(undefined); + const [noProvidersAck, setNoProvidersAck] = useState(false); + const [selectedMethod, setSelectedMethod] = useState< + KnownAuthMethods | undefined + >(undefined); + const [tooFewAuths, setTooFewAuths] = useState(false); // const [addingProvider, setAddingProvider] = useState(undefined) - - const reducer = useAnastasisContext() + const reducer = useAnastasisContext(); if (!reducer) { - return
no reducer in context
+ return
no reducer in context
; } - if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) { - return
invalid state
+ if ( + !reducer.currentReducerState || + reducer.currentReducerState.backup_state === undefined + ) { + return
invalid state
; } - const configuredAuthMethods: AuthMethod[] = reducer.currentReducerState.authentication_methods ?? []; + const configuredAuthMethods: AuthMethod[] = + reducer.currentReducerState.authentication_methods ?? []; const haveMethodsConfigured = configuredAuthMethods.length > 0; function removeByIndex(index: number): void { - if (reducer) reducer.transition("delete_authentication", { - authentication_method: index, - }) + if (reducer) + reducer.transition("delete_authentication", { + authentication_method: index, + }); } - const camByType: { [s: string]: AuthMethodWithRemove[] } = {} + const camByType: { [s: string]: AuthMethodWithRemove[] } = {}; for (let index = 0; index < configuredAuthMethods.length; index++) { const cam = { ...configuredAuthMethods[index], - remove: () => removeByIndex(index) - } - const prevValue = camByType[cam.type] || [] - prevValue.push(cam) + remove: () => removeByIndex(index), + }; + const prevValue = camByType[cam.type] || []; + prevValue.push(cam); camByType[cam.type] = prevValue; } - const providers = reducer.currentReducerState.authentication_providers!; const authAvailableSet = new Set(); for (const provKey of Object.keys(providers)) { const p = providers[provKey]; - if ("http_status" in p && (!("error_code" in p)) && p.methods) { + if ("http_status" in p && !("error_code" in p) && p.methods) { for (const meth of p.methods) { authAvailableSet.add(meth.type); } @@ -61,102 +70,147 @@ export function AuthenticationEditorScreen(): VNode { setSelectedMethod(undefined); }; - const AuthSetup = authMethods[selectedMethod].setup ?? AuthMethodNotImplemented; - return ( - + const AuthSetup = + authMethods[selectedMethod].setup ?? AuthMethodNotImplemented; + return ( + + - {!authAvailableSet.has(selectedMethod) && { - null - }} - > - We have found no trusted cloud providers for your recovery secret. You can add a provider manually. - To add a provider you must know the provider URL (e.g. https://provider.com) -

- More about cloud providers -

-
} - -
+ {!authAvailableSet.has(selectedMethod) && ( + { + null; + }} + > +

+ We have found no Anastasis providers that support this + authentication method. You can add a provider manually. To add a + provider you must know the provider URL (e.g. + https://provider.com) +

+

+ Learn more about Anastasis providers +

+
+ )} +
); } function MethodButton(props: { method: KnownAuthMethods }): VNode { - if (authMethods[props.method].skip) return
- + if (authMethods[props.method].skip) return
; + return (
); } - const errors = !haveMethodsConfigured ? "There is not enough authentication methods." : undefined; + const errors = !haveMethodsConfigured + ? "There is not enough authentication methods." + : undefined; + const handleNext = async () => { + const st = reducer.currentReducerState as ReducerStateBackup; + if ((st.authentication_methods ?? []).length <= 2) { + setTooFewAuths(true); + } else { + await reducer.transition("next", {}); + } + }; return ( - +
- {getKeys(authMethods).map(method => )} + {getKeys(authMethods).map((method) => ( + + ))}
- {authAvailableSet.size === 0 && setNoProvidersAck(true)} description="No providers founds" label="Add a provider manually" - onConfirm={() => { - null - }} - > - We have found no trusted cloud providers for your recovery secret. You can add a provider manually. - To add a provider you must know the provider URL (e.g. https://provider.com) -

- More about cloud providers -

-
} + {tooFewAuths ? ( + setTooFewAuths(false)} + description="Too few auth methods configured" + label="Proceed anyway" + onConfirm={() => reducer.transition("next", {})} + > + You have selected fewer than three authentication methods. We + recommend that you add at least three. + + ) : null} + {authAvailableSet.size === 0 && ( + setNoProvidersAck(true)} + description="No providers founds" + label="Add a provider manually" + onConfirm={() => { + null; + }} + > +

+ We have found no Anastasis providers for your chosen country / + currency. You can add a providers manually. To add a provider + you must know the provider URL (e.g. https://provider.com) +

+

+ Learn more about Anastasis providers +

+
+ )}

- When recovering your wallet, you will be asked to verify your identity via the methods you configure here. - The list of authentication method is defined by the backup provider list. + When recovering your wallet, you will be asked to verify your + identity via the methods you configure here. The list of + authentication method is defined by the backup provider list.

- +

- {authAvailableSet.size > 0 &&

- We couldn't find provider for some of the authentication methods. -

} + {authAvailableSet.size > 0 && ( +

+ We couldn't find provider for some of the authentication methods. +

+ )}
@@ -172,30 +226,54 @@ function AuthMethodNotImplemented(props: AuthMethodSetupProps): VNode { ); } - -function ConfirmModal({ active, description, onCancel, onConfirm, children, danger, disabled, label = 'Confirm' }: Props): VNode { - return
-