From 888cfa7be33caf6472973f2c34175fad0888c9fa Mon Sep 17 00:00:00 2001 From: bgptr Date: Fri, 23 Jul 2021 12:27:52 +0200 Subject: [PATCH 1/9] introduce CreationWarning component --- .../views/LNPage/ConnectPage/ConnectPage.jsx | 5 ++++- .../CreationWarning/CreationWarning.jsx | 17 +++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/app/components/views/LNPage/ConnectPage/ConnectPage.jsx b/app/components/views/LNPage/ConnectPage/ConnectPage.jsx index 4a06cbe091..6705e152fb 100644 --- a/app/components/views/LNPage/ConnectPage/ConnectPage.jsx +++ b/app/components/views/LNPage/ConnectPage/ConnectPage.jsx @@ -1,6 +1,9 @@ import { StandalonePage, StandaloneHeader } from "layout"; import { FormattedMessage as T } from "react-intl"; -import { PiUiPassphraseModalButton } from "buttons"; +import { + PiUiPassphraseModalButton, + ToggleSwitch +} from "buttons"; import { Tooltip } from "pi-ui"; import { LNWALLET_STARTUPSTAGE_STARTDCRLND, diff --git a/app/components/views/LNPage/ConnectPage/CreationWarning/CreationWarning.jsx b/app/components/views/LNPage/ConnectPage/CreationWarning/CreationWarning.jsx index 6824e12750..6e48ca36a6 100644 --- a/app/components/views/LNPage/ConnectPage/CreationWarning/CreationWarning.jsx +++ b/app/components/views/LNPage/ConnectPage/CreationWarning/CreationWarning.jsx @@ -24,20 +24,9 @@ const CreationWarning = ({ onAcceptCreationWarning }) => { ); return ( -
- }> - - - - -
+ <> + + Date: Wed, 2 Feb 2022 17:43:34 +0100 Subject: [PATCH 2/9] update launcher --- app/actions/DaemonActions.js | 40 ++ app/actions/SettingsActions.js | 9 +- app/actions/WalletLoaderActions.js | 23 + .../AnimatedLinearProgressFull.jsx | 233 +++++++++ .../AnimatedLinearProgressFull.module.css | 97 ++++ .../AnimatedLinearProgressFull/index.js | 1 + .../AnimatedLinearProgressFull.jsx | 182 ------- .../LinearProgress/LinearProgress.module.css | 85 ---- app/components/indicators/index.js | 2 +- .../AutoWalletLaunchingModal.jsx | 48 ++ .../AutoWalletLaunchingModal.module.css | 47 ++ .../modals/AutoWalletLaunchingModal/index.js | 1 + app/components/modals/index.js | 1 + .../AdvancedStartup/Form/Form.jsx | 8 +- .../GetStartedPage/GetStarted.module.css | 39 +- .../GetStartedMachinePage.jsx | 108 ++--- .../GetStartedMachinePage.module.css | 3 +- .../views/GetStartedPage/GetStartedPage.jsx | 35 +- .../LoadingPage/LoadingPage.jsx | 47 ++ .../LoadingPage/LoadingPage.module.css | 19 + .../views/GetStartedPage/LoadingPage/index.js | 1 + .../OnboardingTutorialPage.jsx | 43 ++ .../OnboardingTutorialPage.module.css | 21 + .../OnboardingTutorialPage/hooks.js | 22 + .../OnboardingTutorialPage/index.js | 1 + .../CreateWalletForm/CreateWalletForm.jsx | 58 +-- .../RescanWallet/RescanWallet.jsx | 29 -- .../ProcessManagedTickets.jsx | 10 - .../ProcessUnmanagedTickets.jsx | 10 - .../SetMixedAcctPage/SetMixedAcctPage.jsx | 11 +- .../SetupWallet/SetupWallet.jsx | 45 +- .../SetupWallet/SetupWallet.module.css | 17 +- .../views/GetStartedPage/SetupWallet/hooks.js | 1 - .../TutorialPage/TutorialPage.jsx | 4 +- .../WalletSelection/Form/Form.jsx | 445 +++++++++++------- .../WalletSelection/Form/Form.module.css | 180 +++---- .../WalletSelection/WalletSelection.jsx | 22 +- .../ContentContainer.module.css | 9 +- .../GetStartedPage/helpers/Header/Header.jsx | 21 - .../helpers/Header/Header.module.css | 17 - .../GetStartedPage/helpers/Header/index.js | 1 - .../LoaderBarContainer/LoaderBarContainer.jsx | 10 + .../LoaderBarContainer.module.css | 7 + .../helpers/LoaderBarContainer/index.js | 1 + .../views/GetStartedPage/helpers/index.js | 2 +- app/components/views/GetStartedPage/hooks.js | 224 ++++++--- .../GetStartedPage/messages/messages.jsx | 72 ++- .../TutorialsTab/TutorialsTab.jsx | 5 +- .../TutorialsTab/TutorialsTab.module.css | 15 + .../helpers/PagedTutorial/PagedTutorial.jsx | 12 +- .../helpers/TutorialCard/TutorialCard.jsx | 48 +- .../TutorialCard/TutorialCard.module.css | 32 +- .../TutorialOverview/TutorialOverview.jsx | 12 +- .../TutorialOverview.module.css | 8 + .../helpers/TutorialPage/TutorialPage.jsx | 10 +- .../views/WalletError/WalletError.jsx | 7 +- app/constants/config.js | 5 +- app/helpers/displayWalletGradients.js | 13 + app/helpers/index.js | 1 + app/hooks/useDaemonStartup.js | 34 +- app/index.js | 3 +- app/main_dev/ipc.js | 6 +- app/reducers/walletLoader.js | 14 +- app/selectors.js | 16 +- app/stateMachines/GetStartedStateMachine.js | 35 +- app/style/icons/blockchainInitial.svg | 2 +- app/style/icons/blockchain_syncing_loader.gif | Bin 20247 -> 3764 bytes app/style/icons/closeWhite.svg | 17 - app/style/icons/daemon_waiting_loader.gif | Bin 6606 -> 6719 bytes .../icons/discovering_addresses_loader.gif | Bin 55100 -> 2306 bytes app/style/icons/editDefault.svg | 1 - app/style/icons/editDefaultDark.svg | 8 - app/style/icons/editHover.svg | 1 - app/style/icons/editHoverDark.svg | 8 - app/style/icons/establishing_rpc_loader.gif | Bin 24389 -> 5298 bytes app/style/icons/fetching_headers_loader.gif | Bin 8567 -> 4839 bytes app/style/icons/finalizing_setup_loader.gif | Bin 38281 -> 9328 bytes app/style/icons/scanning_blocks_loader.gif | Bin 40687 -> 10798 bytes app/style/themes/darkTheme.js | 12 +- app/style/themes/icons.js | 1 - app/style/themes/lightTheme.js | 15 +- test/unit/actions/DaemonActions.spec.js | 130 +++++ .../AnimatedLinearProgressFull.spec.js | 88 ++-- .../GetStaredPage/AdvancedStartup.spec.js | 9 +- .../views/GetStaredPage/CreateWallet.spec.js | 18 +- .../GetStaredPage/GetStartedPage.spec.js | 58 +-- .../GetStaredPage/LanguageSelectPage.spec.js | 2 +- .../GetStaredPage/PreCreateWallet.spec.js | 8 +- .../views/GetStaredPage/RescanWallet.spec.js | 46 -- .../GetStaredPage/WalletSelection.spec.js | 50 +- yarn.lock | 2 +- 91 files changed, 1868 insertions(+), 1196 deletions(-) create mode 100644 app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.jsx create mode 100644 app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.module.css create mode 100644 app/components/indicators/AnimatedLinearProgressFull/index.js delete mode 100644 app/components/indicators/LinearProgress/AnimatedLinearProgressFull.jsx create mode 100644 app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.jsx create mode 100644 app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.module.css create mode 100644 app/components/modals/AutoWalletLaunchingModal/index.js create mode 100644 app/components/views/GetStartedPage/LoadingPage/LoadingPage.jsx create mode 100644 app/components/views/GetStartedPage/LoadingPage/LoadingPage.module.css create mode 100644 app/components/views/GetStartedPage/LoadingPage/index.js create mode 100644 app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.jsx create mode 100644 app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.module.css create mode 100644 app/components/views/GetStartedPage/OnboardingTutorialPage/hooks.js create mode 100644 app/components/views/GetStartedPage/OnboardingTutorialPage/index.js delete mode 100644 app/components/views/GetStartedPage/RescanWallet/RescanWallet.jsx delete mode 100644 app/components/views/GetStartedPage/helpers/Header/Header.jsx delete mode 100644 app/components/views/GetStartedPage/helpers/Header/Header.module.css delete mode 100644 app/components/views/GetStartedPage/helpers/Header/index.js create mode 100644 app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.jsx create mode 100644 app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.module.css create mode 100644 app/components/views/GetStartedPage/helpers/LoaderBarContainer/index.js create mode 100644 app/components/views/SettingsPage/TutorialsTab/TutorialsTab.module.css create mode 100644 app/helpers/displayWalletGradients.js delete mode 100644 app/style/icons/closeWhite.svg delete mode 100644 app/style/icons/editDefault.svg delete mode 100755 app/style/icons/editDefaultDark.svg delete mode 100644 app/style/icons/editHover.svg delete mode 100644 app/style/icons/editHoverDark.svg create mode 100644 test/unit/actions/DaemonActions.spec.js delete mode 100644 test/unit/components/views/GetStaredPage/RescanWallet.spec.js diff --git a/app/actions/DaemonActions.js b/app/actions/DaemonActions.js index 764fef237d..abae592043 100644 --- a/app/actions/DaemonActions.js +++ b/app/actions/DaemonActions.js @@ -28,6 +28,7 @@ import { STANDARD_EXTERNAL_REQUESTS } from "constants"; import { DIFF_CONNECTION_ERROR, LOCALE, TESTNET } from "constants"; import * as cfgConstants from "constants/config"; import { CSPP_URL, CSPP_URL_LEGACY } from "constants"; +import { preDefinedGradients } from "helpers"; export const DECREDITON_VERSION = "DECREDITON_VERSION"; export const SELECT_LANGUAGE = "SELECT_LANGUAGE"; @@ -770,3 +771,42 @@ export const getDexLogs = () => (dispatch, getState) => .then((logs) => resolve(logs)) .catch((err) => reject(err)); }); + +export const generateRandomGradient = () => { + const randomColor = Math.floor(Math.random() * 16777215).toString(16); + const invertedColor = (Number(`0x1${randomColor}`) ^ 0xffffff) + .toString(16) + .substr(1); + return `linear-gradient(#${randomColor} 0%, #${invertedColor} 100%)`; +}; + +export const checkDisplayWalletGradients = (availableWallets) => ( + dispatch, + getState +) => { + const missingGradientWallets = []; + let availableGradients = [...preDefinedGradients]; + availableWallets + .sort((a, b) => b.lastAccess - a.lastAccess) + .forEach(({ wallet, displayWalletGradient }) => { + if (!displayWalletGradient) { + missingGradientWallets.push(wallet); + } else { + availableGradients = availableGradients.filter( + (gradient) => gradient != displayWalletGradient + ); + } + }); + + // set missing gradients + if (missingGradientWallets.length > 0) { + availableGradients.reverse(); + missingGradientWallets.forEach((walletName) => { + const gradient = availableGradients.pop() ?? generateRandomGradient(); + const config = wallet.getWalletCfg(isTestNet(getState()), walletName); + config.set(cfgConstants.DISPLAY_WALLET_GRADIENT, gradient); + }); + + dispatch(getAvailableWallets()); + } +}; diff --git a/app/actions/SettingsActions.js b/app/actions/SettingsActions.js index e02eefc958..e76bee83ec 100644 --- a/app/actions/SettingsActions.js +++ b/app/actions/SettingsActions.js @@ -52,6 +52,10 @@ export const saveSettings = (settings) => async (dispatch, getState) => { config.set(configConstants.NETWORK, settings.network); config.set(configConstants.THEME, settings.theme); config.set(configConstants.UI_ANIMATIONS, settings.uiAnimations); + config.set( + configConstants.AUTO_WALLET_LAUNCHING, + settings.autoWalletLaunching + ); if (walletName) { const walletConfig = wallet.getWalletCfg(isTestNet(getState()), walletName); @@ -62,7 +66,10 @@ export const saveSettings = (settings) => async (dispatch, getState) => { } if ( - !equalElements(oldAllowedExternalRequests, settings.allowedExternalRequests) + !equalElements( + oldAllowedExternalRequests ?? [], + settings.allowedExternalRequests + ) ) { wallet.reloadAllowedExternalRequests(); } diff --git a/app/actions/WalletLoaderActions.js b/app/actions/WalletLoaderActions.js index e240375272..84c250c01c 100644 --- a/app/actions/WalletLoaderActions.js +++ b/app/actions/WalletLoaderActions.js @@ -28,6 +28,7 @@ import * as cfgConstants from "constants/config"; import { RESCAN_PROGRESS } from "./ControlActions"; import { stopAccountMixer } from "./AccountMixerActions"; import { TRZ_WALLET_CLOSED } from "actions/TrezorActions"; +import { saveSettings, updateStateSettingsChanged } from "./SettingsActions"; const { SyncNotificationType } = api; @@ -717,3 +718,25 @@ export const acceptStakingWarning = () => (dispatch, getState) => { showStakingWarning: false }); }; + +export const STOP_UNFINISHED_WALLET_FAILED = "STOP_UNFINISHED_WALLET_FAILED"; +export const stopUnfinishedWallet = () => async (dispatch) => { + try { + await wallet.stopWallet(); + dispatch(setSelectedWallet(null)); + } catch (err) { + dispatch({ error: err, type: STOP_UNFINISHED_WALLET_FAILED }); + } +}; + +export const setAutoWalletLaunching = (autoWalletLaunching) => async ( + dispatch, + getState +) => { + dispatch(updateStateSettingsChanged({ autoWalletLaunching }, true)); + const tempSettings = getState().settings.tempSettings; + const config = wallet.getGlobalCfg(); + config.set(cfgConstants.AUTO_WALLET_LAUNCHING, autoWalletLaunching); + + await dispatch(saveSettings(tempSettings)); +}; diff --git a/app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.jsx b/app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.jsx new file mode 100644 index 0000000000..8a2a6d65cf --- /dev/null +++ b/app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.jsx @@ -0,0 +1,233 @@ +import { useState, useCallback } from "react"; +import { useDaemonStartup, useMountEffect } from "hooks"; +import { HeaderTimeMsg } from "views/GetStartedPage/messages"; +import { FormattedRelative } from "shared"; +import { FormattedMessage as T } from "react-intl"; +import ReactTimeout from "react-timeout"; +import { classNames, Tooltip } from "pi-ui"; +import styles from "./AnimatedLinearProgressFull.module.css"; +import { useRescan } from "hooks"; +import { KeyBlueButton } from "buttons"; +import { AutoWalletLaunchingModal } from "modals"; + +const AnimatedLinearProgressFull = ({ + setInterval, + min, + error, + text, + animationType, + initialAnimationType, + hideTextBlock, + onCancelLoadingWallet, + onContinueOpeningWallet, + onSaveAndContinueOpeningWallet, + nextStateAfterWalletLoading, + hideOpenWalletButton +}) => { + const { + isSPV, + getNeededBlocks, + getEstimatedTimeLeft, + selectedWalletSelector, + getCurrentBlockCount, + syncFetchHeadersLastHeaderTime, + syncFetchHeadersFirstHeaderTime, + getDcrwalletLogs, + getDaemonSynced, + onGetDcrdLogs, + syncRescanAttempt, + startWalletServiceAttempt, + synced + } = useDaemonStartup(); + const { rescanEndBlock, rescanStartBlock, rescanCurrentBlock } = useRescan(); + const [lastDcrwalletLogLine, setLogLine] = useState(""); + const [lastDcrdLogLine, setDcrdLogLine] = useState(""); + const [ + isAutoWalletLaunchingModalVisible, + setIsAutoWalletLaunchingModalVisible + ] = useState(false); + const showAutoWalletLaunchingModalVisible = useCallback( + () => setIsAutoWalletLaunchingModalVisible(true), + [setIsAutoWalletLaunchingModalVisible] + ); + + useMountEffect(() => { + setInterval(async () => { + try { + const lastDcrwalletLogLine = await getDcrwalletLogs(); + setLogLine(lastDcrwalletLogLine); + } catch (err) { + console.log(err); + } + }, 2000); + setInterval(async () => { + try { + const lastDcrdLogLine = await onGetDcrdLogs(); + setDcrdLogLine(lastDcrdLogLine); + } catch (err) { + console.log(err); + } + }, 2000); + }, [setInterval, getDcrwalletLogs, onGetDcrdLogs]); + + const now = Date.now(); + let perComplete; + if (!getDaemonSynced && getCurrentBlockCount) { + perComplete = (getCurrentBlockCount - min) / (getNeededBlocks - min); + } else if (syncRescanAttempt && rescanCurrentBlock) { + perComplete = + (rescanCurrentBlock - rescanStartBlock) / + (rescanEndBlock - rescanStartBlock); + } else if (syncFetchHeadersLastHeaderTime) { + const syncFetchHeadersLastHeaderTimeTs = new Date( + syncFetchHeadersLastHeaderTime + ).getTime(); + const syncFetchHeadersFirstHeaderTimeTs = new Date( + syncFetchHeadersFirstHeaderTime + ).getTime(); + perComplete = + (syncFetchHeadersLastHeaderTimeTs - syncFetchHeadersFirstHeaderTimeTs) / + (now - syncFetchHeadersFirstHeaderTimeTs); + } + + const leftStartingPoint = perComplete ? perComplete * 100 : 0; + let finishDateEstimation = null; + if (getEstimatedTimeLeft !== null) { + finishDateEstimation = new Date(); + finishDateEstimation.setSeconds( + finishDateEstimation.getSeconds() + getEstimatedTimeLeft + ); + } + + return ( +
+
+ {perComplete > 0 && ( +
+ )} +
+ {selectedWalletSelector?.value?.wallet && + `${selectedWalletSelector.value.wallet} - `} + {text} +
+ {getCurrentBlockCount && !getDaemonSynced && ( +
+ + + {finishDateEstimation && ( + + )} + ({getCurrentBlockCount} / {getNeededBlocks}) + +
+ )} + {syncRescanAttempt && rescanCurrentBlock ? ( +
+ rescanStartBlock + ? rescanCurrentBlock + : rescanStartBlock, + rescanEndBlock: rescanEndBlock + }} + /> +
+ ) : startWalletServiceAttempt ? ( +
+ +
+ ) : ( + selectedWalletSelector && + !synced && + syncFetchHeadersLastHeaderTime && ( +
+ + + + +
+ ) + )} +
+
+ {isSPV && ( +
+ }> +
+ +
+ )} +
+
+
+ {!hideOpenWalletButton && + selectedWalletSelector && + (nextStateAfterWalletLoading ? ( + <> + + + + + + ) : ( + !startWalletServiceAttempt && ( + + + + ) + ))} +
+ {!hideTextBlock && ( +
+ {!getDaemonSynced && lastDcrdLogLine && !selectedWalletSelector && ( +
+
{lastDcrdLogLine}
+
+ )} + {selectedWalletSelector && lastDcrwalletLogLine && ( +
+
{lastDcrwalletLogLine}
+
+ )} +
+ )} +
+ ); +}; + +export default ReactTimeout(AnimatedLinearProgressFull); diff --git a/app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.module.css b/app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.module.css new file mode 100644 index 0000000000..2b8117da5a --- /dev/null +++ b/app/components/indicators/AnimatedLinearProgressFull/AnimatedLinearProgressFull.module.css @@ -0,0 +1,97 @@ +.linearProgress { + height: 9.4rem; + width: 100%; + background-color: var(--loader-bg); + position: relative; + display: grid; + + grid-template-columns: max-content auto; + padding: 1.7rem 4rem 2.2rem 4rem; + color: var(--main-dark-blue); +} + +.linearProgressBar { + top: 0; + left: 0; + background: linear-gradient( + 270deg, + var(--display-wallet-gradient-selected-right), + var(--input-color) + ); + border-radius: 0 0.25rem 0.25rem 0; + height: 0.5rem; + box-shadow: 0px 5px 13px var(--input-color-blue-shadow); + transition: width 0.3s linear 0ms; + position: absolute; +} + +.linearProgressBar.error { + background-color: var(--error-text-color); +} + +.linearProgressText { + font-family: var(--font-family-regular); + + font-size: 1.1rem; + font-weight: 700; + line-height: 1.4rem; +} + +.icons { + display: flex; + justify-content: flex-end; +} + +.icon { + background-image: var(--blockchain-default); + background-repeat: no-repeat; + background-size: 3rem; + width: 3rem; + height: 3rem; +} + +.icon.initial { + background-image: var(--blockchain-initial); + background-size: 2.5rem; +} + +.loaderBarEstimation { + font-size: 1.1rem; + font-weight: 400; + line-height: 1.4rem; +} + +.loaderBarEstimation .bold { + font-weight: 700; +} + +.lastLogLines { + font-size: 0.9rem; + text-align: right; + margin-top: 0.5rem; +} + +.openWalletButton, +.cancelLoadingButton { + line-height: 1.6rem !important; + padding: 0.6rem 1rem !important; + margin-top: 0.5rem; +} + +.cancelLoadingButton { + background-color: var(--grey-7) !important; +} + +.spvIcon { + background-image: var(--menu-spvon-icon); + height: 3rem; + width: 3rem; + background-size: 3rem; + margin-right: 1.5rem; +} + +@media screen and (max-width: 768px) { + .loaderBarEstimation { + display: none; + } +} diff --git a/app/components/indicators/AnimatedLinearProgressFull/index.js b/app/components/indicators/AnimatedLinearProgressFull/index.js new file mode 100644 index 0000000000..4262b5ecfb --- /dev/null +++ b/app/components/indicators/AnimatedLinearProgressFull/index.js @@ -0,0 +1 @@ +export { default } from "./AnimatedLinearProgressFull"; diff --git a/app/components/indicators/LinearProgress/AnimatedLinearProgressFull.jsx b/app/components/indicators/LinearProgress/AnimatedLinearProgressFull.jsx deleted file mode 100644 index 0246a4d014..0000000000 --- a/app/components/indicators/LinearProgress/AnimatedLinearProgressFull.jsx +++ /dev/null @@ -1,182 +0,0 @@ -import { useState } from "react"; -import { useDaemonStartup, useMountEffect } from "hooks"; -import { HeaderTimeMsg } from "views/GetStartedPage/messages"; -import { FormattedRelative } from "shared"; -import { FormattedMessage as T } from "react-intl"; -import ReactTimeout from "react-timeout"; -import { classNames } from "pi-ui"; -import styles from "./LinearProgress.module.css"; - -const AnimatedLinearProgressFull = ({ - setInterval, - min, - error, - text, - animationType, - initialAnimationType, - hideTextBlock -}) => { - const { - isSPV, - getNeededBlocks, - getEstimatedTimeLeft, - selectedWalletSelector, - getCurrentBlockCount, - syncFetchHeadersLastHeaderTime, - getDcrwalletLogs, - getDaemonSynced, - onGetDcrdLogs - } = useDaemonStartup(); - const [lastDcrwalletLogLine, setLogLine] = useState(""); - const [lastDcrdLogLine, setDcrdLogLine] = useState(""); - - useMountEffect(() => { - setInterval(async () => { - try { - const lastDcrwalletLogLine = await getDcrwalletLogs(); - setLogLine(lastDcrwalletLogLine); - } catch (err) { - console.log(err); - } - }, 2000); - setInterval(async () => { - try { - const lastDcrdLogLine = await onGetDcrdLogs(); - setDcrdLogLine(lastDcrdLogLine); - } catch (err) { - console.log(err); - } - }, 2000); - }, [setInterval, getDcrwalletLogs, onGetDcrdLogs]); - - const perComplete = (getCurrentBlockCount - min) / (getNeededBlocks - min); - const leftStartingPoint = perComplete ? perComplete * 100 : 0; - let finishDateEstimation = null; - if (getEstimatedTimeLeft !== null) { - finishDateEstimation = new Date(); - finishDateEstimation.setSeconds( - finishDateEstimation.getSeconds() + getEstimatedTimeLeft - ); - } - return ( - <> -
- {getDaemonSynced || isSPV ? ( - <> -
-
- {text} -
- - ) : ( - <> -
-
- {perComplete > 0.1 && perComplete < 1 && ( -
- )} - {perComplete > 0.25 && perComplete < 1 && ( -
- )} - {perComplete > 0.4 && perComplete < 1 && ( -
- )} - {perComplete > 0.6 && perComplete < 1 && ( -
- )} - {perComplete > 0.75 && perComplete < 1 && ( -
- )} - {perComplete > 0.9 && perComplete < 1 && ( -
- )} -
-
- {text} -
- - )} -
- {!hideTextBlock && ( -
- {getCurrentBlockCount && !getDaemonSynced && ( -
- - - {finishDateEstimation && ( - - )} - ({getCurrentBlockCount} / {getNeededBlocks}) - -
- )} - {selectedWalletSelector && syncFetchHeadersLastHeaderTime && ( -
- - - - -
- )} - {!getDaemonSynced && lastDcrdLogLine && !selectedWalletSelector && ( -
-
{lastDcrdLogLine}
-
- )} - {selectedWalletSelector && lastDcrwalletLogLine && ( -
-
{lastDcrwalletLogLine}
-
- )} -
- )} - - ); -}; - -export default ReactTimeout(AnimatedLinearProgressFull); diff --git a/app/components/indicators/LinearProgress/LinearProgress.module.css b/app/components/indicators/LinearProgress/LinearProgress.module.css index 8ac76f32b2..6c4bfa8fb1 100644 --- a/app/components/indicators/LinearProgress/LinearProgress.module.css +++ b/app/components/indicators/LinearProgress/LinearProgress.module.css @@ -26,88 +26,3 @@ .linearProgressBar.error { background-color: var(--error-text-color); } -@keyframes slide { - 0% { - opacity: 0.01; - } - - 25% { - opacity: 0.08; - } - - 75% { - opacity: 0.08; - } - - 100% { - left: 59px; - } -} -.linearProgressBox { - position: absolute; - margin-top: 7px; - height: 41px; - width: 41px; - border-radius: 3px; - opacity: 0; - background-color: var(--background-back-color); - animation: slide 3s cubic-bezier(0.46, 0.03, 0.52, 0.96) infinite; -} -.linearProgressBox.one { - animation-delay: 0s; -} -.linearProgressBox.two { - animation-delay: 0.5s; -} -.linearProgressBox.three { - animation-delay: 1s; -} -.linearProgressBox.four { - animation-delay: 1.5s; -} -.linearProgressBox.five { - animation-delay: 2s; -} -.linearProgressBox.six { - animation-delay: 2.5s; -} -.linearProgressText { - height: 100%; - text-align: left; - color: var(--linear-progress-text-default); - font-size: 11px; - font-weight: 600; - padding-left: 46px; - padding-top: 19px; - font-family: var(--font-family-regular); - background-image: var(--blockchain-default); - background-repeat: no-repeat; - background-position: 20px 20px; - background-size: 16px; - position: absolute; - width: 100%; -} -.linearProgressText.initial { - color: var(--linear-progress-text-initial); - background-image: var(--blockchain-initial); -} -.isRow { - display: flex; - flex-direction: row; -} -.loaderBarEstimation { - text-align: left; - font-size: 9px; -} -.loaderBarEstimation .bold { - opacity: 1; - font-weight: 700; -} -.lastLogLines { - font-size: 9px; -} -@media (--sm-viewport) { - .loaderBarEstimation { - display: none; - } -} diff --git a/app/components/indicators/index.js b/app/components/indicators/index.js index 372a71050e..e48f9504da 100644 --- a/app/components/indicators/index.js +++ b/app/components/indicators/index.js @@ -8,7 +8,7 @@ export { default as NoTicketsIndicator } from "./NoMoreIndicators/NoTickets"; export { default as DecredLoading } from "./DecredLoading/DecredLoading"; export { default as SimpleLoading } from "./SimpleLoading/SimpleLoading"; export { default as RescanProgress } from "./RescanProgress/RescanProgress"; -export { default as AnimatedLinearProgressFull } from "./LinearProgress/AnimatedLinearProgressFull"; +export { default as AnimatedLinearProgressFull } from "./AnimatedLinearProgressFull"; export { default as LinearProgressSmall } from "./LinearProgress/LinearProgressSmall"; export { default as LoaderBarBottom } from "./LoaderBarBottom"; export { default as NoStats } from "./NoMoreIndicators/NoStats"; diff --git a/app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.jsx b/app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.jsx new file mode 100644 index 0000000000..218f4936b6 --- /dev/null +++ b/app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.jsx @@ -0,0 +1,48 @@ +import { FormattedMessage as T } from "react-intl"; +import Modal from "../Modal"; +import styles from "./AutoWalletLaunchingModal.module.css"; +import { PiUiButton, InvisiblePiUiButton } from "buttons"; +import { useState } from "react"; +import { Checkbox } from "pi-ui"; + +const AutoWalletLaunchingModal = ({ onCancelModal, onSubmit, show }) => { + const [autoOpenWallet, setAutoOpeningWallet] = useState(true); + return ( + +
+ +
+ + } + id="autostart" + description={ + + } + checked={autoOpenWallet} + onChange={() => setAutoOpeningWallet(!autoOpenWallet)} + /> +
onCancelModal()} + /> +
+ onCancelModal()}> + + + onSubmit(autoOpenWallet)}> + + +
+ + ); +}; + +export default AutoWalletLaunchingModal; diff --git a/app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.module.css b/app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.module.css new file mode 100644 index 0000000000..2022c5acfb --- /dev/null +++ b/app/components/modals/AutoWalletLaunchingModal/AutoWalletLaunchingModal.module.css @@ -0,0 +1,47 @@ +.modal { + background-image: none; + padding: 30px 40px 20px 40px; + min-width: 52.1rem; + position: relative; + display: flex; + flex-direction: column; +} +.title { + font-size: 28px; + line-height: 35px; + color: var(--grey-7); + margin-bottom: 20px; +} +.infoCloseButtonTop { + position: absolute; + top: 20px; + right: 20px; + height: 10px; + width: 10px; + background-image: var(--x-grey); + background-size: 10px 10px; + background-repeat: no-repeat; + cursor: pointer; +} + +.infoCloseButtonTop:hover { + opacity: 0.7; +} +.buttons { + display: flex; + flex-direction: row; + justify-content: flex-end; + margin-top: 30px; +} + +@media screen and (max-width: 1179px) { + .modal { + width: 421px; + } +} + +@media screen and (max-width: 768px) { + .modal { + width: 355px; + } +} diff --git a/app/components/modals/AutoWalletLaunchingModal/index.js b/app/components/modals/AutoWalletLaunchingModal/index.js new file mode 100644 index 0000000000..f09f56cb9d --- /dev/null +++ b/app/components/modals/AutoWalletLaunchingModal/index.js @@ -0,0 +1 @@ +export { default } from "./AutoWalletLaunchingModal"; diff --git a/app/components/modals/index.js b/app/components/modals/index.js index 22f8fa37d2..0358d3e8cb 100644 --- a/app/components/modals/index.js +++ b/app/components/modals/index.js @@ -25,3 +25,4 @@ export { default as LNPaymentModal } from "./LNPaymentModal"; export { default as LNChannelModal } from "./LNChannelModal"; export { default as DiscoverUsageModal } from "./DiscoverUsageModal"; export { default as SearchForNodesModal } from "./SearchForNodesModal"; +export { default as AutoWalletLaunchingModal } from "./AutoWalletLaunchingModal"; diff --git a/app/components/views/GetStartedPage/AdvancedStartup/Form/Form.jsx b/app/components/views/GetStartedPage/AdvancedStartup/Form/Form.jsx index 28e3096a86..8860d1ae9b 100644 --- a/app/components/views/GetStartedPage/AdvancedStartup/Form/Form.jsx +++ b/app/components/views/GetStartedPage/AdvancedStartup/Form/Form.jsx @@ -5,7 +5,8 @@ import { KeyBlueButton, InvisibleButton } from "buttons"; import RemoteDaemonForm from "../RemoteDaemonForm"; import AppDataForm from "../AppDataForm"; import styles from "./Form.module.css"; -import { FormContainer, ButtonsBar } from "../../helpers"; +import { FormContainer, ButtonsBar, ContentContainer } from "../../helpers"; +import { LoaderTitleMsg } from "../../messages"; const AdvancedBodyBase = ({ onShowRemote, @@ -43,6 +44,11 @@ const AdvancedBodyBase = ({ return ( <> + +
+ +
+
( - <> -
-
- -
- {error && ( -
- {error} -
- )} - {availableWalletsError && ( -
- {availableWalletsError} -
- )} - {daemonWarning && ( -
{daemonWarning}
- )} +}) => { + const loaderBar = ( + + ); - {StateComponent && - (React.isValidElement(StateComponent) ? ( - StateComponent - ) : ( - - ))} - -); + return ( + <> + {showLoaderBar && + (loaderBarContainer ? ( + React.createElement(loaderBarContainer, { loaderBar }, null) + ) : ( +
{loaderBar}
+ ))} + {error && ( +
+ {error} +
+ )} + {availableWalletsError && ( +
+ {availableWalletsError} +
+ )} + {daemonWarning && ( +
{daemonWarning}
+ )} + {StateComponent && + (React.isValidElement(StateComponent) ? ( + StateComponent + ) : ( + + ))} + + ); +}; diff --git a/app/components/views/GetStartedPage/GetStartedMachinePage/GetStartedMachinePage.module.css b/app/components/views/GetStartedPage/GetStartedMachinePage/GetStartedMachinePage.module.css index 9e803979ef..81a4ddcc2c 100644 --- a/app/components/views/GetStartedPage/GetStartedMachinePage/GetStartedMachinePage.module.css +++ b/app/components/views/GetStartedPage/GetStartedMachinePage/GetStartedMachinePage.module.css @@ -11,7 +11,8 @@ } .daemonWarning { - padding: 10px; + color: var(--error-text-color); + padding-bottom: 0.1rem; white-space: pre-line; } diff --git a/app/components/views/GetStartedPage/GetStartedPage.jsx b/app/components/views/GetStartedPage/GetStartedPage.jsx index b67359ed9c..1d290d54cb 100644 --- a/app/components/views/GetStartedPage/GetStartedPage.jsx +++ b/app/components/views/GetStartedPage/GetStartedPage.jsx @@ -5,7 +5,8 @@ import { LogsLinkMsg, SettingsLinkMsg, UpdateAvailableLink, - AboutModalButton + LearnBasicsMsg, + ReleaseInfoMsg } from "./messages"; import { PageBody } from "layout"; import { LoaderBarBottom } from "indicators"; @@ -15,8 +16,7 @@ import styles from "./GetStarted.module.css"; const GetStarted = ({ getCurrentBlockCount, getNeededBlocks, - getEstimatedTimeLeft, - appVersion + getEstimatedTimeLeft }) => { const { onShowLogs, @@ -24,7 +24,9 @@ const GetStarted = ({ updateAvailable, isTestNet, PageComponent, - showNavLinks + showNavLinks, + onShowTutorial, + onShowReleaseNotes } = useGetStarted(); return ( @@ -41,13 +43,32 @@ const GetStarted = ({ tooltipClassName={styles.updateAvailableTooltip} /> )} - {showNavLinks && ( <> - + + + + + + + - + diff --git a/app/components/views/GetStartedPage/LoadingPage/LoadingPage.jsx b/app/components/views/GetStartedPage/LoadingPage/LoadingPage.jsx new file mode 100644 index 0000000000..8b0b5b1e83 --- /dev/null +++ b/app/components/views/GetStartedPage/LoadingPage/LoadingPage.jsx @@ -0,0 +1,47 @@ +import { + TutorialOverview, + tutorials +} from "../../SettingsPage/TutorialsTab/helpers"; +import { Subtitle } from "shared"; +import { FormattedMessage as T } from "react-intl"; +import styles from "./LoadingPage.module.css"; + +const LoadingPage = ({ onShowOnboardingTutorial }) => { + return ( +
+ + } + /> + {[ + "decredIntro", + "ln", + "consensusCode", + "powPos", + "tickets", + "staking", + "lifecycle", + "consensusVoting", + "blocks", + "identity" + ].map((name) => ( + + ))} +
+ ); +}; + +export default LoadingPage; diff --git a/app/components/views/GetStartedPage/LoadingPage/LoadingPage.module.css b/app/components/views/GetStartedPage/LoadingPage/LoadingPage.module.css new file mode 100644 index 0000000000..23fe68a39f --- /dev/null +++ b/app/components/views/GetStartedPage/LoadingPage/LoadingPage.module.css @@ -0,0 +1,19 @@ +.container { + width: 106rem; +} + +.subtitle { + padding-top: 3rem; +} + +@media screen and (max-width: 1180px) { + .container { + width: 63.4rem; + } +} + +@media screen and (max-width: 768px) { + .container { + width: 31.5rem; + } +} diff --git a/app/components/views/GetStartedPage/LoadingPage/index.js b/app/components/views/GetStartedPage/LoadingPage/index.js new file mode 100644 index 0000000000..a583868d3d --- /dev/null +++ b/app/components/views/GetStartedPage/LoadingPage/index.js @@ -0,0 +1 @@ +export { default } from "./LoadingPage"; diff --git a/app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.jsx b/app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.jsx new file mode 100644 index 0000000000..af7e5f7870 --- /dev/null +++ b/app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.jsx @@ -0,0 +1,43 @@ +import { + TutorialPage, + tutorials +} from "../../SettingsPage/TutorialsTab/helpers"; +import styles from "./OnboardingTutorialPage.module.css"; +import { useOnboardingTutorials } from "./hooks"; + +const OnboardingTutorialPage = ({ goBackHistory, currentTutorial }) => { + const { + visitedTutorialTabs, + setVisitedTutorialTabs, + activeTabIndexes, + setActiveTabIndexes + } = useOnboardingTutorials(); + + return ( +
+ + setVisitedTutorialTabs({ + ...visitedTutorialTabs, + [currentTutorial]: newCheckedTabs + }), + activeTabIndex: activeTabIndexes[currentTutorial], + setActiveTabIndex: (newActiveTabIndex) => + setActiveTabIndexes({ + ...activeTabIndexes, + [currentTutorial]: newActiveTabIndex + }), + pagedTutorialClassname: styles.pagedTutorial, + tabContentWrapperClassName: styles.tabContentWrapper + }} + /> +
+ ); +}; + +export default OnboardingTutorialPage; diff --git a/app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.module.css b/app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.module.css new file mode 100644 index 0000000000..6f4da78e69 --- /dev/null +++ b/app/components/views/GetStartedPage/OnboardingTutorialPage/OnboardingTutorialPage.module.css @@ -0,0 +1,21 @@ +.pagedTutorial, +.tabContentWrapper, +.container { + width: 106rem; +} + +@media screen and (max-width: 1180px) { + .pagedTutorial, + .tabContentWrapper, + .container { + width: 63.4rem; + } +} + +@media screen and (max-width: 768px) { + .pagedTutorial, + .tabContentWrapper, + .container { + width: 31.5rem; + } +} diff --git a/app/components/views/GetStartedPage/OnboardingTutorialPage/hooks.js b/app/components/views/GetStartedPage/OnboardingTutorialPage/hooks.js new file mode 100644 index 0000000000..ca05fd3371 --- /dev/null +++ b/app/components/views/GetStartedPage/OnboardingTutorialPage/hooks.js @@ -0,0 +1,22 @@ +import { useCallback, useState } from "react"; +import { useSelector, useDispatch } from "react-redux"; +import * as sel from "selectors"; +import * as da from "actions/DaemonActions"; + +export const useOnboardingTutorials = () => { + const visitedTutorialTabs = useSelector(sel.visitedTutorialTabs) ?? {}; + const [activeTabIndexes, setActiveTabIndexes] = useState({}); + + const dispatch = useDispatch(); + const setVisitedTutorialTabs = useCallback( + (visitedTabs) => dispatch(da.setVisitedTutorialTabs(visitedTabs)), + [dispatch] + ); + + return { + visitedTutorialTabs, + setVisitedTutorialTabs, + activeTabIndexes, + setActiveTabIndexes + }; +}; diff --git a/app/components/views/GetStartedPage/OnboardingTutorialPage/index.js b/app/components/views/GetStartedPage/OnboardingTutorialPage/index.js new file mode 100644 index 0000000000..cff2151477 --- /dev/null +++ b/app/components/views/GetStartedPage/OnboardingTutorialPage/index.js @@ -0,0 +1 @@ +export { default } from "./OnboardingTutorialPage"; diff --git a/app/components/views/GetStartedPage/PreCreateWallet/CreateWalletForm/CreateWalletForm.jsx b/app/components/views/GetStartedPage/PreCreateWallet/CreateWalletForm/CreateWalletForm.jsx index 4806a105d8..b322e91ef1 100644 --- a/app/components/views/GetStartedPage/PreCreateWallet/CreateWalletForm/CreateWalletForm.jsx +++ b/app/components/views/GetStartedPage/PreCreateWallet/CreateWalletForm/CreateWalletForm.jsx @@ -1,55 +1,12 @@ -import { FormattedMessage as T, defineMessages } from "react-intl"; +import { FormattedMessage as T } from "react-intl"; import { classNames, Checkbox, Tooltip } from "pi-ui"; import { TextInput, IntegerInput } from "inputs"; import { KeyBlueButton, InvisibleButton } from "buttons"; import { Collapse, ExternalLink } from "shared"; -import { NewSeedTabMsg, RestoreTabMsg } from "../../messages"; -import { Label, Input, Row } from "../../helpers"; +import { LoaderTitleMsg, messages } from "../../messages"; +import { Label, Input, Row, ContentContainer } from "../../helpers"; import styles from "./CreateWalletForm.module.css"; -const messages = defineMessages({ - messageWalletNamePlaceholder: { - id: "createwallet.walletname.placehlder", - defaultMessage: "Choose a Name" - }, - messageWalletNameTooltip: { - id: "createwallet.walletname.tooltip", - defaultMessage: - "The name is used to identify your wallet. Restoring a wallet does not require the name to match the previous wallet name." - }, - messageWalletWatchOnlyDescription: { - id: "createwallet.watchonly.description", - defaultMessage: - "A watch-only wallet has limited functionality. It can only be used to view the balance and monitor transaction history. You won't be able to spend any DCR associated with this wallet." - }, - messageWalletTrezorDescription: { - id: "createwallet.trezor.description", - defaultMessage: - "Trezor is a hardware wallet. For more information, visit {link}" - }, - messageWalletMasterPubKey: { - id: "createwallet.walletpubkey.placeholder", - defaultMessage: "Master Pub Key" - }, - messageWalletMasterPubkeyError: { - id: "createwallet.walletWatchOnly.error", - defaultMessage: "Invalid Master Pubkey" - }, - messageWalletDupeNameError: { - id: "createwallet.dupeWalletName.error", - defaultMessage: "Please choose an unused wallet name" - }, - messageDisablecointypeupgrades: { - id: "createwallet.disablecointypeupgrades.description", - defaultMessage: "Never upgrade from legacy to SLIP0044 coin type keys" - }, - messageGapLimit: { - id: "createwallet.gaplimit.description", - defaultMessage: - "Allowed unused address gap between used addresses of accounts" - } -}); - const CreateWalletForm = ({ createWallet, hideCreateWalletForm, @@ -75,18 +32,23 @@ const CreateWalletForm = ({ setGapLimit }) => ( <> + +
+ +
+
{isCreateNewWallet ? (
- + {intl.formatMessage(messages.newSeedTabMsg)}
) : (
- + {intl.formatMessage(messages.restoreTabMsg)}
)} diff --git a/app/components/views/GetStartedPage/RescanWallet/RescanWallet.jsx b/app/components/views/GetStartedPage/RescanWallet/RescanWallet.jsx deleted file mode 100644 index 736e33551b..0000000000 --- a/app/components/views/GetStartedPage/RescanWallet/RescanWallet.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import { LinearProgressSmall } from "indicators"; -import { FormattedMessage as T } from "react-intl"; -import { useRescan } from "hooks"; - -const RescanWalletFormBody = () => { - const { rescanEndBlock, rescanStartBlock, rescanCurrentBlock } = useRescan(); - return ( - <> - - rescanStartBlock - ? rescanCurrentBlock - : rescanStartBlock, - rescanEndBlock: rescanEndBlock - }} - /> - - ); -}; - -export default RescanWalletFormBody; diff --git a/app/components/views/GetStartedPage/SetupWallet/ProcessManagedTickets/ProcessManagedTickets.jsx b/app/components/views/GetStartedPage/SetupWallet/ProcessManagedTickets/ProcessManagedTickets.jsx index 90bed7fca2..177a1c1b69 100644 --- a/app/components/views/GetStartedPage/SetupWallet/ProcessManagedTickets/ProcessManagedTickets.jsx +++ b/app/components/views/GetStartedPage/SetupWallet/ProcessManagedTickets/ProcessManagedTickets.jsx @@ -1,10 +1,7 @@ import { useState, useEffect } from "react"; -import { Tooltip } from "pi-ui"; import { Subtitle } from "shared"; -import { GoBackMsg } from "../../messages"; import { FormattedMessage as T } from "react-intl"; import { PassphraseModalButton, InvisibleButton } from "buttons"; -import { BackButton, BackButtonArea } from "../../helpers"; import styles from "./ProcessUnmanagedTickets.module.css"; import { VSPSelect } from "inputs"; @@ -43,13 +40,6 @@ export default ({ return (
- - {!isProcessingManaged && ( - }> - - - )} -
{description}
{!noVspSelection && ( diff --git a/app/components/views/GetStartedPage/SetupWallet/ProcessUnmanagedTickets/ProcessUnmanagedTickets.jsx b/app/components/views/GetStartedPage/SetupWallet/ProcessUnmanagedTickets/ProcessUnmanagedTickets.jsx index 2f98b1ad92..9706ef6c7d 100644 --- a/app/components/views/GetStartedPage/SetupWallet/ProcessUnmanagedTickets/ProcessUnmanagedTickets.jsx +++ b/app/components/views/GetStartedPage/SetupWallet/ProcessUnmanagedTickets/ProcessUnmanagedTickets.jsx @@ -1,11 +1,8 @@ import { useState, useEffect } from "react"; -import { Tooltip } from "pi-ui"; import { Subtitle } from "shared"; -import { GoBackMsg } from "../../messages"; import { FormattedMessage as T } from "react-intl"; import { PassphraseModalButton, InvisibleButton } from "buttons"; import styles from "./ProcessUnmanagedTickets.module.css"; -import { BackButton, BackButtonArea } from "../../helpers"; import { VSPSelect } from "inputs"; export default ({ @@ -42,13 +39,6 @@ export default ({ return (
- - {isProcessingUnmanaged && ( - }> - - - )} -
{description}
{!noVspSelection && ( diff --git a/app/components/views/GetStartedPage/SetupWallet/SetMixedAcctPage/SetMixedAcctPage.jsx b/app/components/views/GetStartedPage/SetupWallet/SetMixedAcctPage/SetMixedAcctPage.jsx index f45dd13288..b44dd91f6c 100644 --- a/app/components/views/GetStartedPage/SetupWallet/SetMixedAcctPage/SetMixedAcctPage.jsx +++ b/app/components/views/GetStartedPage/SetupWallet/SetMixedAcctPage/SetMixedAcctPage.jsx @@ -1,15 +1,13 @@ import { useState, useEffect } from "react"; import { FormattedMessage as T } from "react-intl"; -import { classNames, Checkbox, Tooltip } from "pi-ui"; +import { classNames, Checkbox } from "pi-ui"; import { Subtitle } from "shared"; import { KeyBlueButton } from "buttons"; import { MIXED_ACCOUNT, CHANGE_ACCOUNT } from "constants"; -import { GoBackMsg } from "../../messages"; import { useDaemonStartup, useMountEffect, useAccounts } from "hooks"; -import { BackButton, BackButtonArea } from "../../helpers"; import styles from "./SetMixedAcctPage.module.css"; -export default ({ cancel, onSendContinue }) => { +export default ({ onSendContinue }) => { const { getCoinjoinOutputspByAcct, setCoinjoinCfg } = useDaemonStartup(); const { onRenameAccount } = useAccounts(); const [coinjoinSumByAcct, setCjSumByAcct] = useState(null); @@ -58,11 +56,6 @@ export default ({ cancel, onSendContinue }) => { return (
- - }> - - - } diff --git a/app/components/views/GetStartedPage/SetupWallet/SetupWallet.jsx b/app/components/views/GetStartedPage/SetupWallet/SetupWallet.jsx index 434ec6c938..0466840147 100644 --- a/app/components/views/GetStartedPage/SetupWallet/SetupWallet.jsx +++ b/app/components/views/GetStartedPage/SetupWallet/SetupWallet.jsx @@ -4,14 +4,13 @@ import { useEffect } from "react"; import { useWalletSetup } from "./hooks"; import { FormattedMessage as T } from "react-intl"; import { AnimatedLinearProgressFull } from "indicators"; -import { Header } from "../helpers"; import styles from "./SetupWallet.module.css"; +import { LoaderBarContainer } from "../helpers"; const SetupWallet = ({ - settingUpWalletRef, - appVersion, - onShowTutorial, - onShowReleaseNotes + NavlinkComponent, + LoadingPageComponent, + settingUpWalletRef }) => { const { getStateComponent, StateComponent } = useWalletSetup( settingUpWalletRef @@ -23,22 +22,26 @@ const SetupWallet = ({ return (
- {StateComponent && React.isValidElement(StateComponent) ? ( - StateComponent - ) : ( - <> -
-
- , - animationType: styles.setupWallet, - hideTextBlock: true - }} - /> -
- - )} + {NavlinkComponent && React.isValidElement(NavlinkComponent) + ? NavlinkComponent + : StateComponent && React.isValidElement(StateComponent) + ? StateComponent + : LoadingPageComponent && + React.isValidElement(LoadingPageComponent) && + LoadingPageComponent} + , + animationType: styles.setupWallet, + hideTextBlock: true, + hideOpenWalletButton: true + }} + /> + } + />
); }; diff --git a/app/components/views/GetStartedPage/SetupWallet/SetupWallet.module.css b/app/components/views/GetStartedPage/SetupWallet/SetupWallet.module.css index b375606947..cc500e70e2 100644 --- a/app/components/views/GetStartedPage/SetupWallet/SetupWallet.module.css +++ b/app/components/views/GetStartedPage/SetupWallet/SetupWallet.module.css @@ -1,21 +1,6 @@ .loaderBar { - float: left; - width: 100%; - margin-bottom: 20px; + height: 6rem; } .setupWallet { - padding-left: 56px; background-image: var(--loader-animation-finalizing-setup) !important; - background-position: 15px 15px; - background-size: 30px; -} -@media (--sm-viewport) { - .loaderBar { - margin-bottom: 0; - position: fixed; - bottom: 0; - left: 0; - display: flex; - flex-direction: column; - } } diff --git a/app/components/views/GetStartedPage/SetupWallet/hooks.js b/app/components/views/GetStartedPage/SetupWallet/hooks.js index a5e92ff9ff..35ee1e5e60 100644 --- a/app/components/views/GetStartedPage/SetupWallet/hooks.js +++ b/app/components/views/GetStartedPage/SetupWallet/hooks.js @@ -185,7 +185,6 @@ export const useWalletSetup = (settingUpWalletRef) => { sendContinue(); } else { component = h(SettingMixedAccount, { - cancel: sendContinue, onSendContinue: sendContinue }); } diff --git a/app/components/views/GetStartedPage/TutorialPage/TutorialPage.jsx b/app/components/views/GetStartedPage/TutorialPage/TutorialPage.jsx index 7271d9f38c..8bb8775e01 100644 --- a/app/components/views/GetStartedPage/TutorialPage/TutorialPage.jsx +++ b/app/components/views/GetStartedPage/TutorialPage/TutorialPage.jsx @@ -2,7 +2,7 @@ import { useState, useCallback } from "react"; import TutorialPage from "./Page"; import { useDaemonStartup } from "hooks"; -const Tutorial = () => { +const Tutorial = ({ onSendBack }) => { const { finishTutorial } = useDaemonStartup(); const [tutorialStep, setTutorialStep] = useState(0); @@ -18,7 +18,7 @@ const Tutorial = () => { tutorialStep, onNextTutorialStep, onGoToStep: setTutorialStep, - finishTutorial + finishTutorial: onSendBack ?? finishTutorial }} /> ); diff --git a/app/components/views/GetStartedPage/WalletSelection/Form/Form.jsx b/app/components/views/GetStartedPage/WalletSelection/Form/Form.jsx index a5b7bfca7c..efa572cef8 100644 --- a/app/components/views/GetStartedPage/WalletSelection/Form/Form.jsx +++ b/app/components/views/GetStartedPage/WalletSelection/Form/Form.jsx @@ -1,190 +1,293 @@ import { FormattedMessage as T } from "react-intl"; -import { classNames, Tooltip } from "pi-ui"; +import { useIntl } from "react-intl"; +import { + classNames, + Tooltip, + Icon, + useTheme, + getThemeProperty, + ButtonIcon +} from "pi-ui"; import { RemoveWalletButton } from "buttons"; -import { FormattedRelative } from "shared"; -import { NewSeedTabMsg, RestoreTabMsg } from "../../messages"; -import { FormContainer, Row } from "../../helpers"; +import { FormattedRelative, Subtitle } from "shared"; +import { FormContainer, ContentContainer /* , Row */ } from "../../helpers"; import styles from "./Form.module.css"; - -const CreateRestoreButtons = ({ showCreateWalletForm }) => ( - <> -
showCreateWalletForm(true)}> -
-
- -
-
-
showCreateWalletForm(false)}> -
-
- -
-
- -); - -const WalletTypeLabel = ({ isWatchingOnly, finished, isTrezor, isPrivacy }) => { - if (isPrivacy) return ; - if (isTrezor) return ; - if (isWatchingOnly) - return ; - if (!finished) - return ; - return null; -}; +import { + TutorialOverview, + tutorials +} from "../../../SettingsPage/TutorialsTab/helpers"; +import { + LoaderTitleMsg, + LoaderTitleMsgChooseTheWalletToAccess, + messages +} from "../../messages"; const WalletSelectionForm = ({ availableWallets, showCreateWalletForm, onRemoveWallet, - selectedWallet, - onChangeAvailableWallets, onToggleEditWallet, editWallets, - submitChosenWallet -}) => ( -
- - - {availableWallets.map((wallet) => { - const selected = - selectedWallet && - selectedWallet.value.wallet === wallet.value.wallet && - wallet.network === selectedWallet.network; - return ( -
onChangeAvailableWallets(wallet) : null - }> - {editWallets && ( -
- - }> - - {wallet.value.wallet} - - ) - }} - /> - } - modalContent={ - - } - onSubmit={() => onRemoveWallet(wallet)} - /> - -
- )} -
- -
-
-
- {wallet.value.wallet} -
-
- {wallet.lastAccess && ( + submitChosenWallet, + onShowOnboardingTutorial +}) => { + const { theme } = useTheme(); + const intl = useIntl(); + const trezorIconColor = getThemeProperty(theme, "light-blue"); + const accentBlue = getThemeProperty(theme, "accent-blue"); + const green = getThemeProperty(theme, "green-2"); + const lightGreen = getThemeProperty(theme, "light-green"); + const closeButtonColor = getThemeProperty(theme, "background-back-color"); + + const CreateButton = (props) => ( + showCreateWalletForm(true)} + text={intl.formatMessage(messages.newSeedTabMsg)} + iconColor={accentBlue} + {...props} + /> + ); + + const RestoreButton = (props) => ( + showCreateWalletForm(false)} + text={intl.formatMessage(messages.restoreTabMsg)} + iconColor={green} + iconBackgroundColor={lightGreen} + {...props} + /> + ); + + const TrezorButton = (props) => ( + { + /* TODO */ + }} + text={intl.formatMessage(messages.trezorTabMsg)} + iconColor={trezorIconColor} + {...props} + /> + ); + + return ( +
+ +
+ , +
+
+ +
+
+ + +
+ {availableWallets.length > 0 ? ( + <> +
+ {editWallets ? ( + + ) : ( <> - :{" "} - + + + )}
- {!editWallets && selected && ( - <> + {availableWallets.map((wallet) => { + return (
submitChosenWallet({ selectedWallet })}> - + className={styles.displayWallet} + key={wallet.label} + onClick={ + !editWallets + ? () => submitChosenWallet({ selectedWallet: wallet }) + : null + }> +
+ +
+ {wallet.value.wallet} +
+
+ {editWallets ? ( +
+ + }> + + {wallet.value.wallet} + + ) + }} + /> + } + modalContent={ + + } + onSubmit={() => onRemoveWallet(wallet)} + /> + +
+ ) : ( + <> + {wallet.value.isPrivacy && ( +
+ + }> + + +
+ )} + {wallet.value.isLN && ( +
+ + }> + + +
+ )} + {wallet.value.isTrezor && ( +
+ + }> + + +
+ )} + {wallet.isWatchingOnly && ( +
+ + }> + + +
+ )} + + )} +
+
+ {!wallet.finished ? ( + + ) : ( + wallet.lastAccess && ( + <> + + :{" "} + + + ) + )} +
- - - )} -
- ); - })} - - {editWallets ? ( - }> -
- - ) : ( - }> -
- - )} - - -
-); + ); + })} + + ) : ( + <> + + + + + )} +
+ + + + } + /> + {["decredIntro", "powPos", "lifecycle", "blocks"].map((name) => ( + + ))} +
+ ); +}; export default WalletSelectionForm; diff --git a/app/components/views/GetStartedPage/WalletSelection/Form/Form.module.css b/app/components/views/GetStartedPage/WalletSelection/Form/Form.module.css index 01409a7236..6f090c6050 100644 --- a/app/components/views/GetStartedPage/WalletSelection/Form/Form.module.css +++ b/app/components/views/GetStartedPage/WalletSelection/Form/Form.module.css @@ -1,51 +1,59 @@ +.container { + width: 106rem; +} + +.displayWalletContainer { + position: relative; + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 2rem; + width: 106rem; +} + .displayWallet { - margin: 5px 10px 5px 0px; - float: left; - height: 161px; - width: 168px; - border-radius: 5px; - border: 1px solid var(--background-container); - background: var(--display-wallet-bg); + padding: 1.6rem 1rem 1.6rem 2rem; + height: 7.6rem; + border-radius: 0.5rem; + background-color: var(--background-back-color); font-size: 15px; + box-shadow: 0px 2px 8px var(--icons-shadow); + + display: grid; + grid-template-columns: min-content auto min-content; + grid-template-rows: repeat(2, 1fr); + position: relative; } .displayWallet:hover { cursor: pointer; + box-shadow: 0px 2px 8px var(--icons-shadow-hover); } -.displayWallet.new { - background: none; - background-color: var(--background-back-color); +.walletIcon { + grid-row: 1/3; + align-self: center; + margin-right: 2rem; } -.displayWallet.new .displayWalletName { - color: var(--new-wallet-label); - margin-top: 20px; +.walletTypeIcons { + height: 2.1rem; } -.walletIcon { - margin-left: 54px; - height: 62px; - width: 62px; - background-repeat: no-repeat; - background-size: 45px 45px; - background-position: 8px 10px; +.walletTypeIcons > div { + margin-right: 1rem; } -.displayWalletButtons { - text-align: center; - margin-top: 5px; - margin-right: 10px; - float: right; +.walletTypeIcons > div:last-of-type { + margin: 0; } .displayWalletButton { - height: 20px; - width: 20px; border-radius: 3px; background-repeat: no-repeat; background-size: 14px; background-position: 50% 50%; + width: 2.1rem; + height: 2.1rem; } .displayWalletButton.remove { @@ -61,24 +69,6 @@ box-shadow: 0px 1px 3px var(--title-text-and-button-background-drop-shadow); } -.displayWallet:hover:not(.selected) { - border: 1px solid var(--disabled-color); -} - -.displayWallet.selected { - background: linear-gradient( - 45deg, - var(--input-color), - var(--display-wallet-gradient-selected-right) - ); - box-shadow: 0px 5px 21px var(--title-text-and-button-background-drop-shadow); - border: 1px solid var(--input-color); -} - -.displayWallet.selected .displayWalletName { - color: var(--selected_wallet-label); -} - .displayWalletComplete { color: var(--title-text-and-button-background); margin-top: 5px; @@ -89,15 +79,16 @@ } .displayWalletName { - color: var(--wallet-label); - text-align: center; + font-size: 1.9rem; + line-height: 2.4rem; + color: var(--main-dark-blue); } .displayWalletLastAccess { - height: 11px; - color: var(--button-text); - text-align: center; - font-size: 11px; + font-size: 1.3rem; + line-height: 1.6rem; + color: var(--main-dark-blue); + grid-column: 2/4; } .displayWalletCancelChanges { @@ -132,50 +123,49 @@ color: var(--wallet-desc); } -.walletIcon.wallet { - background-image: var(--wallet-gray-icon); +.close { + background-color: var(--disabled-color) !important; + color: var(--background-back-color) !important; } -.walletIcon.selected { - background-image: var(--wallet-blue-icon); +.gradient { + position: absolute; + height: 100%; + width: 0.7rem; + top: 0; + left: 0; + border-radius: 0.5rem 0 0 0.5rem; } -.walletIcon.createnew { - margin-top: 25px; - background-size: 58px 58px; - background-position: 0px 5px; - background-image: var(--create-wallet-icon); +.buttons { + position: absolute; + right: 0; + top: -5.5rem; } -.walletIcon.restore { - margin-top: 25px; - background-size: 58px 58px; - background-position: 0px 5px; - background-image: var(--restore-wallet-icon); +.buttons > button { + margin-left: 1rem; } -.editWalletsButton { - margin: 5px; - float: left; - height: 36px; - width: 36px; - border-radius: 5px; - background-color: var(--background-back-color); - background-repeat: no-repeat; - background-size: 20px 20px; - background-position: 50% 50%; - background-image: var(--launcher-edit-wallets); - cursor: pointer; +.largeButtonIcon { + height: 5.2rem !important; + width: auto !important; +} + +.largeButtonIcon svg { + width: 2.1rem; + height: 2.1rem; } -.editWalletsButton:hover { - background-image: var(--launcher-edit-wallets-hover); +.largeButtonIcon span { + font-size: 1.9rem !important; + line-height: 2.4rem !important; + display: inline !important; + margin-left: 1.2rem !important; } -.editWalletsButton.close { - background-color: var(--disabled-color); - background-size: 12px 12px; - background-image: var(--x-white-icon); +.subtitle { + padding-top: 6rem; } @keyframes bounce { @@ -199,7 +189,31 @@ animation: bounce 1s var(--ease-in-out-quart) infinite; } +@media (--bg-viewport) { + .container, + .displayWalletContainer { + width: 63.4rem; + } + + .largeButtonIcon span { + font-size: 1.3rem !important; + } +} + @media (--sm-viewport) { + .container, + .displayWalletContainer { + width: 31.5rem; + } + + .displayWalletContainer { + grid-template-columns: 1fr; + } + + .largeButtonIcon span { + font-size: 1.9rem !important; + } + .editWalletsButton { margin: 5px 0; } diff --git a/app/components/views/GetStartedPage/WalletSelection/WalletSelection.jsx b/app/components/views/GetStartedPage/WalletSelection/WalletSelection.jsx index 27c610b955..057808c2e4 100644 --- a/app/components/views/GetStartedPage/WalletSelection/WalletSelection.jsx +++ b/app/components/views/GetStartedPage/WalletSelection/WalletSelection.jsx @@ -1,8 +1,12 @@ -import { useState, useCallback, useEffect } from "react"; +import { useState, useCallback } from "react"; import WalletSelectionForm from "./Form"; import { useDaemonStartup } from "hooks"; -const WalletSelectionBody = ({ submitChosenWallet, onSendCreateWallet }) => { +const WalletSelectionBody = ({ + submitChosenWallet, + onSendCreateWallet, + onShowOnboardingTutorial +}) => { const { isSPV, availableWallets, @@ -11,12 +15,6 @@ const WalletSelectionBody = ({ submitChosenWallet, onSendCreateWallet }) => { creatingWallet } = useDaemonStartup(); const [editWallets, setEditWallets] = useState(false); - const [selectedWallet, setSelectedWallet] = useState(null); - - useEffect(() => { - setSelectedWallet(availableWallets[0]); - }, [availableWallets]); - const onToggleEditWallet = useCallback(() => { setEditWallets(!editWallets); }, [editWallets]); @@ -28,15 +26,9 @@ const WalletSelectionBody = ({ submitChosenWallet, onSendCreateWallet }) => { [onSendCreateWallet] ); - const onChangeAvailableWallets = useCallback( - (selectedWallet) => setSelectedWallet(selectedWallet), - [setSelectedWallet] - ); - return ( { creatingWallet, onToggleEditWallet, showCreateWalletForm, - onChangeAvailableWallets + onShowOnboardingTutorial }} /> ); diff --git a/app/components/views/GetStartedPage/helpers/ContentContainer/ContentContainer.module.css b/app/components/views/GetStartedPage/helpers/ContentContainer/ContentContainer.module.css index 14177034ee..2ce5f2f3dc 100644 --- a/app/components/views/GetStartedPage/helpers/ContentContainer/ContentContainer.module.css +++ b/app/components/views/GetStartedPage/helpers/ContentContainer/ContentContainer.module.css @@ -1,9 +1,10 @@ .contentContainer { - font-size: 27px; - line-height: 34px; - margin-bottom: 13px; + margin-bottom: 3rem; width: 100%; - float: left; + font-size: 2.8rem; + font-weight: 400; + line-height: 3.5rem; + color: var(--grey-7); } @media (--sm-viewport) { diff --git a/app/components/views/GetStartedPage/helpers/Header/Header.jsx b/app/components/views/GetStartedPage/helpers/Header/Header.jsx deleted file mode 100644 index 40771cba4c..0000000000 --- a/app/components/views/GetStartedPage/helpers/Header/Header.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import styles from "./Header.module.css"; -import ContentContainer from "../ContentContainer"; -import { SlateGrayButton } from "buttons"; -import { LearnBasicsMsg, WhatsNewLink, LoaderTitleMsg } from "../../messages"; - -const Header = ({ appVersion, onShowTutorial, onShowReleaseNotes }) => ( - <> - - - -
- - - - -
- -); -export default Header; diff --git a/app/components/views/GetStartedPage/helpers/Header/Header.module.css b/app/components/views/GetStartedPage/helpers/Header/Header.module.css deleted file mode 100644 index 6c6a7b1562..0000000000 --- a/app/components/views/GetStartedPage/helpers/Header/Header.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.loaderButtons { - float: left; - margin-bottom: 90px; - width: 100%; -} -.tutorialButton { - background-color: var(--info-modal-button-bg); - color: var(--back-button-dark-text); -} -.tutorialButton:hover { - background-color: var(--title-text-and-button-background-hovered); -} -@media (--sm-viewport) { - .loaderButtons { - margin-bottom: 50px; - } -} diff --git a/app/components/views/GetStartedPage/helpers/Header/index.js b/app/components/views/GetStartedPage/helpers/Header/index.js deleted file mode 100644 index 2764567d96..0000000000 --- a/app/components/views/GetStartedPage/helpers/Header/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./Header"; diff --git a/app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.jsx b/app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.jsx new file mode 100644 index 0000000000..63dd0d8b46 --- /dev/null +++ b/app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.jsx @@ -0,0 +1,10 @@ +import styles from "./LoaderBarContainer.module.css"; +import { classNames } from "pi-ui"; + +const LoaderBarContainer = ({ loaderBar, className }) => ( +
+
{loaderBar}
+
+); + +export default LoaderBarContainer; diff --git a/app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.module.css b/app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.module.css new file mode 100644 index 0000000000..035fdfaa4c --- /dev/null +++ b/app/components/views/GetStartedPage/helpers/LoaderBarContainer/LoaderBarContainer.module.css @@ -0,0 +1,7 @@ +.loaderBarContainer { + position: fixed; + bottom: 0; + left: 0; + right: 0; + box-shadow: 0px -4px 8px rgba(0, 0, 0, 0.1); +} diff --git a/app/components/views/GetStartedPage/helpers/LoaderBarContainer/index.js b/app/components/views/GetStartedPage/helpers/LoaderBarContainer/index.js new file mode 100644 index 0000000000..c4269aef3e --- /dev/null +++ b/app/components/views/GetStartedPage/helpers/LoaderBarContainer/index.js @@ -0,0 +1 @@ +export { default } from "./LoaderBarContainer"; diff --git a/app/components/views/GetStartedPage/helpers/index.js b/app/components/views/GetStartedPage/helpers/index.js index 5b216269f3..fcaf596ce2 100644 --- a/app/components/views/GetStartedPage/helpers/index.js +++ b/app/components/views/GetStartedPage/helpers/index.js @@ -9,4 +9,4 @@ export { default as Content } from "./Content"; export { default as Title } from "./Title"; export { default as SubTitle } from "./SubTitle"; export { default as ContentContainer } from "./ContentContainer"; -export { default as Header } from "./Header"; +export { default as LoaderBarContainer } from "./LoaderBarContainer"; diff --git a/app/components/views/GetStartedPage/hooks.js b/app/components/views/GetStartedPage/hooks.js index becb79129a..8901e0756e 100644 --- a/app/components/views/GetStartedPage/hooks.js +++ b/app/components/views/GetStartedPage/hooks.js @@ -8,10 +8,11 @@ import { createElement as h } from "react"; import GetStartedMachinePage from "./GetStartedMachinePage"; import TrezorConfig from "./TrezorConfig/TrezorConfig"; import PreCreateWalletForm from "./PreCreateWallet/PreCreateWallet"; -import RescanWalletBody from "./RescanWallet/RescanWallet"; import WalletPubpassInput from "./OpenWallet/OpenWallet"; import DiscoverAccounts from "./OpenWallet/DiscoverAccounts"; import ReleaseNotes from "./ReleaseNotes/ReleaseNotes"; +import OnboardingTutorialPage from "./OnboardingTutorialPage"; +import LoadingPage from "./LoadingPage"; import { OPENWALLET_INPUT, OPENWALLET_INPUTPRIVPASS @@ -21,9 +22,11 @@ import { useDaemonStartup } from "hooks"; import { useMachine } from "@xstate/react"; import { getStartedMachine } from "stateMachines/GetStartedStateMachine"; import { AdvancedStartupBody } from "./AdvancedStartup/AdvancedStartup"; +import { TutorialPage } from "components/views/GetStartedPage"; import styles from "./GetStarted.module.css"; import { isObject } from "lodash"; import { wallet } from "wallet-preload-shim"; +import { LoaderBarContainer } from "./helpers"; export const useGetStarted = () => { const { @@ -47,16 +50,26 @@ export const useGetStarted = () => { checkNetworkMatch, onConnectDaemon, onStartWallet, + onCloseWallet, syncDaemon, onOpenWallet, - onShowTutorial, appVersion, syncAttemptRequest, onGetDcrdLogs, - daemonWarning + daemonWarning, + stopUnfinishedWallet, + checkDisplayWalletGradients, + setAutoWalletLaunching, + autoWalletLaunching } = useDaemonStartup(); const [PageComponent, setPageComponent] = useState(null); const [showNavLinks, setShowNavLinks] = useState(true); + const [NavlinkComponent, setNavlinkComponent] = useState(null); + const [ + nextStateAfterWalletLoading, + setNextStateAfterWalletLoading + ] = useState(null); + const [state, send] = useMachine(getStartedMachine, { actions: { isAtPreStart: () => { @@ -104,8 +117,8 @@ export const useGetStarted = () => { .catch((error) => { if ( !error.connected && - error.error.includes && - error.error.includes("SSLV3_ALERT_HANDSHAKE_FAILURE") + error.error?.includes && + error.error?.includes("SSLV3_ALERT_HANDSHAKE_FAILURE") ) { error = ( { return; } onGetAvailableWallets() - .then((w) => send({ type: "CHOOSE_WALLET", payload: { w } })) + .then((w) => { + checkDisplayWalletGradients(w.availableWallets); + send({ type: "CHOOSE_WALLET", payload: { w } }); + }) .catch((error) => send({ type: "AVAILABLE_WALLET_ERROR", error })); setShowNavLinks(true); @@ -194,6 +210,7 @@ export const useGetStarted = () => { }); }, isSyncingRPC: async (context) => { + setNextStateAfterWalletLoading(null); const { passPhrase, isSPV } = context; if (syncAttemptRequest) { return; @@ -202,17 +219,20 @@ export const useGetStarted = () => { // if synced, it means that the wallet is finished to sync and we can // push decrediton to home view. if (synced === true) { - send({ type: "SHOW_SETTING_UP_WALLET" }); + setNextStateAfterWalletLoading({ type: "SHOW_SETTING_UP_WALLET" }); } if (isSPV) { return startSPVSync(passPhrase) - .then(() => send({ type: "SHOW_SETTING_UP_WALLET" })) + .then(() => { + onNextStateAfterWalletLoading({ type: "SHOW_SETTING_UP_WALLET" }); + }) .catch((error) => { // If the error is OPENWALLET_INPUTPRIVPASS, the wallet needs the // private passphrase to discover accounts and the user typed a wrong // one. if (error == OPENWALLET_INPUTPRIVPASS) { send({ type: "WALLET_DISCOVERACCOUNTS_PASS" }); + return; } send({ type: "ERROR_SYNCING_WALLET", payload: { error } }); }); @@ -225,15 +245,34 @@ export const useGetStarted = () => { send({ type: "WALLET_DISCOVERACCOUNTS_PASS" }); return; } + if (error.includes("wallet is loaded")) { + onNextStateAfterWalletLoading({ type: "SHOW_SETTING_UP_WALLET" }); + return; + } throw error; } - send({ type: "SHOW_SETTING_UP_WALLET" }); + onNextStateAfterWalletLoading({ type: "SHOW_SETTING_UP_WALLET" }); } catch (error) { send({ type: "ERROR_SYNCING_WALLET", payload: { error } }); } } } }); + + const onNextStateAfterWalletLoading = useCallback( + (nextState) => { + if (autoWalletLaunching) { + send({ + type: "SHOW_SETTING_UP_WALLET" + }); + setNextStateAfterWalletLoading(null); + } else { + setNextStateAfterWalletLoading(nextState); + } + }, + [setNextStateAfterWalletLoading, autoWalletLaunching, send] + ); + const getError = useCallback((serviceError) => { if (!serviceError) return; @@ -350,6 +389,27 @@ export const useGetStarted = () => { [send] ); + const onCancelLoadingWallet = useCallback( + () => onCloseWallet().then(() => send({ type: "CANCEL_SYNCING_WALLET" })), + [send, onCloseWallet] + ); + + const onContinueOpeningWallet = useCallback(() => { + const nextState = nextStateAfterWalletLoading ?? { + type: "SHOW_SETTING_UP_WALLET" + }; + send(nextState); + setNextStateAfterWalletLoading(null); + }, [send, setNextStateAfterWalletLoading, nextStateAfterWalletLoading]); + + const onSaveAndContinueOpeningWallet = useCallback( + (autoOpeningWallet) => { + setAutoWalletLaunching(autoOpeningWallet); + onContinueOpeningWallet(); + }, + [onContinueOpeningWallet, setAutoWalletLaunching] + ); + const onShowCreateWallet = useCallback( ({ isNew, walletMasterPubKey, isTrezor }) => send({ @@ -361,9 +421,47 @@ export const useGetStarted = () => { [send] ); + const onShowSettings = useCallback( + () => + setNavlinkComponent( + h(Settings, { onSendBack: () => setNavlinkComponent(null) }) + ), + [setNavlinkComponent] + ); + + const onShowLogs = useCallback( + () => + setNavlinkComponent( + h(Logs, { onSendBack: () => setNavlinkComponent(null) }) + ), + [setNavlinkComponent] + ); + const onShowReleaseNotes = useCallback( - () => send({ type: "SHOW_RELEASE_NOTES" }), - [send] + () => + setNavlinkComponent( + h(ReleaseNotes, { onSendBack: () => setNavlinkComponent(null) }) + ), + [setNavlinkComponent] + ); + + const onShowTutorial = useCallback( + () => + setNavlinkComponent( + h(TutorialPage, { onSendBack: () => setNavlinkComponent(null) }) + ), + [setNavlinkComponent] + ); + + const onShowOnboardingTutorial = useCallback( + (currentOnboardingTutorial) => + setNavlinkComponent( + h(OnboardingTutorialPage, { + goBackHistory: () => setNavlinkComponent(null), + currentTutorial: currentOnboardingTutorial + }) + ), + [setNavlinkComponent] ); const submitChosenWallet = useCallback( @@ -392,7 +490,7 @@ export const useGetStarted = () => { ); const getStateComponent = useCallback( - (updatedText, updatedAnimationType, updatedComponent) => { + (updatedText, updatedAnimationType) => { const { isCreateNewWallet, isSPV, @@ -402,6 +500,8 @@ export const useGetStarted = () => { let component, text, animationType, PageComponent; const key = Object.keys(state.value)[0]; + const loaderBarContainer = LoaderBarContainer; + let showLoaderBar = true; if (key === "startMachine") { switch (state.value[key]) { case "startAdvancedDaemon": @@ -414,17 +514,15 @@ export const useGetStarted = () => { }} /> ); - text = ( - - ); + showLoaderBar = false; break; case "connectingDaemon": text = ( - + ); + component = h(LoadingPage, { + onShowOnboardingTutorial + }); break; case "checkingNetworkMatch": text = ( @@ -433,39 +531,34 @@ export const useGetStarted = () => { m="Checking if network matches..." /> ); + component = h(LoadingPage, { + onShowOnboardingTutorial + }); break; case "startingDaemon": animationType = styles.daemonWaiting; text = ; + component = h(LoadingPage, { + onShowOnboardingTutorial + }); break; case "syncingDaemon": animationType = styles.blockchainSyncing; text = ; + component = h(LoadingPage, { + onShowOnboardingTutorial + }); break; case "choosingWallet": - text = isSPV ? ( - - ) : ( - - ); + showLoaderBar = false; component = h(WalletSelection, { onSendCreateWallet, submitChosenWallet, - isSPV + isSPV, + onShowOnboardingTutorial }); break; case "preCreateWallet": - text = isCreateNewWallet ? ( - - ) : ( - - ); component = h(PreCreateWalletForm, { onShowCreateWallet, onSendContinue, @@ -475,6 +568,7 @@ export const useGetStarted = () => { isCreateNewWallet, error }); + showLoaderBar = false; break; case "walletPubpassInput": text = ; @@ -500,23 +594,26 @@ export const useGetStarted = () => { break; case "startingWallet": text = ; + component = h(LoadingPage, { + onShowOnboardingTutorial + }); break; case "syncingRPC": animationType = styles.establishingRpc; text = ( ); + component = h(LoadingPage, { + onShowOnboardingTutorial + }); break; } + PageComponent = h(GetStartedMachinePage, { submitRemoteCredentials, submitAppdata, error, availableWalletsError, - isSPV, - onShowReleaseNotes, - onShowTutorial, - appVersion, onGetDcrdLogs, daemonWarning, @@ -525,21 +622,19 @@ export const useGetStarted = () => { animationType: updatedAnimationType ? updatedAnimationType : animationType, - StateComponent: updatedComponent ? updatedComponent : component + StateComponent: NavlinkComponent ?? component, + loaderBarContainer, + showLoaderBar, + onCancelLoadingWallet, + onContinueOpeningWallet, + onSaveAndContinueOpeningWallet, + nextStateAfterWalletLoading }); } - if (key === "settings") { - PageComponent = h(Settings, { onSendBack }); - } - if (key === "logs") { - PageComponent = h(Logs, { onSendBack }); - } + if (key === "trezorConfig") { PageComponent = h(TrezorConfig, { onSendBack }); } - if (key === "releaseNotes") { - PageComponent = h(ReleaseNotes, { onSendBack }); - } if (key === "creatingWallet") { PageComponent = h(CreateWalletMachine, { createWalletRef, @@ -552,7 +647,11 @@ export const useGetStarted = () => { settingUpWalletRef, appVersion, onShowTutorial, - onShowReleaseNotes + onShowReleaseNotes, + NavlinkComponent: NavlinkComponent, + LoadingPageComponent: h(LoadingPage, { + onShowOnboardingTutorial + }) }); } @@ -579,13 +678,19 @@ export const useGetStarted = () => { onSendSetPassphrase, error, availableWalletsError, - daemonWarning + daemonWarning, + onShowOnboardingTutorial, + NavlinkComponent, + nextStateAfterWalletLoading, + onCancelLoadingWallet, + onContinueOpeningWallet, + onSaveAndContinueOpeningWallet ] ); const machineStateValue = state && state.value; useEffect(() => { - let text, animationType, component; + let text, animationType; if (syncFetchMissingCfiltersAttempt) { animationType = styles.daemonWaiting; text = ( @@ -618,7 +723,6 @@ export const useGetStarted = () => { m="Scanning blocks for transactions" /> ); - component = RescanWalletBody; } else if (synced) { animationType = styles.finalizingSetup; text = ( @@ -628,7 +732,7 @@ export const useGetStarted = () => { /> ); } - getStateComponent(text, animationType, component); + getStateComponent(text, animationType); }, [ syncFetchMissingCfiltersAttempt, syncFetchHeadersAttempt, @@ -639,18 +743,14 @@ export const useGetStarted = () => { machineStateValue ]); - const onShowSettings = useCallback(() => send({ type: "SHOW_SETTINGS" }), [ - send - ]); - - const onShowLogs = useCallback(() => send({ type: "SHOW_LOGS" }), [send]); - return { onShowLogs, onShowSettings, updateAvailable, isTestNet, PageComponent, - showNavLinks + showNavLinks, + onShowTutorial, + onShowReleaseNotes }; }; diff --git a/app/components/views/GetStartedPage/messages/messages.jsx b/app/components/views/GetStartedPage/messages/messages.jsx index 2d190d9a09..df9a250106 100644 --- a/app/components/views/GetStartedPage/messages/messages.jsx +++ b/app/components/views/GetStartedPage/messages/messages.jsx @@ -24,7 +24,10 @@ export const DiscoverLabelMsg = () => ( ); export const LoaderTitleMsg = () => ( - + +); +export const LoaderTitleMsgChooseTheWalletToAccess = () => ( + ); export const DiscoverAccountsInfoMsg = () => ( ( export const LearnBasicsMsg = () => ( ); -export const NewSeedTabMsg = () => ( - -); -export const RestoreTabMsg = () => ( - +export const ReleaseInfoMsg = () => ( + ); export const CreateWalletMsg = () => ( @@ -68,6 +68,66 @@ export const messages = defineMessages({ confirmSeedEnterAllWordsError: { id: "getStarted.confirmSeed.enterAllWords", defaultMessage: "*Please enter all words" + }, + newSeedTabMsg: { + id: "getStarted.newSeedTab", + defaultMessage: "Create a New Wallet" + }, + restoreTabMsg: { + id: "getStarted.restore", + defaultMessage: "Restore Existing Wallet" + }, + trezorTabMsg: { + id: "getStarted.trezor", + defaultMessage: "Setup a Trezor Wallet" + }, + closeEditWallets: { + id: "getStarted.closeEditWallets", + defaultMessage: "Close" + }, + editWallets: { + id: "getStarted.editWallets", + defaultMessage: "Edit Wallets" + }, + messageWalletNamePlaceholder: { + id: "createwallet.walletname.placehlder", + defaultMessage: "Choose a Name" + }, + messageWalletNameTooltip: { + id: "createwallet.walletname.tooltip", + defaultMessage: + "The name is used to identify your wallet. Restoring a wallet does not require the name to match the previous wallet name." + }, + messageWalletWatchOnlyDescription: { + id: "createwallet.watchonly.description", + defaultMessage: + "A watch-only wallet has limited functionality. It can only be used to view the balance and monitor transaction history. You won't be able to spend any DCR associated with this wallet." + }, + messageWalletTrezorDescription: { + id: "createwallet.trezor.description", + defaultMessage: + "Trezor is a hardware wallet. For more information, visit {link}" + }, + messageWalletMasterPubKey: { + id: "createwallet.walletpubkey.placeholder", + defaultMessage: "Master Pub Key" + }, + messageWalletMasterPubkeyError: { + id: "createwallet.walletWatchOnly.error", + defaultMessage: "Invalid Master Pubkey" + }, + messageWalletDupeNameError: { + id: "createwallet.dupeWalletName.error", + defaultMessage: "Please choose an unused wallet name" + }, + messageDisablecointypeupgrades: { + id: "createwallet.disablecointypeupgrades.description", + defaultMessage: "Never upgrade from legacy to SLIP0044 coin type keys" + }, + messageGapLimit: { + id: "createwallet.gaplimit.description", + defaultMessage: + "Allowed unused address gap between used addresses of accounts" } }); diff --git a/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.jsx b/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.jsx index 8991d6b254..664d96a396 100644 --- a/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.jsx +++ b/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.jsx @@ -2,6 +2,7 @@ import { FormattedMessage as T } from "react-intl"; import { Subtitle } from "shared"; import { TutorialOverview, TutorialPage, tutorials } from "./helpers"; import { useTutorialsTab } from "./hooks"; +import styles from "./TutorialsTab.module.css"; const TutorialsTab = () => { const { @@ -35,7 +36,7 @@ const TutorialsTab = () => { }} /> ) : ( - <> +
} /> @@ -62,7 +63,7 @@ const TutorialsTab = () => { }} /> ))} - +
); }; diff --git a/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.module.css b/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.module.css new file mode 100644 index 0000000000..bbb2d4fdc5 --- /dev/null +++ b/app/components/views/SettingsPage/TutorialsTab/TutorialsTab.module.css @@ -0,0 +1,15 @@ +.container { + width: 72.4rem; +} + +@media screen and (max-width: 1180px) { + .container { + width: 63.4rem; + } +} + +@media screen and (max-width: 768px) { + .container { + width: 31.5rem; + } +} diff --git a/app/components/views/SettingsPage/TutorialsTab/helpers/PagedTutorial/PagedTutorial.jsx b/app/components/views/SettingsPage/TutorialsTab/helpers/PagedTutorial/PagedTutorial.jsx index c40e7a3709..b75925b565 100644 --- a/app/components/views/SettingsPage/TutorialsTab/helpers/PagedTutorial/PagedTutorial.jsx +++ b/app/components/views/SettingsPage/TutorialsTab/helpers/PagedTutorial/PagedTutorial.jsx @@ -13,6 +13,8 @@ const PagedTutorial = ({ setVisitedTabs, activeTabIndex, setActiveTabIndex, + className, + tabContentWrapperClassName onFinish }) => { useMountEffect(() => { @@ -65,7 +67,7 @@ const PagedTutorial = ({ const spaceEvenly = slides.length < 4; return ( -
+