From 5411580777ca09eef272c65d58a167dd107d09f9 Mon Sep 17 00:00:00 2001 From: Zachary Johnson Date: Wed, 24 Jan 2024 22:11:27 -0500 Subject: [PATCH 1/6] automatically jump to the next input box when confirming the seed phrase backup --- src/components/MnemonicPhraseInput.tsx | 19 +++++++++++++++++++ src/components/MnemonicWordInput.tsx | 17 ++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/components/MnemonicPhraseInput.tsx b/src/components/MnemonicPhraseInput.tsx index 7f6ff21dc..cc53a56fe 100644 --- a/src/components/MnemonicPhraseInput.tsx +++ b/src/components/MnemonicPhraseInput.tsx @@ -1,3 +1,4 @@ +import { useEffect, useRef, useState } from 'react' import MnemonicWordInput from './MnemonicWordInput' interface MnemonicPhraseInputProps { @@ -15,6 +16,20 @@ export default function MnemonicPhraseInput({ isValid, onChange, }: MnemonicPhraseInputProps) { + const [activeIndex, setActiveIndex] = useState(0) + const inputRefs = useRef([]) + + useEffect(() => { + if (activeIndex < mnemonicPhrase.length && isValid && isValid(activeIndex)) { + const nextIndex = activeIndex + 1 + setActiveIndex(nextIndex) + + if (inputRefs.current[nextIndex]) { + inputRefs.current[nextIndex].focus() + } + } + }, [mnemonicPhrase, activeIndex, isValid]) + return (
{mnemonicPhrase.map((_, outerIndex) => { @@ -26,9 +41,11 @@ export default function MnemonicPhraseInput({
{wordGroup.map((givenWord, innerIndex) => { const wordIndex = outerIndex + innerIndex + const isCurrentActive = wordIndex === activeIndex return (
(inputRefs.current[wordIndex] = el)} index={wordIndex} value={givenWord} setValue={(value, i) => { @@ -37,6 +54,8 @@ export default function MnemonicPhraseInput({ }} isValid={isValid ? isValid(wordIndex) : undefined} disabled={isDisabled ? isDisabled(wordIndex) : undefined} + onFocus={() => setActiveIndex(wordIndex)} + autoFocus={isCurrentActive} />
) diff --git a/src/components/MnemonicWordInput.tsx b/src/components/MnemonicWordInput.tsx index eb61abc8b..94039cd12 100644 --- a/src/components/MnemonicWordInput.tsx +++ b/src/components/MnemonicWordInput.tsx @@ -3,19 +3,32 @@ import { useTranslation } from 'react-i18next' import styles from './MnemonicWordInput.module.css' interface MnemonicWordInputProps { + forwardRef: (el: HTMLInputElement) => void index: number value: string setValue: (value: string, index: number) => void isValid?: boolean disabled?: boolean + onFocus?: () => void + autoFocus?: boolean } -const MnemonicWordInput = ({ index, value, setValue, isValid, disabled }: MnemonicWordInputProps) => { +const MnemonicWordInput = ({ + forwardRef, + index, + value, + setValue, + isValid, + disabled, + onFocus, + autoFocus, +}: MnemonicWordInputProps) => { const { t } = useTranslation() return ( {index + 1}. 0} isValid={isValid === true} + onFocus={onFocus} + autoFocus={autoFocus} required /> From 01abc36ad19dba4a9a6c0aeed72973e49bc3e525 Mon Sep 17 00:00:00 2001 From: Zachary Johnson Date: Wed, 3 Apr 2024 15:42:10 -0400 Subject: [PATCH 2/6] initial connection error message improvement --- src/components/App.tsx | 6 +++++- src/context/ServiceInfoContext.tsx | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index c21c84ec6..e78822585 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -132,7 +132,11 @@ export default function App() { path="*" element={ - {t('app.alert_no_connection', { connectionError: sessionConnectionError.message })}. + {t('app.alert_no_connection', { connectionError: sessionConnectionError })}. + {!sessionConnectionError.response?.ok && + sessionConnectionError.response?.url && + ` Unable to access ${sessionConnectionError.response.url}. + Please confirm that the backend is running.`} } /> diff --git a/src/context/ServiceInfoContext.tsx b/src/context/ServiceInfoContext.tsx index 23051dbb2..3add84751 100644 --- a/src/context/ServiceInfoContext.tsx +++ b/src/context/ServiceInfoContext.tsx @@ -89,11 +89,16 @@ type ServiceInfo = SessionFlag & SessionInfo & ServerInfo +interface ErrorAndResponse { + error?: Error + response?: Response +} + interface ServiceInfoContextEntry { serviceInfo: ServiceInfo | null reloadServiceInfo: ({ signal }: { signal: AbortSignal }) => Promise dispatchServiceInfo: Dispatch> - connectionError?: Error + connectionError?: ErrorAndResponse } const ServiceInfoContext = createContext(undefined) @@ -107,7 +112,7 @@ const ServiceInfoProvider = ({ children }: PropsWithChildren<{}>) => { (state: ServiceInfo | null, obj: Partial) => ({ ...state, ...obj }) as ServiceInfo | null, null, ) - const [connectionError, setConnectionError] = useState() + const [connectionError, setConnectionError] = useState() useEffect(() => { const abortCtrl = new AbortController() From 89834ed627b78489e99fa7f9eb12d2fb62a0ef36 Mon Sep 17 00:00:00 2001 From: Zachary Johnson Date: Wed, 3 Apr 2024 16:59:44 -0400 Subject: [PATCH 3/6] add translation entry --- src/components/App.tsx | 29 ++++++++++++++++++++++------ src/i18n/locales/en/translation.json | 1 + 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index e78822585..f8173c1d8 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,6 +1,6 @@ import { Suspense, lazy, useCallback, useEffect, useMemo, useState } from 'react' import * as rb from 'react-bootstrap' -import { useTranslation } from 'react-i18next' +import { Trans, useTranslation } from 'react-i18next' import { createBrowserRouter, createRoutesFromElements, @@ -132,11 +132,28 @@ export default function App() { path="*" element={ - {t('app.alert_no_connection', { connectionError: sessionConnectionError })}. - {!sessionConnectionError.response?.ok && - sessionConnectionError.response?.url && - ` Unable to access ${sessionConnectionError.response.url}. - Please confirm that the backend is running.`} + {t('app.alert_no_connection', { connectionError: sessionConnectionError })}.{' '} + {!sessionConnectionError.response?.ok && sessionConnectionError.response?.url && ( + + {sessionConnectionError.response.url} + + ), + 2: ( + + this link + + ), + }} + /> + )} } /> diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index f32e6e2b9..6f523881f 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -32,6 +32,7 @@ }, "app": { "alert_no_connection": "No connection to backend: {{ connectionError }}", + "alert_no_connection_details": "Unable to access <1>this URL. Please confirm that the backend is running and see <2>this link for more information.", "alert_rescan_in_progress": "Rescanning in progress..." }, "navbar": { From 1fb13b7c9019b7476ad0d97a5172fa804b992094 Mon Sep 17 00:00:00 2001 From: Zachary Johnson Date: Wed, 3 Apr 2024 17:01:12 -0400 Subject: [PATCH 4/6] update language --- src/components/App.tsx | 2 +- src/i18n/locales/en/translation.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index f8173c1d8..c9e99eb9d 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -148,7 +148,7 @@ export default function App() { target="_blank" rel="noopener noreferrer" > - this link + the docs ), }} diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index 6f523881f..4b035bdda 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -32,7 +32,7 @@ }, "app": { "alert_no_connection": "No connection to backend: {{ connectionError }}", - "alert_no_connection_details": "Unable to access <1>this URL. Please confirm that the backend is running and see <2>this link for more information.", + "alert_no_connection_details": "Unable to access <1>this URL. Please confirm that the backend is running and see <2>the docs for more information.", "alert_rescan_in_progress": "Rescanning in progress..." }, "navbar": { From 0cb53f0adfde4f302c767c88d7df624913200b96 Mon Sep 17 00:00:00 2001 From: Zachary Johnson Date: Wed, 3 Apr 2024 17:11:55 -0400 Subject: [PATCH 5/6] fix type to just use original JmApiError --- src/components/App.tsx | 2 +- src/context/ServiceInfoContext.tsx | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index c9e99eb9d..cb963fb65 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -132,7 +132,7 @@ export default function App() { path="*" element={ - {t('app.alert_no_connection', { connectionError: sessionConnectionError })}.{' '} + {t('app.alert_no_connection', { connectionError: sessionConnectionError.message })}.{' '} {!sessionConnectionError.response?.ok && sessionConnectionError.response?.url && ( Promise dispatchServiceInfo: Dispatch> - connectionError?: ErrorAndResponse + connectionError?: Api.JmApiError } const ServiceInfoContext = createContext(undefined) @@ -112,7 +107,7 @@ const ServiceInfoProvider = ({ children }: PropsWithChildren<{}>) => { (state: ServiceInfo | null, obj: Partial) => ({ ...state, ...obj }) as ServiceInfo | null, null, ) - const [connectionError, setConnectionError] = useState() + const [connectionError, setConnectionError] = useState() useEffect(() => { const abortCtrl = new AbortController() From 4970ecadb86d33c3267e9c16e87592ab8641fce6 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Mon, 22 Apr 2024 13:41:24 +0200 Subject: [PATCH 6/6] chore(alert): heading and paragraph for connection error alert --- src/components/App.tsx | 50 ++++++++++++++++------------ src/i18n/locales/en/translation.json | 2 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index cb963fb65..1edbd5e67 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -87,6 +87,8 @@ export default function App() { [reloadCurrentWalletInfo], ) + debugger + const router = createBrowserRouter( createRoutesFromElements( - {t('app.alert_no_connection', { connectionError: sessionConnectionError.message })}.{' '} - {!sessionConnectionError.response?.ok && sessionConnectionError.response?.url && ( - - {sessionConnectionError.response.url} - - ), - 2: ( - - the docs - - ), - }} - /> +
+ {t('app.alert_no_connection', { connectionError: sessionConnectionError.message })} +
+ {!sessionConnectionError.response?.ok && ( + <> +

+ + the docs + + ), + }} + /> +

+
+                        {sessionConnectionError.response.status} {sessionConnectionError.response.statusText} 
+                        {sessionConnectionError.response.url}
+                      
+ )}
} diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index 4b035bdda..8ddf45d3f 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -32,7 +32,7 @@ }, "app": { "alert_no_connection": "No connection to backend: {{ connectionError }}", - "alert_no_connection_details": "Unable to access <1>this URL. Please confirm that the backend is running and see <2>the docs for more information.", + "alert_no_connection_details": "Please confirm that the backend is running and <1>see the docs for more information.", "alert_rescan_in_progress": "Rescanning in progress..." }, "navbar": {