diff --git a/packages/common-components/src/ExpansionPanel/ExpansionPanel.tsx b/packages/common-components/src/ExpansionPanel/ExpansionPanel.tsx index e1bd7ab69f..db79fd50dd 100644 --- a/packages/common-components/src/ExpansionPanel/ExpansionPanel.tsx +++ b/packages/common-components/src/ExpansionPanel/ExpansionPanel.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, useState } from "react" +import React, { ReactNode, useCallback, useState } from "react" import { ITheme, makeStyles, createStyles } from "@chainsafe/common-theme" import { Typography } from "../Typography" import clsx from "clsx" @@ -35,6 +35,7 @@ const useStyles = makeStyles( }px`, color: palette.additional["gray"][9], cursor: "pointer", + display: "flex", "&.basic": { backgroundColor: palette.additional["gray"][2], ...overrides?.ExpansionPanel?.heading?.basic?.root, @@ -56,6 +57,9 @@ const useStyles = makeStyles( }, ...overrides?.ExpansionPanel?.heading?.root }, + flexGrow: { + flex: 1 + }, content: { overflow: "hidden", color: palette.additional["gray"][8], @@ -90,37 +94,54 @@ export interface IExpansionPanelProps { children?: ReactNode | ReactNode[] | null active?: boolean variant?: "basic" | "borderless" + iconPosition?: "left" | "right" toggle?: (state: boolean) => void + injectedClasses?: { + root?: string + heading?: string + content?: string + } } -const ExpansionPanel: React.FC = ({ - children, - header, - variant = "basic", - toggle, - active -}: IExpansionPanelProps) => { +const ExpansionPanel = ({ children, header, iconPosition, variant = "basic", toggle, active, injectedClasses }: IExpansionPanelProps) => { const classes = useStyles() const [activeInternal, setActive] = useState(!!active) - const handleToggle = () => { + const handleToggle = useCallback(() => { toggle && toggle(!activeInternal) setActive(!activeInternal) - } + }, [activeInternal, toggle]) + return ( -
+
handleToggle()} - className={clsx(classes.heading, variant, { - ["active"]: active != undefined ? active : activeInternal - })} + onClick={handleToggle} + className={clsx( + classes.heading, + variant, + injectedClasses?.heading, + { + ["active"]: active !== undefined ? active : activeInternal + } + )} > - + {iconPosition === "left" && } {header} + {iconPosition === "right" && ( + <> +
+ + + )}
{children}
diff --git a/packages/files-ui/src/Components/Modules/LoginModule/SignInMethods.tsx b/packages/files-ui/src/Components/Modules/LoginModule/SignInMethods.tsx index ed610ce076..2e2f2d8805 100644 --- a/packages/files-ui/src/Components/Modules/LoginModule/SignInMethods.tsx +++ b/packages/files-ui/src/Components/Modules/LoginModule/SignInMethods.tsx @@ -4,7 +4,6 @@ import { CheckCircleSvg, CopySvg, KeySvg, Typography } from "@chainsafe/common-c import { Trans } from "@lingui/macro" import { useThresholdKey } from "../../../Contexts/ThresholdKeyContext" import { CSFTheme } from "../../../Themes/types" -import bowser from "bowser" import clsx from "clsx" import { ROUTE_LINKS } from "../../FilesRoutes" @@ -196,7 +195,7 @@ const SignInMethods = ({ goToComplete, goToMnemonic, goToPassword, goToSkip, cla desktop && ( Saved{" "} - {`${bowser.parse(browserShares[0].userAgent).browser.name} ${bowser.parse(browserShares[0].userAgent).browser.version}`} + {`${browserShares[0].browser.name} ${browserShares[0].browser.version}`} ) } diff --git a/packages/files-ui/src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx b/packages/files-ui/src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx new file mode 100644 index 0000000000..61eb96701c --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx @@ -0,0 +1,192 @@ +import React, { useCallback, useState } from "react" +import { + makeStyles, + createStyles +} from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../Themes/types" +import { Button, ExpansionPanel, Typography } from "@chainsafe/common-components" +import clsx from "clsx" +import { Trans } from "@lingui/macro" +import dayjs from "dayjs" +import { BrowserShare, useThresholdKey } from "../../../../Contexts/ThresholdKeyContext" + +const useStyles = makeStyles(({ palette, constants, animation, breakpoints }: CSFTheme) => + createStyles({ + panelHeading: { + backgroundColor: palette.additional["gray"][4], + borderRadius: "10px", + padding: `${constants.generalUnit}px 0 ${constants.generalUnit}px ${constants.generalUnit * 2}px`, + transition: `border-radius ${animation.transform}ms`, + "&.active": { + borderBottomLeftRadius: 0, + borderBottomRightRadius: 0 + } + }, + panelBody: { + backgroundColor: palette.additional["gray"][4], + padding: 0, + borderBottomLeftRadius: "10px", + borderBottomRightRadius: "10px", + marginTop: `-${constants.generalUnit}px` + }, + panelContent: { + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit, + color: palette.additional["gray"][9], + display: "flex", + flexDirection: "column" + }, + subtitle: { + paddingBottom: constants.generalUnit, + lineHeight: "24px", + [breakpoints.down("md")]: { + fontSize: "14px", + lineHeight: "22px" + } + }, + subtitleLast: { + lineHeight: "24px", + [breakpoints.down("md")]: { + fontSize: "14px", + lineHeight: "22px" + } + }, + lightSubtitle: { + color: palette.additional["gray"][8], + paddingBottom: constants.generalUnit * 0.5, + [breakpoints.down("md")]: { + fontSize: "14px", + lineHeight: "22px" + } + }, + actionBox: { + marginTop: constants.generalUnit * 2 + }, + spanMarginRight: { + marginRight: "0.5rem" + } + }) +) + +function download(filename: string, text: string) { + const element = document.createElement("a") + element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)) + element.setAttribute("download", filename) + element.style.display = "none" + document.body.appendChild(element) + element.click() + document.body.removeChild(element) +} + +const BrowserPanel = ({ dateAdded, shareIndex, browser, os }: BrowserShare) => { + const { deleteShare, getSerializedDeviceShare } = useThresholdKey() + const classes = useStyles() + const [showPanel, setShowPanel] = useState(false) + const [loadingDeleteShare, setLoadingDeleteShare] = useState(false) + const [loadingDownloadKey, setLoadingDownloadKey] = useState(false) + + const onDeleteShare = useCallback(() => { + setLoadingDeleteShare(true) + deleteShare(shareIndex) + .then(() => { + setLoadingDeleteShare(false) + setShowPanel(false) + }).catch((e) => { + console.error(e) + setLoadingDeleteShare(false) + }) + }, + [deleteShare, shareIndex]) + + const onDownloadKey = useCallback(() => { + setLoadingDownloadKey(true) + getSerializedDeviceShare(shareIndex) + .then((mnemonicKey) => { + if (mnemonicKey) { + download(`Chainsafe Files - ${browser.name || ""} key.txt`, mnemonicKey) + } + setLoadingDownloadKey(false) + }) + .catch((e) => { + console.error(e) + setLoadingDownloadKey(false) + }) + }, [browser.name, getSerializedDeviceShare, shareIndex]) + + return ( + setShowPanel(!showPanel)} + > +
+
+ + Operating system:{os.name} + + + + Browser: + + {browser.name}{browser.version} + + + Saved on:{dayjs(dateAdded).format("DD MMM YYYY - HH:mm")} + +
+ + Your recovery key can be used to restore your account in place of your backup phrase. + + +
+
+ + Forgetting this browser deletes this from your list of sign-in methods. + You will not be able to forget a browser if you only have two methods set up. + + +
+
+
+
+ ) +} + +export default BrowserPanel \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SavedBrowsers/index.tsx b/packages/files-ui/src/Components/Modules/Settings/SavedBrowsers/index.tsx new file mode 100644 index 0000000000..7684b16f8c --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SavedBrowsers/index.tsx @@ -0,0 +1,48 @@ +import React from "react" +import { + makeStyles, + createStyles +} from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../Themes/types" +import { Typography } from "@chainsafe/common-components" +import BrowserPanel from "./BrowserPanel" +import { useThresholdKey } from "../../../../Contexts/ThresholdKeyContext" + +const useStyles = makeStyles(({ constants, breakpoints }: CSFTheme) => + createStyles({ + root: { + paddingBottom: constants.generalUnit, + [breakpoints.down("md")]: { + padding: `0 ${constants.generalUnit * 2}px` + } + }, + title: { + fontSize: "16px", + lineHeight: "24px", + paddingBottom: constants.generalUnit * 2 + }, + expansionContainer: { + marginBottom: constants.generalUnit * 3 + } + }) +) + +const SavedBrowsers: React.FC = () => { + const classes = useStyles() + const { browserShares } = useThresholdKey() + + return ( +
+ + Saved Browsers + + {browserShares.map((bs, i) => ( +
+ +
+ ))} +
+ ) +} + +export default SavedBrowsers \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/Security/index.tsx b/packages/files-ui/src/Components/Modules/Settings/Security/index.tsx index 57756e4207..f11717e422 100644 --- a/packages/files-ui/src/Components/Modules/Settings/Security/index.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/Security/index.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useMemo, useState } from "react" -import { CheckCircleSvg, CloseSvg, CrossOutlinedSvg, Grid, Typography } from "@chainsafe/common-components" +import { CheckCircleSvg, CloseSvg, CrossOutlinedSvg, Divider, Grid, Typography } from "@chainsafe/common-components" import { makeStyles, createStyles, useThemeSwitcher } from "@chainsafe/common-theme" import { CSFTheme } from "../../../../Themes/types" import { t, Trans } from "@lingui/macro" @@ -7,11 +7,13 @@ import { useThresholdKey } from "../../../../Contexts/ThresholdKeyContext" import clsx from "clsx" import PasswordForm from "../../../Elements/PasswordForm" import MnemonicForm from "../../../Elements/MnemonicForm" +import SavedBrowsers from "../SavedBrowsers" -const useStyles = makeStyles(({ constants, breakpoints, palette, typography }: CSFTheme) => +const useStyles = makeStyles(({ constants, breakpoints, palette, typography, zIndex }: CSFTheme) => createStyles({ root: { paddingTop: constants.generalUnit * 2, + paddingBottom: constants.generalUnit * 3, [breakpoints.down("md")]: { padding: constants.generalUnit * 2 } @@ -54,7 +56,6 @@ const useStyles = makeStyles(({ constants, breakpoints, palette, typography }: C fill: palette.additional.red[6] }, buttonLink: { - // color: palette.additional["gray"][10], outline: "none", textDecoration: "underline", cursor: "pointer" @@ -121,6 +122,9 @@ const useStyles = makeStyles(({ constants, breakpoints, palette, typography }: C }, changeButton: { marginLeft: "0.5rem" + }, + divider: { + zIndex: zIndex?.layer1 } }) ) @@ -347,6 +351,8 @@ const Security = ({ className }: SecurityProps) => { ) }
+ + ) diff --git a/packages/files-ui/src/Contexts/ThresholdKeyContext.tsx b/packages/files-ui/src/Contexts/ThresholdKeyContext.tsx index 7c6accd579..f31a81ec64 100644 --- a/packages/files-ui/src/Contexts/ThresholdKeyContext.tsx +++ b/packages/files-ui/src/Contexts/ThresholdKeyContext.tsx @@ -25,6 +25,12 @@ const TORUS_USERINFO_KEY = "csf.userInfo" const PASSWORD_QUESTION = "What is your password?" export type ThresholdKeyContextStatus = "initializing"|"initialized"|"awaiting confirmation"|"logging in"|"done" +export type BrowserShare = { + shareIndex: string + module: string + userAgent: string + dateAdded: number +} & Bowser.Parser.ParsedResult export type TThresholdKeyContext = { userInfo?: TorusLoginResponse @@ -32,7 +38,7 @@ export type TThresholdKeyContext = { publicKey?: string isNewDevice: boolean isNewKey: boolean - browserShares: any[] + browserShares: BrowserShare[] hasMnemonicShare: boolean hasPasswordShare: boolean shouldInitializeAccount: boolean @@ -45,15 +51,19 @@ export type TThresholdKeyContext = { inputPasswordShare(password: string): Promise inputMnemonicShare(mnemonic: string): Promise addNewDeviceShareAndSave(): Promise + deleteShare(shareIndex: string): Promise approveShareTransferRequest(encPubKeyX: string): Promise rejectShareTransferRequest(encPubKeyX: string): Promise clearShareTransferRequests(): Promise addMnemonicShare(): Promise + getSerializedDeviceShare(shareIndex: string): Promise encryptForPublicKey(publicKey: string, message: string): Promise decryptMessageWithThresholdKey(message: string): Promise logout(): Promise status: ThresholdKeyContextStatus resetStatus(): void + getAvailableShareIndices(): string[] | undefined + refreshTKeyMeta(): Promise loggedinAs: string } @@ -100,15 +110,24 @@ const ThresholdKeyProvider = ({ children, network = "mainnet", enableLogging = f // mnemonic has not been set up for the account. If totalShares - shares.length === 2 // this indicates that a mnemonic has already been set up. "2" corresponds here to one // service provider (default), and one mnemonic. - const shares = useMemo(() => keyDetails - ? Object.values(keyDetails.shareDescriptions).map((share) => { - return JSON.parse(share[0]) - }) + const parsedShares = useMemo(() => keyDetails + ? Object.keys(keyDetails.shareDescriptions).map((shareIndex) => ( + { + shareIndex: shareIndex, + ...JSON.parse(keyDetails.shareDescriptions[shareIndex][0]) + } + )) : [] , [keyDetails]) - const browserShares = useMemo(() => shares.filter((s) => s.module === WEB_STORAGE_MODULE_NAME), [shares]) - const hasMnemonicShare = useMemo(() => (keyDetails && (keyDetails.totalShares - shares.length > 1)) || false, [keyDetails, shares.length]) - const hasPasswordShare = useMemo(() => shares.filter((s) => s.module === SECURITY_QUESTIONS_MODULE_NAME).length > 0, [shares]) + + const browserShares = useMemo(() => parsedShares.filter((s) => s.module === WEB_STORAGE_MODULE_NAME).map(bs => ({ + ...bs, + ...bowser.parse(bs.userAgent) + } as BrowserShare)), [parsedShares]) + const hasMnemonicShare = useMemo(() => (keyDetails && (keyDetails.totalShares - parsedShares.length > 1)) || false, + [keyDetails, parsedShares.length]) + const hasPasswordShare = useMemo(() => parsedShares.filter((s) => s.module === SECURITY_QUESTIONS_MODULE_NAME).length > 0, + [parsedShares]) // Initialize Threshold Key and DirectAuth useEffect(() => { @@ -613,6 +632,37 @@ const ThresholdKeyProvider = ({ children, network = "mainnet", enableLogging = f } } + const deleteShare = async (shareIndex: string) => { + if (!TKeySdk) return + try { + await TKeySdk.deleteShare(shareIndex) + const newKeyDetails = await TKeySdk.getKeyDetails() + setKeyDetails(newKeyDetails) + } catch (e) { + console.error(e) + return Promise.reject(e) + } + } + + const getSerializedDeviceShare = async (shareIndex: string) => { + if (!TKeySdk) return + try { + return await TKeySdk.outputShare(shareIndex, "mnemonic") as string + } catch (e) { + console.error(e) + return Promise.reject(e) + } + } + + const getAvailableShareIndices = () => { + if (!TKeySdk) return + + const pubPoly = TKeySdk.metadata.getLatestPublicPolynomial() + const polyId = pubPoly.getPolynomialID() + const shareStoreMap = TKeySdk.shares[polyId] + return Object.keys(shareStoreMap) + } + const encryptForPublicKey = async (publicKey: string, message: string) => { const messageCipher = await EthCrypto.encryptWithPublicKey( publicKey, @@ -658,12 +708,23 @@ const ThresholdKeyProvider = ({ children, network = "mainnet", enableLogging = f }) const serviceProvider = (tkey.serviceProvider as unknown) as DirectAuthSdk - await serviceProvider.init({ skipSw: false }).then(() => { - console.log("initialized") - setStatus("initialized") - }).catch(() => "error initializing") - setTKeySdk(tkey) - logout() + serviceProvider.init({ skipSw: false }) + .then(() => { + setStatus("initialized") + }) + .catch((e) => console.error("error initializing", e)) + .finally(() => { + setTKeySdk(tkey) + logout() + }) + } + + const refreshTKeyMeta = async () => { + if (!TKeySdk) return + + await TKeySdk.syncShareMetadata() + const newKeyDetails = await TKeySdk.getKeyDetails() + setKeyDetails(newKeyDetails) } return ( @@ -677,6 +738,8 @@ const ThresholdKeyProvider = ({ children, network = "mainnet", enableLogging = f inputMnemonicShare, keyDetails, addNewDeviceShareAndSave, + deleteShare, + getSerializedDeviceShare, isNewDevice, pendingShareTransferRequests, approveShareTransferRequest, @@ -696,6 +759,8 @@ const ThresholdKeyProvider = ({ children, network = "mainnet", enableLogging = f hasPasswordShare, status, resetStatus: () => setStatus("initialized"), + getAvailableShareIndices, + refreshTKeyMeta, loggedinAs }} > diff --git a/packages/files-ui/src/locales/en/messages.po b/packages/files-ui/src/locales/en/messages.po index 294fe48ee4..778241cc30 100644 --- a/packages/files-ui/src/locales/en/messages.po +++ b/packages/files-ui/src/locales/en/messages.po @@ -13,7 +13,7 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" -#: src/Components/Modules/Settings/Security/index.tsx:222 +#: src/Components/Modules/Settings/Security/index.tsx:230 msgid "(Change)" msgstr "(Change)" @@ -21,7 +21,7 @@ msgstr "(Change)" msgid "A backup phrase will be generated and used for your account.<0/>We do not store it and <1>it can only be displayed once. Save it somewhere safe!" msgstr "A backup phrase will be generated and used for your account.<0/>We do not store it and <1>it can only be displayed once. Save it somewhere safe!" -#: src/Components/Modules/Settings/Security/index.tsx:250 +#: src/Components/Modules/Settings/Security/index.tsx:258 msgid "A backup phrase will be generated for your account.<0/>We do not store it and <1>it can only be displayed once. Please save it somewhere safe!" msgstr "A backup phrase will be generated for your account.<0/>We do not store it and <1>it can only be displayed once. Please save it somewhere safe!" @@ -37,17 +37,25 @@ msgstr "Account" msgid "Add and change passwords" msgstr "Add and change passwords" +#: src/Components/Modules/Settings/Security/index.tsx:205 +msgid "Add at least one more authentication method to protect your account. You’d only need any two to sign in to Files from any device." +msgstr "Add at least one more authentication method to protect your account. You’d only need any two to sign in to Files from any device." + #: src/Components/Modules/Settings/Security/index.tsx:197 -msgid "Add at least one more sign-in method to protect your account for account recovery. You’d only need any two to sign in to Files from any device." -msgstr "Add at least one more sign-in method to protect your account for account recovery. You’d only need any two to sign in to Files from any device." +#~ msgid "Add at least one more sign-in method to protect your account for account recovery. You’d only need any two to sign in to Files from any device." +#~ msgstr "Add at least one more sign-in method to protect your account for account recovery. You’d only need any two to sign in to Files from any device." #: src/Components/Modules/UploadFileModule.tsx:112 msgid "Add more files" msgstr "Add more files" #: src/Components/Modules/LoginModule/SignInMethods.tsx:222 -msgid "Add sign-in Methods" -msgstr "Add sign-in Methods" +#~ msgid "Add sign-in Methods" +#~ msgstr "Add sign-in Methods" + +#: src/Components/Modules/LoginModule/SignInMethods.tsx:211 +msgid "Add sign-in methods" +msgstr "Add sign-in methods" #: src/Components/Elements/ShareTransferRequestModal.tsx:75 msgid "Approve" @@ -61,19 +69,19 @@ msgstr "Are you sure you wish to delete?" msgid "Are you sure?" msgstr "Are you sure?" -#: src/Components/Modules/Settings/Security/index.tsx:260 +#: src/Components/Modules/Settings/Security/index.tsx:268 msgid "Backup Phrase" msgstr "Backup Phrase" -#: src/Components/Modules/LoginModule/Complete.tsx:143 +#: src/Components/Modules/LoginModule/Complete.tsx:127 msgid "Backup phrase" msgstr "Backup phrase" -#: src/Components/Modules/LoginModule/MissingShares.tsx:139 +#: src/Components/Modules/LoginModule/MissingShares.tsx:132 msgid "Backup phrase does not match user account, please double-check and try again." msgstr "Backup phrase does not match user account, please double-check and try again." -#: src/Components/Modules/LoginModule/SignInMethods.tsx:212 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:201 msgid "Backup phrase saved" msgstr "Backup phrase saved" @@ -82,7 +90,12 @@ msgstr "Backup phrase saved" msgid "Bin" msgstr "Bin" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:243 +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:115 +msgid "Browser:" +msgstr "Browser:" + +#: src/Components/Modules/LoginModule/InitialScreen.tsx:249 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:278 msgid "By connecting your wallet, you agree to our terms and privacy policy." msgstr "By connecting your wallet, you agree to our terms and privacy policy." @@ -98,11 +111,11 @@ msgstr "CID (Content Identifier)" msgid "Cancel" msgstr "Cancel" -#: src/Components/Modules/Settings/Security/index.tsx:240 +#: src/Components/Modules/Settings/Security/index.tsx:248 msgid "Change Password" msgstr "Change Password" -#: src/Components/Modules/Settings/Security/index.tsx:233 +#: src/Components/Modules/Settings/Security/index.tsx:241 msgid "Change password" msgstr "Change password" @@ -118,7 +131,7 @@ msgstr "Click or drag to upload files" msgid "Close" msgstr "Close" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:252 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:241 msgid "Complete" msgstr "Complete" @@ -126,53 +139,53 @@ msgstr "Complete" msgid "Confirm" msgstr "Confirm" -#: src/Components/Elements/PasswordForm.tsx:82 +#: src/Components/Elements/PasswordForm.tsx:83 msgid "Confirm Password:" msgstr "Confirm Password:" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:248 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:254 msgid "Connect Wallet to Files" msgstr "Connect Wallet to Files" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:238 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:244 msgid "Connect a new wallet" msgstr "Connect a new wallet" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:256 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:283 msgid "Connection failed" msgstr "Connection failed" #: src/Components/Elements/MnemonicForm.tsx:103 -#: src/Components/Modules/LoginModule/Complete.tsx:151 +#: src/Components/Modules/LoginModule/Complete.tsx:135 #: src/Components/Modules/LoginModule/MigrateAccount.tsx:139 -#: src/Components/Modules/LoginModule/MissingShares.tsx:191 -#: src/Components/Modules/LoginModule/MissingShares.tsx:205 +#: src/Components/Modules/LoginModule/MissingShares.tsx:184 +#: src/Components/Modules/LoginModule/MissingShares.tsx:198 #: src/Components/Modules/LoginModule/SaveBackupPhrase.tsx:64 msgid "Continue" msgstr "Continue" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:205 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:211 msgid "Continue with Facebook" msgstr "Continue with Facebook" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:197 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:203 msgid "Continue with Github" msgstr "Continue with Github" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:201 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:207 msgid "Continue with Google" msgstr "Continue with Google" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:193 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:199 msgid "Continue with Web3 Wallet" msgstr "Continue with Web3 Wallet" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:235 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:241 msgid "Continue with {0}" msgstr "Continue with {0}" -#: src/Components/Elements/MnemonicForm.tsx:153 -#: src/Components/Modules/Settings/Profile.tsx:130 +#: src/Components/Elements/MnemonicForm.tsx:147 +#: src/Components/Modules/Settings/Profile.tsx:129 msgid "Copied!" msgstr "Copied!" @@ -180,7 +193,7 @@ msgstr "Copied!" msgid "Copy CID" msgstr "Copy CID" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:244 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:233 msgid "Copy backup phrase" msgstr "Copy backup phrase" @@ -231,6 +244,10 @@ msgstr "Download" msgid "Download complete" msgstr "Download complete" +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:125 +msgid "Download recovery key" +msgstr "Download recovery key" + #: src/Components/Modules/FileBrowsers/views/FilesTable.view.tsx:430 msgid "Drop to upload files" msgstr "Drop to upload files" @@ -239,16 +256,16 @@ msgstr "Drop to upload files" msgid "Encryption Password" msgstr "Encryption Password" -#: src/Components/Modules/LoginModule/MissingShares.tsx:172 +#: src/Components/Modules/LoginModule/MissingShares.tsx:165 msgid "Enter a password" msgstr "Enter a password" -#: src/Components/Modules/LoginModule/MissingShares.tsx:199 +#: src/Components/Modules/LoginModule/MissingShares.tsx:192 msgid "Enter backup phrase:" msgstr "Enter backup phrase:" #: src/Components/Modules/LoginModule/MigrateAccount.tsx:135 -#: src/Components/Modules/LoginModule/MissingShares.tsx:187 +#: src/Components/Modules/LoginModule/MissingShares.tsx:180 msgid "Enter password:" msgstr "Enter password:" @@ -256,7 +273,7 @@ msgstr "Enter password:" msgid "Essentials - Free" msgstr "Essentials - Free" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:171 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:177 msgid "Failed to get signature" msgstr "Failed to get signature" @@ -264,7 +281,7 @@ msgstr "Failed to get signature" msgid "Failed to migrate account, please try again." msgstr "Failed to migrate account, please try again." -#: src/Components/Modules/LoginModule/InitialScreen.tsx:164 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:170 msgid "" "Failed to validate signature.\n" "If you are using a contract wallet, please make \n" @@ -305,7 +322,7 @@ msgstr "File size" msgid "Files" msgstr "Files" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:193 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:182 msgid "Files uses device backups to save your browser." msgstr "Files uses device backups to save your browser." @@ -324,36 +341,48 @@ msgstr "Folder created successfully" msgid "Folders" msgstr "Folders" +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:134 +msgid "Forget this browser" +msgstr "Forget this browser" + +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:130 +msgid "Forgetting this browser deletes this from your list of sign-in methods. You will not be able to forget a browser if you only have two methods set up." +msgstr "Forgetting this browser deletes this from your list of sign-in methods. You will not be able to forget a browser if you only have two methods set up." + #: src/Components/Modules/FileBrowsers/FileInfoModal.tsx:155 msgid "General" msgstr "General" #: src/Components/Modules/LoginModule/SaveBackupPhrase.tsx:54 -#: src/Components/Modules/Settings/Security/index.tsx:245 -#: src/Components/Modules/Settings/Security/index.tsx:268 +#: src/Components/Modules/Settings/Security/index.tsx:253 +#: src/Components/Modules/Settings/Security/index.tsx:276 msgid "Generate backup phrase" msgstr "Generate backup phrase" -#: src/Components/Elements/MnemonicForm.tsx:146 +#: src/Components/Elements/MnemonicForm.tsx:140 msgid "Generate phrase" msgstr "Generate phrase" -#: src/Components/Elements/MnemonicForm.tsx:140 +#: src/Components/Elements/MnemonicForm.tsx:134 msgid "Generating..." msgstr "Generating..." -#: src/Components/Modules/LoginModule/InitialScreen.tsx:182 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:188 msgid "Get Started" msgstr "Get Started" -#: src/Components/Modules/LoginModule/Complete.tsx:99 +#: src/Components/Modules/LoginModule/Complete.tsx:83 msgid "Great! You’re all done." msgstr "Great! You’re all done." -#: src/Components/Modules/Settings/Security/index.tsx:162 +#: src/Components/Modules/Settings/Security/index.tsx:170 msgid "Hey! You only have two sign-in methods. If you lose that and have only one left, you will be locked out of your account forever." msgstr "Hey! You only have two sign-in methods. If you lose that and have only one left, you will be locked out of your account forever." +#: src/Components/Modules/LoginModule/InitialScreen.tsx:261 +msgid "Hold on, we are logging you in..." +msgstr "Hold on, we are logging you in..." + #: src/Components/Layouts/AppNav.tsx:240 msgid "Home" msgstr "Home" @@ -376,15 +405,15 @@ msgstr "" msgid "Introducing multi-factor sign in" msgstr "Introducing multi-factor sign in" -#: src/Components/Modules/Settings/Security/index.tsx:255 +#: src/Components/Modules/Settings/Security/index.tsx:263 msgid "I’m done saving my backup phrase" msgstr "I’m done saving my backup phrase" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:194 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:183 msgid "Learn more" msgstr "Learn more" -#: src/Components/Pages/LoginPage.tsx:187 +#: src/Components/Pages/LoginPage.tsx:191 msgid "Learn more about ChainSafe" msgstr "Learn more about ChainSafe" @@ -401,23 +430,27 @@ msgstr "Light mode" msgid "Loading preview" msgstr "Loading preview" +#: src/Contexts/ThresholdKeyContext.tsx:269 +msgid "Logged in with" +msgstr "Logged in with" + #: src/Components/Modules/hooks/useLoggedInAs.ts:18 -msgid "Logged in with Facebook" -msgstr "Logged in with Facebook" +#~ msgid "Logged in with Facebook" +#~ msgstr "Logged in with Facebook" #: src/Components/Modules/hooks/useLoggedInAs.ts:21 -msgid "Logged in with Github" -msgstr "Logged in with Github" +#~ msgid "Logged in with Github" +#~ msgstr "Logged in with Github" #: src/Components/Modules/hooks/useLoggedInAs.ts:24 -msgid "Logged in with Google" -msgstr "Logged in with Google" +#~ msgid "Logged in with Google" +#~ msgstr "Logged in with Google" -#: src/Components/Modules/hooks/useLoggedInAs.ts:15 +#: src/Contexts/ThresholdKeyContext.tsx:264 msgid "Logged in with Web3" msgstr "Logged in with Web3" -#: src/Components/Modules/LoginModule/MissingShares.tsx:165 +#: src/Components/Modules/LoginModule/MissingShares.tsx:158 msgid "Looks like you’re signing in from a new browser. Please choose one of the following to continue:" msgstr "Looks like you’re signing in from a new browser. Please choose one of the following to continue:" @@ -479,44 +512,48 @@ msgstr "OK" msgid "One sec, getting files ready..." msgstr "One sec, getting files ready..." -#: src/Components/Modules/LoginModule/MissingShares.tsx:179 +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:112 +msgid "Operating system:" +msgstr "Operating system:" + +#: src/Components/Modules/LoginModule/MissingShares.tsx:172 msgid "Or confirm by signing into your Files on any browser you’ve used before." msgstr "Or confirm by signing into your Files on any browser you’ve used before." -#: src/Components/Modules/Settings/Security/index.tsx:207 +#: src/Components/Modules/Settings/Security/index.tsx:215 msgid "Password" msgstr "Password" -#: src/Components/Elements/PasswordForm.tsx:60 +#: src/Components/Elements/PasswordForm.tsx:61 msgid "Password confirmation is required" msgstr "Password confirmation is required" #: src/Components/Modules/LoginModule/MigrateAccount.tsx:110 -#: src/Components/Modules/LoginModule/MissingShares.tsx:128 +#: src/Components/Modules/LoginModule/MissingShares.tsx:121 msgid "Password does not match user account, please double-check and try again." msgstr "Password does not match user account, please double-check and try again." -#: src/Components/Elements/PasswordForm.tsx:46 +#: src/Components/Elements/PasswordForm.tsx:47 msgid "Password needs to be more complex" msgstr "Password needs to be more complex" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:201 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:190 msgid "Password set" msgstr "Password set" -#: src/Components/Modules/LoginModule/Complete.tsx:133 +#: src/Components/Modules/LoginModule/Complete.tsx:117 msgid "Password setup" msgstr "Password setup" -#: src/Components/Elements/PasswordForm.tsx:81 +#: src/Components/Elements/PasswordForm.tsx:82 msgid "Password:" msgstr "Password:" -#: src/Components/Elements/PasswordForm.tsx:59 +#: src/Components/Elements/PasswordForm.tsx:60 msgid "Passwords must match" msgstr "Passwords must match" -#: src/Components/Elements/PasswordForm.tsx:56 +#: src/Components/Elements/PasswordForm.tsx:57 msgid "Please provide a password" msgstr "Please provide a password" @@ -538,7 +575,7 @@ msgstr "" "We’re happy to announce that you don’t need a password to sign in anymore. \n" "All you have to do is set up multiple sign-in methods." -#: src/Components/Modules/LoginModule/InitialScreen.tsx:216 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:222 msgid "Privacy Policy" msgstr "Privacy Policy" @@ -562,7 +599,7 @@ msgstr "Recover with passphrase" msgid "Reject" msgstr "Reject" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:256 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:245 msgid "Remind me later" msgstr "Remind me later" @@ -582,11 +619,11 @@ msgstr "Requested from" msgid "Resources" msgstr "Resources" -#: src/Components/Modules/LoginModule/MissingShares.tsx:175 +#: src/Components/Modules/LoginModule/MissingShares.tsx:168 msgid "Restore with backup phrase" msgstr "Restore with backup phrase" -#: src/Components/Modules/Settings/Profile.tsx:154 +#: src/Components/Modules/Settings/Profile.tsx:153 msgid "Save changes" msgstr "Save changes" @@ -598,20 +635,24 @@ msgstr "Save the device" msgid "Save this browser for next time?" msgstr "Save this browser for next time?" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:187 -#: src/Components/Modules/Settings/Security/index.tsx:188 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:176 +#: src/Components/Modules/Settings/Security/index.tsx:196 msgid "Saved" msgstr "Saved" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:182 -#: src/Components/Modules/Settings/Security/index.tsx:183 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:171 +#: src/Components/Modules/Settings/Security/index.tsx:191 msgid "Saved Browser" msgstr "Saved Browser" -#: src/Components/Modules/LoginModule/Complete.tsx:123 +#: src/Components/Modules/LoginModule/Complete.tsx:107 msgid "Saved browser" msgstr "Saved browser" +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:118 +msgid "Saved on:" +msgstr "Saved on:" + #: src/Components/Modules/FileBrowsers/SearchFileBrowser.tsx:56 msgid "Search results" msgstr "Search results" @@ -624,27 +665,31 @@ msgstr "Search..." msgid "Security" msgstr "Security" +#: src/Components/Modules/LoginModule/InitialScreen.tsx:270 +msgid "Select a wallet" +msgstr "Select a wallet" + #: src/Components/Layouts/AppNav.tsx:270 msgid "Send Feedback" msgstr "Send Feedback" -#: src/Components/Elements/PasswordForm.tsx:42 -#: src/Components/Modules/Settings/Security/index.tsx:240 +#: src/Components/Elements/PasswordForm.tsx:43 +#: src/Components/Modules/Settings/Security/index.tsx:248 msgid "Set Password" msgstr "Set Password" -#: src/Components/Modules/Settings/Security/index.tsx:220 -#: src/Components/Modules/Settings/Security/index.tsx:273 +#: src/Components/Modules/Settings/Security/index.tsx:228 +#: src/Components/Modules/Settings/Security/index.tsx:281 msgid "Set up" msgstr "Set up" #: src/Components/Modules/LoginModule/PasswordSetup.tsx:55 -#: src/Components/Modules/LoginModule/SignInMethods.tsx:236 -#: src/Components/Modules/Settings/Security/index.tsx:236 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:225 +#: src/Components/Modules/Settings/Security/index.tsx:244 msgid "Set up a password" msgstr "Set up a password" -#: src/Components/Modules/Settings/Security/index.tsx:215 +#: src/Components/Modules/Settings/Security/index.tsx:223 msgid "Set up password" msgstr "Set up password" @@ -679,20 +724,21 @@ msgstr "Share" msgid "Sign Out" msgstr "Sign Out" -#: src/Components/Modules/LoginModule/MissingShares.tsx:161 +#: src/Components/Modules/LoginModule/MissingShares.tsx:154 msgid "Sign in" msgstr "Sign in" #: src/Components/Modules/LoginModule/MigrateAccount.tsx:148 -#: src/Components/Modules/LoginModule/MissingShares.tsx:215 +#: src/Components/Modules/LoginModule/MissingShares.tsx:208 msgid "Sign in with a different account" msgstr "Sign in with a different account" #: src/Components/Modules/LoginModule/SignInMethods.tsx:160 -msgid "Sign-in Methods" -msgstr "Sign-in Methods" +#~ msgid "Sign-in Methods" +#~ msgstr "Sign-in Methods" -#: src/Components/Modules/Settings/Security/index.tsx:159 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:149 +#: src/Components/Modules/Settings/Security/index.tsx:167 msgid "Sign-in methods" msgstr "Sign-in methods" @@ -700,12 +746,12 @@ msgstr "Sign-in methods" msgid "Size" msgstr "Size" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:168 -#: src/Components/Modules/Settings/Security/index.tsx:170 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:157 +#: src/Components/Modules/Settings/Security/index.tsx:178 msgid "Social Sign-in Wallet" msgstr "Social Sign-in Wallet" -#: src/Components/Modules/LoginModule/Complete.tsx:113 +#: src/Components/Modules/LoginModule/Complete.tsx:97 msgid "Social sign in or wallet" msgstr "Social sign in or wallet" @@ -729,24 +775,24 @@ msgstr "Stored by miner" msgid "Technical" msgstr "Technical" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:223 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:229 msgid "Terms and Conditions" msgstr "Terms and Conditions" -#: src/Components/Modules/LoginModule/Complete.tsx:104 +#: src/Components/Modules/LoginModule/Complete.tsx:88 msgid "Thanks for taking care of that. You can <0/> adjust these anytime in security settings." msgstr "Thanks for taking care of that. You can <0/> adjust these anytime in security settings." -#: src/Components/Modules/LoginModule/InitialScreen.tsx:174 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:180 msgid "The authentication popup was closed" msgstr "The authentication popup was closed" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:159 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:165 msgid "There was an error authenticating" msgstr "There was an error authenticating" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:134 -#: src/Components/Modules/LoginModule/InitialScreen.tsx:143 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:139 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:148 msgid "There was an error connecting your wallet" msgstr "There was an error connecting your wallet" @@ -787,11 +833,11 @@ msgstr "There was an error recovering this" msgid "There was an error renaming this file" msgstr "There was an error renaming this file" -#: src/Components/Modules/LoginModule/InitialScreen.tsx:261 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:288 msgid "Try again" msgstr "Try again" -#: src/Components/Modules/LoginModule/MissingShares.tsx:222 +#: src/Components/Modules/LoginModule/MissingShares.tsx:215 msgid "Try another method" msgstr "Try another method" @@ -808,19 +854,23 @@ msgstr "Upload" msgid "Upload complete" msgstr "Upload complete" +#: src/Components/Modules/LoginModule/InitialScreen.tsx:273 +msgid "Use a different login method" +msgstr "Use a different login method" + #: src/Components/Modules/FileBrowsers/views/FileSystemItemRow.tsx:231 msgid "View folder" msgstr "View folder" -#: src/Components/Modules/Settings/Profile.tsx:127 +#: src/Components/Modules/Settings/Profile.tsx:126 msgid "Wallet address" msgstr "Wallet address" -#: src/Components/Modules/LoginModule/SignInMethods.tsx:227 +#: src/Components/Modules/LoginModule/SignInMethods.tsx:216 msgid "We seriously advise that you add a third method. If you lose one of the two sign-in methods, you’ll lose access to your account forever. Plus, signing in on multiple devices will be easier." msgstr "We seriously advise that you add a third method. If you lose one of the two sign-in methods, you’ll lose access to your account forever. Plus, signing in on multiple devices will be easier." -#: src/Components/Modules/LoginModule/InitialScreen.tsx:208 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:214 msgid "We`'`re undergoing maintenance, thank you for being patient" msgstr "We`'`re undergoing maintenance, thank you for being patient" @@ -844,10 +894,14 @@ msgstr "Yes, save it" msgid "You can change this later." msgstr "You can change this later." -#: src/Components/Modules/LoginModule/InitialScreen.tsx:250 +#: src/Components/Modules/LoginModule/InitialScreen.tsx:257 msgid "You will need to sign a message in your wallet to complete sign in." msgstr "You will need to sign a message in your wallet to complete sign in." +#: src/Components/Modules/Settings/SavedBrowsers/BrowserPanel.tsx:122 +msgid "Your recovery key can be used to restore your account in place of your backup phrase." +msgstr "Your recovery key can be used to restore your account in place of your backup phrase." + #: src/Components/Layouts/AppNav.tsx:226 msgid "beta" msgstr "beta"