diff --git a/src/renderer/components/deposit/add/SymDeposit.tsx b/src/renderer/components/deposit/add/SymDeposit.tsx index aa5d92686..27365b2c7 100644 --- a/src/renderer/components/deposit/add/SymDeposit.tsx +++ b/src/renderer/components/deposit/add/SymDeposit.tsx @@ -2304,7 +2304,7 @@ export const SymDeposit: React.FC = (props) => { () => (
= (props) => { () => (
void + onChangeMidgardUrl: (url: string) => void + onChangeMidgardMayaUrl: (url: string) => void + checkMidgardUrl$: CheckMidgardUrlHandler + checkMidgardMayaUrl$: CheckMidgardMayaUrlHandler + checkThornodeNodeUrl$: CheckThornodeNodeUrlHandler + checkMayanodeNodeUrl$: CheckMayanodeNodeUrlHandler + onChangeThornodeNodeUrl: (url: string) => void + onChangeMayanodeNodeUrl: (url: string) => void + checkThornodeRpcUrl$: CheckThornodeRpcUrlHandler + checkMayanodeRpcUrl$: CheckMayanodeRpcUrlHandler + onChangeThornodeRpcUrl: (url: string) => void + onChangeMayanodeRpcUrl: (url: string) => void +} + +type SubSectionProps = { + title: string + children?: React.ReactNode + className?: string +} + +const expertModeDefault: Record = { + thorchain: true, + mayachain: true +} + +const SubSection: React.FC = ({ title, className, children }) => ( +
+

{title}

+
{children}
+
+) + +const Section = ({ + title, + toggleHandler, + children +}: { + title: string + toggleHandler?: React.ReactNode + children?: React.ReactNode +}) => ( +
+
+

{title}

+ {toggleHandler} +
+ {children} +
+) + +export const AppExpertMode: React.FC = (props): JSX.Element => { + const { + togglePrivate, + isPrivate, + midgardUrl: midgardUrlRD, + midgardMayaUrl: midgardMayaUrlRD, + onChangeMidgardUrl, + onChangeMidgardMayaUrl, + checkMidgardUrl$, + checkMidgardMayaUrl$, + onChangeThornodeNodeUrl, + onChangeMayanodeNodeUrl, + checkThornodeNodeUrl$, + checkMayanodeNodeUrl$, + checkThornodeRpcUrl$, + checkMayanodeRpcUrl$, + onChangeThornodeRpcUrl, + onChangeMayanodeRpcUrl, + thornodeRpcUrl, + thornodeNodeUrl, + mayanodeNodeUrl, + mayanodeRpcUrl + } = props + + const intl = useIntl() + + const midgardUrl = useMemo(() => { + const empty = () => '' + return FP.pipe(midgardUrlRD, RD.fold(empty, empty, empty, FP.identity)) + }, [midgardUrlRD]) + const midgardMayaUrl = useMemo(() => { + const empty = () => '' + return FP.pipe(midgardMayaUrlRD, RD.fold(empty, empty, empty, FP.identity)) + }, [midgardMayaUrlRD]) + + const [advancedActive, setAdvancedActive] = useState>(() => { + const cachedValue = localStorage.getItem('advanceActive') + return cachedValue ? JSON.parse(cachedValue) : expertModeDefault + }) + useEffect(() => { + localStorage.setItem('openPanelKeys', JSON.stringify(advancedActive)) + }, [advancedActive]) + + return ( +
+
+ setAdvancedActive((prev) => ({ ...prev, thorchain: !prev.thorchain }))}> + {intl.formatMessage({ id: 'common.advanced' })} + + setAdvancedActive({ ...advancedActive, thorchain: active })}> + + {intl.formatMessage({ id: 'common.privateData' })} + + +
+ }> +
+ + + + + + + + + +
+ +
+ setAdvancedActive((prev) => ({ ...prev, mayachain: !prev.mayachain }))}> + {intl.formatMessage({ id: 'common.advanced' })} + + setAdvancedActive({ ...advancedActive, mayachain: active })}> + + {intl.formatMessage({ id: 'common.privateData' })} + + +
+ }> +
+ + + + + + + + + +
+ +
+ ) +} diff --git a/src/renderer/components/settings/AppGeneralSettings.tsx b/src/renderer/components/settings/AppGeneralSettings.tsx new file mode 100644 index 000000000..b94a76578 --- /dev/null +++ b/src/renderer/components/settings/AppGeneralSettings.tsx @@ -0,0 +1,313 @@ +import React, { useCallback, useMemo } from 'react' + +import * as RD from '@devexperts/remote-data-ts' +import { Network } from '@xchainjs/xchain-client' +import { MAYAChain } from '@xchainjs/xchain-mayachain' +import { THORChain } from '@xchainjs/xchain-thorchain' +import { Dropdown } from 'antd' +import { MenuProps } from 'antd/lib/menu' +import { ItemType } from 'antd/lib/menu/hooks/useItems' +import { clsx } from 'clsx' +import * as FP from 'fp-ts/function' +import * as A from 'fp-ts/lib/Array' +import * as O from 'fp-ts/lib/Option' +import { useIntl } from 'react-intl' + +import { Dex } from '../../../shared/api/types' +import { Locale } from '../../../shared/i18n/types' +import { LOCALES } from '../../i18n' +import { AVAILABLE_DEXS, AVAILABLE_NETWORKS } from '../../services/const' +import { DownIcon } from '../icons' +import { Menu } from '../shared/menu' +import { BorderButton } from '../uielements/button' +import * as Styled from './AppSettings.styles' + +export type Props = { + version: string + locale: Locale + changeLocale: (locale: Locale) => void + network: Network + dex: Dex + changeNetwork: (network: Network) => void + changeDex: (dex: Dex) => void + appUpdateState: RD.RemoteData> + checkForUpdates: FP.Lazy + goToReleasePage: (version: string) => void +} + +type SectionProps = { + title: string + subtitle: string + children?: React.ReactNode + className?: string +} + +const Section: React.FC = ({ title, subtitle, className, children }) => ( +
+
+

{title}

+ {subtitle} +
+
{children}
+
+) + +export const AppGeneralSettings: React.FC = (props): JSX.Element => { + const { + appUpdateState = RD.initial, + changeNetwork = FP.constVoid, + changeDex = FP.constVoid, + network, + dex, + checkForUpdates, + goToReleasePage = FP.constVoid, + version, + changeLocale, + locale + } = props + + const intl = useIntl() + + const changeLang: MenuProps['onClick'] = useCallback( + ({ key }: { key: string }) => { + changeLocale(key as Locale) + }, + [changeLocale] + ) + + const langMenu = useMemo( + () => ( + ((l: Locale) => ({ + label: ( +
+ {l} +
+ ), + key: l + })) + )} + /> + ), + [changeLang, locale] + ) + + const renderLangMenu = useMemo( + () => ( + +
+

{locale}

+ +
+
+ ), + [langMenu, locale] + ) + + const changeNetworkHandler: MenuProps['onClick'] = useCallback( + ({ key }: { key: string }) => { + changeNetwork(key as Network) + }, + [changeNetwork] + ) + const changeDexHandler: MenuProps['onClick'] = useCallback( + ({ key }: { key: string }) => { + const newDex = AVAILABLE_DEXS.find((dex) => dex.chain === key) + if (newDex) { + changeDex(newDex) + } + }, + [changeDex] + ) + + const networkTextColor = useCallback((network: Network) => { + switch (network) { + case Network.Mainnet: + return 'text-turquoise' + case Network.Stagenet: + return 'text-error1 dark:text-error1d' + case Network.Testnet: + return 'text-warning0 dark:text-warning0' + default: + return 'text-text2 dark:text-text2' + } + }, []) + const dexTextColor = useCallback((dex: Dex) => { + switch (dex.chain) { + case THORChain: + return 'text-turquoise' + case MAYAChain: + return 'text-cyanblue' + default: + return 'text-text2 dark:text-text2' + } + }, []) + + const networkMenu = useMemo(() => { + return ( + ((n: Network) => ({ + label: ( +
+ {n} +
+ ), + key: n + })) + )} + /> + ) + }, [changeNetworkHandler, network, networkTextColor]) + + const dexMenu = useMemo(() => { + return ( + ((n: Dex) => ({ + label: ( +
+ {n.chain} +
+ ), + key: n.chain + })) + )} + /> + ) + }, [changeDexHandler, dex, dexTextColor]) + + const renderNetworkMenu = useMemo( + () => ( + +
+

+ {network} +

+ +
+
+ ), + [networkMenu, networkTextColor, network] + ) + const renderDexMenu = useMemo( + () => ( + +
+

{dex.chain}

+ +
+
+ ), + [dexMenu, dexTextColor, dex] + ) + + const checkUpdatesProps = useMemo(() => { + const commonProps = { + onClick: checkForUpdates, + children: <>{intl.formatMessage({ id: 'common.refresh' })} + } + + return FP.pipe( + appUpdateState, + RD.fold( + () => commonProps, + () => ({ + ...commonProps, + loading: true, + disabled: true + }), + () => ({ + ...commonProps + }), + (oVersion) => ({ + ...commonProps, + ...FP.pipe( + oVersion, + O.fold( + () => ({ + onClick: checkForUpdates + }), + (version) => ({ + onClick: () => goToReleasePage(version), + children: ( + <> + {intl.formatMessage({ id: 'update.link' })} + + ) + }) + ) + ) + }) + ) + ) + }, [appUpdateState, checkForUpdates, goToReleasePage, intl]) + + const renderVersionUpdateResult = useMemo( + () => + FP.pipe( + appUpdateState, + RD.fold( + FP.constNull, + FP.constNull, + ({ message }) => ( + + {intl.formatMessage({ id: 'update.checkFailed' }, { error: message })} + + ), + O.fold( + () => {intl.formatMessage({ id: 'update.noUpdate' })}, + (version) => {intl.formatMessage({ id: 'update.description' }, { version })} + ) + ) + ), + [appUpdateState, intl] + ) + + return ( +
+ {/* // TODO: locale for subtitle */} +
+ {renderNetworkMenu} +
+
+ {renderDexMenu} +
+
+ {renderLangMenu} +
+
+
+
+ v{version} + +
+ {renderVersionUpdateResult} +
+
+
+ ) +} diff --git a/src/renderer/components/settings/AppSettings.tsx b/src/renderer/components/settings/AppSettings.tsx index f2ecf23e5..20dc737aa 100644 --- a/src/renderer/components/settings/AppSettings.tsx +++ b/src/renderer/components/settings/AppSettings.tsx @@ -345,7 +345,7 @@ export const AppSettings: React.FC = (props): JSX.Element => { }, [advancedActive]) return ( -
+
} activeKey={collapsed ? '0' : '1'} diff --git a/src/renderer/components/settings/EditableUrl.tsx b/src/renderer/components/settings/EditableUrl.tsx index 79ad4cab2..ee04cd716 100644 --- a/src/renderer/components/settings/EditableUrl.tsx +++ b/src/renderer/components/settings/EditableUrl.tsx @@ -217,7 +217,7 @@ const EditableUrl: React.FC = (props): JSX.Element => { ) return ( -
+
{FP.pipe(editableUrl, O.fold(renderUrl, renderEditableUrl))} {renderTestUrlResult}
diff --git a/src/renderer/components/settings/UnlockWalletSettings.tsx b/src/renderer/components/settings/UnlockWalletSettings.tsx index 6f43bed0c..e61522ae2 100644 --- a/src/renderer/components/settings/UnlockWalletSettings.tsx +++ b/src/renderer/components/settings/UnlockWalletSettings.tsx @@ -1,50 +1,28 @@ import React from 'react' -import { Collapse } from 'antd' import * as FP from 'fp-ts/lib/function' import { useIntl } from 'react-intl' import { KeystoreState } from '../../services/wallet/types' import { hasImportedKeystore, isLocked } from '../../services/wallet/util' import { FlatButton } from '../uielements/button' -import * as Styled from './Common.styles' type Props = { keystoreState: KeystoreState unlockHandler: FP.Lazy - collapsed: boolean - toggleCollapse: FP.Lazy } export const UnlockWalletSettings: React.FC = (props): JSX.Element => { - const { keystoreState, unlockHandler, collapsed, toggleCollapse } = props + const { keystoreState, unlockHandler } = props const intl = useIntl() return ( -
- } - activeKey={collapsed ? '0' : '1'} - expandIconPosition="end" - onChange={toggleCollapse} - ghost> - {intl.formatMessage({ id: 'setting.wallet.title' })}} - key={'1'}> -
- - {!hasImportedKeystore(keystoreState) - ? intl.formatMessage({ id: 'wallet.add.label' }) - : isLocked(keystoreState) && intl.formatMessage({ id: 'wallet.unlock.label' })} - -
-
-
+
+ + {!hasImportedKeystore(keystoreState) + ? intl.formatMessage({ id: 'wallet.add.label' }) + : isLocked(keystoreState) && intl.formatMessage({ id: 'wallet.unlock.label' })} +
) } diff --git a/src/renderer/components/settings/WalletSettings.styles.ts b/src/renderer/components/settings/WalletSettings.styles.ts index 7adbb1325..1c400facc 100644 --- a/src/renderer/components/settings/WalletSettings.styles.ts +++ b/src/renderer/components/settings/WalletSettings.styles.ts @@ -15,11 +15,20 @@ import { } from '../uielements/common/Common.styles' import { Label as UILabel } from '../uielements/label' +export const AutoComplete = styled(A.AutoComplete)` + .ant-select-selector { + border-color: ${palette('background', 2)} !important; + background-color: ${palette('background', 0)} !important; + color: ${palette('text', 0)}; + } +` + export const Input = styled(A.Input)` border-color: ${palette('gray', 1)}; max-width: 300px; .ant-input { + background-color: ${palette('background', 0)} !important; color: ${palette('text', 0)}; } @@ -27,10 +36,6 @@ export const Input = styled(A.Input)` .anticon-close-circle svg { color: ${palette('gray', 1)}; } - - ${media.md` - margin: 0 10px 0 10px; - `} ` export const Subtitle = styled(UILabel)` @@ -90,13 +95,19 @@ export const AccountCard = styled(A.Card)` } ` +export const List = styled(A.List)` + li { + border-bottom: 1px solid ${palette('gray', 0)}; + } +` + export const ListItem = styled(A.List.Item)` padding: 40px 20px; flex-direction: column; align-items: start; border-bottom: none; - border-bottom: 1px solid ${palette('gray', 0)}; + border-bottom: 1px solid ${palette('gray', 0)} !important; .ant-list-item { border-bottom: 1px solid ${palette('gray', 0)}; } @@ -107,7 +118,7 @@ export const AccountTitle = styled(UILabel)` padding-left: 10px; text-transform: uppercase; font-weight: normal; - font-size: 27px; + font-size: 20px; line-height: 25px; letter-spacing: 2px; ` diff --git a/src/renderer/components/settings/WalletSettings.tsx b/src/renderer/components/settings/WalletSettings.tsx index d35df8ac1..d29df9510 100644 --- a/src/renderer/components/settings/WalletSettings.tsx +++ b/src/renderer/components/settings/WalletSettings.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react' -import { SearchOutlined } from '@ant-design/icons' +import { DeleteOutlined, ExportOutlined, EyeOutlined, LockOutlined, SearchOutlined } from '@ant-design/icons' import * as RD from '@devexperts/remote-data-ts' import { ARBChain } from '@xchainjs/xchain-arbitrum' import { AVAXChain } from '@xchainjs/xchain-avax' @@ -18,7 +18,8 @@ import { MAYAChain } from '@xchainjs/xchain-mayachain' import { RadixChain } from '@xchainjs/xchain-radix' import { THORChain } from '@xchainjs/xchain-thorchain' import { Asset, Address, Chain, TokenAsset } from '@xchainjs/xchain-util' -import { List, Collapse, RadioChangeEvent, AutoComplete, message } from 'antd' +import { List, RadioChangeEvent, AutoComplete, message } from 'antd' +import clsx from 'clsx' import * as FP from 'fp-ts/function' import * as A from 'fp-ts/lib/Array' import * as O from 'fp-ts/lib/Option' @@ -31,7 +32,6 @@ import { EvmHDMode } from '../../../shared/evm/types' import { chainToString, EnabledChain, isSupportedChain } from '../../../shared/utils/chain' import { isError } from '../../../shared/utils/guard' import { HDMode, WalletAddress } from '../../../shared/wallet/types' -import { ReactComponent as UnlockOutlined } from '../../assets/svg/icon-unlock-warning.svg' import { WalletPasswordConfirmationModal } from '../../components/modal/confirmation' import { RemoveWalletConfirmationModal } from '../../components/modal/confirmation/RemoveWalletConfirmationModal' import { AssetIcon } from '../../components/uielements/assets/assetIcon/AssetIcon' @@ -70,16 +70,43 @@ import { BSC_TOKEN_WHITELIST } from '../../types/generated/thorchain/bscerc20whi import { ERC20_WHITELIST } from '../../types/generated/thorchain/erc20whitelist' import { AttentionIcon } from '../icons' import * as StyledR from '../shared/form/Radio.styles' -import { BorderButton, FlatButton, TextButton } from '../uielements/button' +import { FlatButton } from '../uielements/button' import { SwitchButton } from '../uielements/button/SwitchButton' import { Tooltip, WalletTypeLabel } from '../uielements/common/Common.styles' import { InfoIcon } from '../uielements/info' import { Modal } from '../uielements/modal' import { WalletSelector } from '../uielements/wallet' import { EditableWalletName } from '../uielements/wallet/EditableWalletName' -import * as CStyled from './Common.styles' import * as Styled from './WalletSettings.styles' +const ActionButton = ({ + className, + icon, + text, + onClick +}: { + className?: string + icon?: React.ReactNode + text: string + onClick: () => void +}) => { + return ( +
+ {icon} + {text} +
+ ) +} + type Props = { network: Network walletAccounts: O.Option @@ -105,8 +132,6 @@ type Props = { wallets: KeystoreWalletsUI clickAddressLinkHandler: (chain: Chain, address: Address) => void validatePassword$: ValidatePasswordHandler - collapsed: boolean - toggleCollapse: FP.Lazy evmHDMode: EvmHDMode updateEvmHDMode: (mode: EvmHDMode) => void } @@ -129,8 +154,6 @@ export const WalletSettings: React.FC = (props): JSX.Element => { wallets, clickAddressLinkHandler, validatePassword$, - collapsed, - toggleCollapse, updateEvmHDMode, evmHDMode } = props @@ -624,7 +647,12 @@ export const WalletSettings: React.FC = (props): JSX.Element => { const [assetSearch, setAssetSearch] = useState<{ [key in Chain]?: string }>({}) const [filteredAssets, setFilteredAssets] = useState<{ [key in Chain]?: TokenAsset[] }>({}) - const [isAddingByChain, setIsAddingByChain] = useState<{ [key in Chain]?: boolean }>({}) + const [isAddingByChain, setIsAddingByChain] = useState<{ [key in Chain]?: boolean }>({ + [ETHChain]: true, + [AVAXChain]: true, + [BSCChain]: true, + [ARBChain]: true + }) const toggleStorageMode = useCallback((chain: Chain) => { setIsAddingByChain((prevState) => ({ @@ -751,23 +779,25 @@ export const WalletSettings: React.FC = (props): JSX.Element => { const renderAddAddressForm = useCallback( () => (
- ({ value: chain }))} value={newAddress.chain} - onChange={(value) => setNewAddress((prev) => ({ ...prev, chain: value }))} + onChange={(value) => setNewAddress((prev) => ({ ...prev, chain: value as string }))} filterOption={(inputValue, option) => option ? option.value.toLowerCase().includes(inputValue.toLowerCase()) : false } /> setNewAddress((prev) => ({ ...prev, address: e.target.value }))} /> setNewAddress((prev) => ({ ...prev, name: e.target.value }))} @@ -829,7 +859,7 @@ export const WalletSettings: React.FC = (props): JSX.Element => { ? renderLedgerAddress(chain, oLedger) : renderLedgerNotSupported}
-
+
toggleChain(chain)} /> {enabledChains.includes(chain) @@ -988,140 +1018,97 @@ export const WalletSettings: React.FC = (props): JSX.Element => { ) return ( -
- } - activeKey={collapsed ? '0' : '1'} - expandIconPosition="end" - onChange={toggleCollapse} - ghost> - {intl.formatMessage({ id: 'setting.wallet.title' })}} - key={'1'}> - {showPasswordModal && ( - setShowPasswordModal(false)} - /> - )} - {showPhraseModal && ( - { - setShowPhraseModal(false) - }} - /> - )} - setShowRemoveWalletModal(false)} - onSuccess={() => removeWalletHandler()} - walletName={walletName} - /> - {renderQRCodeModal} - - {renderVerifyAddressModal(ledgerAddressToVerify)} -
-

- {intl.formatMessage({ id: 'setting.wallet.management' })} -

- + {showPasswordModal && ( + setShowPasswordModal(false)} + /> + )} + {showPhraseModal && ( + { + setShowPhraseModal(false) + }} + /> + )} + setShowRemoveWalletModal(false)} + onSuccess={() => removeWalletHandler()} + walletName={walletName} + /> + {renderQRCodeModal} + + {renderVerifyAddressModal(ledgerAddressToVerify)} +
+
+

+ {intl.formatMessage({ id: 'setting.wallet.management' })} +

+
+ - {renderRenameWalletError} -
-
- - {intl.formatMessage({ id: 'setting.export' })} - -
-
- - {intl.formatMessage({ id: 'setting.lock' })} - -
-
-
-
- setShowPasswordModal(true)}> - {intl.formatMessage({ id: 'setting.view.phrase' })} - -
-
- setShowRemoveWalletModal(true)}> - {intl.formatMessage({ id: 'wallet.remove.label' })} - -
-
+ navigate(walletRoutes.noWallet.path())}> + {intl.formatMessage({ id: 'wallet.add.label' })} + + {/* // TODO: needs to show error on notification */} + {renderChangeWalletError}
- -
-

- {intl.formatMessage({ id: 'setting.multiwallet.management' })} -

- -
-
-

- {intl.formatMessage({ id: 'wallet.add.another' })} -

- navigate(walletRoutes.noWallet.path())}> - {intl.formatMessage({ id: 'wallet.add.label' })} - -
-
-

- {intl.formatMessage({ id: 'wallet.change.title' })} -

- - {renderChangeWalletError} -
-
-
-
- - {intl.formatMessage({ id: 'setting.accounts' })} -
- } - onChange={filterAccounts} - allowClear - placeholder={intl.formatMessage({ id: 'common.search' }).toUpperCase()} - size="large" - /> -
-
{renderAddAddressForm()}
- {renderAccounts} -
-
- - +
+ + {renderRenameWalletError} +
+ } + text={intl.formatMessage({ id: 'setting.export' })} + onClick={exportKeystoreHandler} + /> + } + text={intl.formatMessage({ id: 'setting.lock' })} + onClick={lockWallet} + /> + } + text={intl.formatMessage({ id: 'setting.view.phrase' })} + onClick={() => setShowPasswordModal(true)} + /> + } + text={intl.formatMessage({ id: 'wallet.remove.label' })} + onClick={() => setShowRemoveWalletModal(true)} + /> +
+
+
+ {intl.formatMessage({ id: 'setting.accounts' })} +
+ } + onChange={filterAccounts} + allowClear + placeholder={intl.formatMessage({ id: 'common.search' }).toUpperCase()} + size="large" + /> +
+
{renderAddAddressForm()}
+ {renderAccounts} +
) } diff --git a/src/renderer/components/settings/index.ts b/src/renderer/components/settings/index.ts index dd66f7920..a827449f2 100644 --- a/src/renderer/components/settings/index.ts +++ b/src/renderer/components/settings/index.ts @@ -1,3 +1,4 @@ export { WalletSettings } from './WalletSettings' export { UnlockWalletSettings } from './UnlockWalletSettings' export { AppSettings } from './AppSettings' +export { AppGeneralSettings } from './AppGeneralSettings' diff --git a/src/renderer/components/uielements/alert/Alert.styles.ts b/src/renderer/components/uielements/alert/Alert.styles.ts index 985300830..d9fb0dadd 100644 --- a/src/renderer/components/uielements/alert/Alert.styles.ts +++ b/src/renderer/components/uielements/alert/Alert.styles.ts @@ -20,6 +20,8 @@ export const Alert = styled(A.Alert)` color: ${palette('text', 0)}; } + border-radius: 8px; + &.ant-alert-info { border-color: ${palette('gray', 1)}; > .ant-alert-icon > svg { diff --git a/src/renderer/components/uielements/alert/Alert.tsx b/src/renderer/components/uielements/alert/Alert.tsx index 43e3921fb..5607fffc4 100644 --- a/src/renderer/components/uielements/alert/Alert.tsx +++ b/src/renderer/components/uielements/alert/Alert.tsx @@ -8,7 +8,7 @@ import * as Styled from './Alert.styles' export type Props = Omit export const Alert: React.FC = (props): JSX.Element => { - const { description } = props + const { description, ...rest } = props - return } description={description} {...props} /> + return } description={description} {...rest} /> } diff --git a/src/renderer/i18n/de/settings.ts b/src/renderer/i18n/de/settings.ts index 90b1d79b4..795521465 100644 --- a/src/renderer/i18n/de/settings.ts +++ b/src/renderer/i18n/de/settings.ts @@ -7,7 +7,7 @@ const settings: SettingMessages = { 'setting.multiwallet.management': 'Multi-Wallets Management', 'setting.client': 'Client', 'setting.accounts': 'Konten', - 'setting.export': 'Keystore exportieren', + 'setting.export': 'Exportieren', 'setting.lock': 'Sperren', 'setting.view.phrase': 'Phrase ansehen', 'setting.version': 'Version', diff --git a/src/renderer/i18n/en/settings.ts b/src/renderer/i18n/en/settings.ts index 69538f29b..083e5507b 100644 --- a/src/renderer/i18n/en/settings.ts +++ b/src/renderer/i18n/en/settings.ts @@ -7,7 +7,7 @@ const settings: SettingMessages = { 'setting.multiwallet.management': 'Multi wallets management', 'setting.client': 'Client', 'setting.accounts': 'Accounts', - 'setting.export': 'Export Keystore', + 'setting.export': 'Export', 'setting.lock': 'Lock', 'setting.view.phrase': 'View Phrase', 'setting.version': 'Version', diff --git a/src/renderer/i18n/es/settings.ts b/src/renderer/i18n/es/settings.ts index 5e5fc6468..7efad02d2 100644 --- a/src/renderer/i18n/es/settings.ts +++ b/src/renderer/i18n/es/settings.ts @@ -7,7 +7,7 @@ const settings: SettingMessages = { 'setting.multiwallet.management': 'Gestión de varios monederos', 'setting.client': 'Cliente', 'setting.accounts': 'Cuentas', - 'setting.export': 'Exportar almacén de claves', + 'setting.export': 'Exportar', 'setting.lock': 'Cerradura', 'setting.view.phrase': 'Ver la frase', 'setting.version': 'Versión', diff --git a/src/renderer/i18n/fr/settings.ts b/src/renderer/i18n/fr/settings.ts index 65acbfdbf..6b7e473ff 100644 --- a/src/renderer/i18n/fr/settings.ts +++ b/src/renderer/i18n/fr/settings.ts @@ -7,7 +7,7 @@ const settings: SettingMessages = { 'setting.multiwallet.management': 'Gestion multi portefeuilles', 'setting.client': 'Client', 'setting.accounts': 'Comptes', - 'setting.export': 'Exporter la clé privée', + 'setting.export': 'Exporter', 'setting.lock': 'Verrouiller', 'setting.view.phrase': 'Afficher la phrase de récupération', 'setting.language': 'Langue', diff --git a/src/renderer/i18n/ru/settings.ts b/src/renderer/i18n/ru/settings.ts index a0d24076a..4f8ae88ec 100644 --- a/src/renderer/i18n/ru/settings.ts +++ b/src/renderer/i18n/ru/settings.ts @@ -7,7 +7,7 @@ const settings: SettingMessages = { 'setting.multiwallet.management': 'Управление мульти-кошельками', 'setting.client': 'Клиент', 'setting.accounts': 'Учётные записи', - 'setting.export': 'Экспортировать Keystore', + 'setting.export': 'Экспортировать', 'setting.lock': 'Заблокировать', 'setting.view.phrase': 'Показать секретную фразу', 'setting.language': 'Язык', diff --git a/src/renderer/views/ViewRoutes.tsx b/src/renderer/views/ViewRoutes.tsx index 8dc6be79d..877acf56b 100644 --- a/src/renderer/views/ViewRoutes.tsx +++ b/src/renderer/views/ViewRoutes.tsx @@ -8,7 +8,7 @@ import * as poolsRoutes from '../routes/pools' import * as lendingRoutes from '../routes/pools/lending' import * as saversRoutes from '../routes/pools/savers' import * as walletRoutes from '../routes/wallet' -import { AppSettingsView } from './app/AppSettingsView' +import { AppSettings } from './app/AppSettings' import { DepositView } from './deposit/DepositView' import { LoansView } from './loans/LoansView' import { NoContentView } from './NoContentView' @@ -32,7 +32,6 @@ import { SendView } from './wallet/send' import { TradeAssetsView } from './wallet/TradeAssetsView' import { UnlockView } from './wallet/UnlockView' import { WalletAuth } from './wallet/WalletAuth' -import { WalletSettingsAuth } from './wallet/WalletSettingsAuth' export const ViewRoutes: React.FC<{}> = (): JSX.Element => { const location = useLocation() @@ -173,15 +172,7 @@ export const ViewRoutes: React.FC<{}> = (): JSX.Element => { } /> - - - - - } - /> + } /> {/* playground - DEV only */} } /> {/* 404 */} diff --git a/src/renderer/views/app/AppSettingsView.tsx b/src/renderer/views/app/AppExpertModeView.tsx similarity index 65% rename from src/renderer/views/app/AppSettingsView.tsx rename to src/renderer/views/app/AppExpertModeView.tsx index bde3f64ff..365aca8a2 100644 --- a/src/renderer/views/app/AppSettingsView.tsx +++ b/src/renderer/views/app/AppExpertModeView.tsx @@ -3,25 +3,16 @@ import React, { useCallback } from 'react' import * as RD from '@devexperts/remote-data-ts' import { useObservableState } from 'observable-hooks' -import { ExternalUrl } from '../../../shared/const' -import { DEFAULT_LOCALE } from '../../../shared/i18n/const' -import { envOrDefault } from '../../../shared/utils/env' -import { AppSettings } from '../../components/settings' -import { useI18nContext } from '../../contexts/I18nContext' +import { AppExpertMode } from '../../components/settings/AppExpertMode' import { useMidgardContext } from '../../contexts/MidgardContext' import { useMidgardMayaContext } from '../../contexts/MidgardMayaContext' -import { useAppUpdate } from '../../hooks/useAppUpdate' -import { useCollapsedSetting } from '../../hooks/useCollapsedSetting' -import { useDex } from '../../hooks/useDex' import { useMayachainClientUrl } from '../../hooks/useMayachainClientUrl' import { useNetwork } from '../../hooks/useNetwork' import { usePrivateData } from '../../hooks/usePrivateData' import { useThorchainClientUrl } from '../../hooks/useThorchainClientUrl' -export const AppSettingsView: React.FC = (): JSX.Element => { - const { network, changeNetwork } = useNetwork() - const { dex, changeDex } = useDex() - const { appUpdater, checkForUpdates } = useAppUpdate() +export const AppExpertModeView: React.FC = (): JSX.Element => { + const { network } = useNetwork() const { service: { apiEndpoint$, setMidgardUrl, checkMidgardUrl$ } } = useMidgardContext() @@ -37,8 +28,6 @@ export const AppSettingsView: React.FC = (): JSX.Element => { const { isPrivate, changePrivateData } = usePrivateData() - const { collapsed, toggle: toggleCollapse } = useCollapsedSetting('app') - const { node: thornodeNodeUrl, rpc: thornodeRpcUrl, @@ -57,14 +46,6 @@ export const AppSettingsView: React.FC = (): JSX.Element => { checkNode$: checkMayanodeNodeUrl$ } = useMayachainClientUrl() - const { changeLocale, locale$ } = useI18nContext() - const currentLocale = useObservableState(locale$, DEFAULT_LOCALE) - - const goToReleasePage = useCallback( - (version: string) => window.apiUrl.openExternal(`${ExternalUrl.GITHUB_RELEASE}${version}`), - [] - ) - const updateMidgardUrlHandler = useCallback( (url: string) => { setMidgardUrl(url, network) @@ -79,21 +60,9 @@ export const AppSettingsView: React.FC = (): JSX.Element => { ) return ( - { + const { network, changeNetwork } = useNetwork() + const { dex, changeDex } = useDex() + const { appUpdater, checkForUpdates } = useAppUpdate() + + const { changeLocale, locale$ } = useI18nContext() + const currentLocale = useObservableState(locale$, DEFAULT_LOCALE) + + const goToReleasePage = useCallback( + (version: string) => window.apiUrl.openExternal(`${ExternalUrl.GITHUB_RELEASE}${version}`), + [] + ) + + return ( + + ) +} diff --git a/src/renderer/views/app/AppSettings.styles.ts b/src/renderer/views/app/AppSettings.styles.ts new file mode 100644 index 000000000..e854c83bf --- /dev/null +++ b/src/renderer/views/app/AppSettings.styles.ts @@ -0,0 +1,31 @@ +import styled from 'styled-components' +import { palette } from 'styled-theme' + +import { Tabs as TabsUI } from '../../components/tabs/Tabs' + +export const Tabs = styled(TabsUI)` + padding-top: 0; + .ant-tabs { + &-nav { + margin: 0; + + &:before { + border-bottom: 1px solid ${palette('gray', 0)}; + } + + &-list { + padding: 10px 0; + } + + &-wrap { + justify-content: start !important; + } + } + + &-tabpane { + > div { + padding: 0px; + } + } + } +` diff --git a/src/renderer/views/app/AppSettings.tsx b/src/renderer/views/app/AppSettings.tsx new file mode 100644 index 000000000..5a2600d91 --- /dev/null +++ b/src/renderer/views/app/AppSettings.tsx @@ -0,0 +1,43 @@ +import { useMemo } from 'react' + +import { useIntl } from 'react-intl' + +import { WalletSettingsAuth } from '../wallet/WalletSettingsAuth' +import { AppExpertModeView } from './AppExpertModeView' +import { AppGeneralSettingsView } from './AppGeneralSettingsView' +import * as Styled from './AppSettings.styles' + +export const AppSettings = () => { + const intl = useIntl() + + const tabs = useMemo( + () => [ + { + key: 'settings-general', + disabled: false, + label: intl.formatMessage({ id: 'common.general' }), + content: + }, + { + key: 'settings-wallet', + disabled: false, + label: intl.formatMessage({ id: 'common.wallet' }), + content: + }, + { + key: 'settings-expert', + disabled: false, + // TODO: add locale + label: 'Expert Mode', + content: + } + ], + [intl] + ) + + return ( +
+ +
+ ) +} diff --git a/src/renderer/views/wallet/WalletSettingsAuth.tsx b/src/renderer/views/wallet/WalletSettingsAuth.tsx index 41340614b..25c36a0fa 100644 --- a/src/renderer/views/wallet/WalletSettingsAuth.tsx +++ b/src/renderer/views/wallet/WalletSettingsAuth.tsx @@ -8,7 +8,6 @@ import * as RxOp from 'rxjs/operators' import { UnlockWalletSettings } from '../../components/settings' import { useWalletContext } from '../../contexts/WalletContext' -import { useCollapsedSetting } from '../../hooks/useCollapsedSetting' import * as walletRoutes from '../../routes/wallet' import { INITIAL_KEYSTORE_STATE } from '../../services/wallet/const' import { isKeystoreUnlocked } from '../../services/wallet/types' @@ -26,8 +25,6 @@ export const WalletSettingsAuth: React.FC = (): JSX.Element => { // In other case it will jump to `UnlockWalletSettings` right after changing a wallet in `WalletSettingsView` const keystoreState = useObservableState(FP.pipe(keystoreState$, RxOp.delay(100)), INITIAL_KEYSTORE_STATE) - const { collapsed, toggle: toggleCollapse } = useCollapsedSetting('wallet') - const unlockWalletHandler = useCallback(() => { navigate(walletRoutes.base.path(location.pathname)) }, [location.pathname, navigate]) @@ -38,14 +35,7 @@ export const WalletSettingsAuth: React.FC = (): JSX.Element => { O.chain(FP.flow(O.fromPredicate(isKeystoreUnlocked))), O.fold( // keystore locked / not imported - () => ( - - ), + () => , // keystore unlocked (keystoreUnlocked) => ) diff --git a/src/renderer/views/wallet/WalletSettingsView.tsx b/src/renderer/views/wallet/WalletSettingsView.tsx index db431ebed..4ccdd2da0 100644 --- a/src/renderer/views/wallet/WalletSettingsView.tsx +++ b/src/renderer/views/wallet/WalletSettingsView.tsx @@ -63,7 +63,6 @@ import { isXrdChain } from '../../helpers/chainHelper' import { sequenceTOptionFromArray } from '../../helpers/fpHelpers' -import { useCollapsedSetting } from '../../hooks/useCollapsedSetting' import { useKeystoreState } from '../../hooks/useKeystoreState' import { useKeystoreWallets } from '../../hooks/useKeystoreWallets' import { useLedger } from '../../hooks/useLedger' @@ -88,8 +87,6 @@ export const WalletSettingsView: React.FC = ({ keystoreUnlocked }): JSX.E const { network } = useNetwork() - const { collapsed, toggle: toggleCollapse } = useCollapsedSetting('wallet') - const { address$: thorAddressUI$ } = useThorchainContext() const { addressUI$: ethAddressUI$, ethHDMode$, updateEvmHDMode } = useEthereumContext() const { addressUI$: arbAddressUI$ } = useArbContext() @@ -500,8 +497,6 @@ export const WalletSettingsView: React.FC = ({ keystoreUnlocked }): JSX.E walletAccounts={walletAccounts} clickAddressLinkHandler={clickAddressLinkHandler} validatePassword$={validatePassword$} - collapsed={collapsed} - toggleCollapse={toggleCollapse} evmHDMode={evmHDMode} updateEvmHDMode={updateEvmHDMode} />