chore: ttag setup and authentication flow localization (#2987)
* chore: add ttag dependency * chore: wrap strings for authentication flows * chore: fix lint errors
This commit is contained in:
committed by
GitHub
parent
92b7be4221
commit
7f3d2d0c72
BIN
.yarn/cache/dedent-npm-1.5.1-8d0a005200-c3c300a14e.zip
vendored
Normal file
BIN
.yarn/cache/dedent-npm-1.5.1-8d0a005200-c3c300a14e.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/plural-forms-npm-0.5.5-17e30e89ab-97e1ff5bb6.zip
vendored
Normal file
BIN
.yarn/cache/plural-forms-npm-0.5.5-17e30e89ab-97e1ff5bb6.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/ttag-npm-1.8.12-a48f025d37-7bb7713fdc.zip
vendored
Normal file
BIN
.yarn/cache/ttag-npm-1.8.12-a48f025d37-7bb7713fdc.zip
vendored
Normal file
Binary file not shown.
@@ -120,6 +120,7 @@
|
|||||||
"comlink": "^4.4.1",
|
"comlink": "^4.4.1",
|
||||||
"fast-diff": "^1.3.0",
|
"fast-diff": "^1.3.0",
|
||||||
"lexical": "0.38.1",
|
"lexical": "0.38.1",
|
||||||
|
"ttag": "^1.8.12",
|
||||||
"unicode-script": "^1.2.0"
|
"unicode-script": "^1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { useCaptcha } from '@/Hooks/useCaptcha'
|
|||||||
import { isErrorResponse } from '@standardnotes/snjs'
|
import { isErrorResponse } from '@standardnotes/snjs'
|
||||||
import MergeLocalDataCheckbox from './MergeLocalDataCheckbox'
|
import MergeLocalDataCheckbox from './MergeLocalDataCheckbox'
|
||||||
import ConfirmNoMergeDialog from './ConfirmNoMergeDialog'
|
import ConfirmNoMergeDialog from './ConfirmNoMergeDialog'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
setMenuPane: (pane: AccountMenuPane) => void
|
setMenuPane: (pane: AccountMenuPane) => void
|
||||||
@@ -165,9 +166,9 @@ const ConfirmPassword: FunctionComponent<Props> = ({ setMenuPane, email, passwor
|
|||||||
const confirmPasswordForm = (
|
const confirmPasswordForm = (
|
||||||
<>
|
<>
|
||||||
<div className="mb-3 px-3 text-sm">
|
<div className="mb-3 px-3 text-sm">
|
||||||
Because your notes are encrypted using your password,{' '}
|
{c('Info').jt`Because your notes are encrypted using your password, ${(
|
||||||
<span className="text-danger">Standard Notes does not have a password reset option</span>. If you forget your
|
<span className="text-danger">Standard Notes does not have a password reset option</span>
|
||||||
password, you will permanently lose access to your data.
|
)}. If you forget your password, you will permanently lose access to your data.`}
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={handleConfirmFormSubmit} className="mb-1 px-3">
|
<form onSubmit={handleConfirmFormSubmit} className="mb-1 px-3">
|
||||||
{!isRegistering && (
|
{!isRegistering && (
|
||||||
@@ -177,7 +178,7 @@ const ConfirmPassword: FunctionComponent<Props> = ({ setMenuPane, email, passwor
|
|||||||
left={[<Icon type="password" className="text-neutral" />]}
|
left={[<Icon type="password" className="text-neutral" />]}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Confirm password"
|
placeholder={c('Label').t`Confirm password`}
|
||||||
ref={passwordInputRef}
|
ref={passwordInputRef}
|
||||||
value={confirmPassword}
|
value={confirmPassword}
|
||||||
/>
|
/>
|
||||||
@@ -187,13 +188,13 @@ const ConfirmPassword: FunctionComponent<Props> = ({ setMenuPane, email, passwor
|
|||||||
primary
|
primary
|
||||||
fullWidth
|
fullWidth
|
||||||
className="mb-3 mt-1"
|
className="mb-3 mt-1"
|
||||||
label={isRegistering ? 'Creating account...' : 'Create account & sign in'}
|
label={isRegistering ? c('Action').t`Creating account...` : c('Action').t`Create account & sign in`}
|
||||||
onClick={handleConfirmFormSubmit}
|
onClick={handleConfirmFormSubmit}
|
||||||
disabled={isRegistering}
|
disabled={isRegistering}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
name="is-ephemeral"
|
name="is-ephemeral"
|
||||||
label="Stay signed in"
|
label={c('Option').t`Stay signed in`}
|
||||||
checked={!isEphemeral}
|
checked={!isEphemeral}
|
||||||
onChange={handleEphemeralChange}
|
onChange={handleEphemeralChange}
|
||||||
disabled={isRegistering}
|
disabled={isRegistering}
|
||||||
@@ -215,13 +216,15 @@ const ConfirmPassword: FunctionComponent<Props> = ({ setMenuPane, email, passwor
|
|||||||
<div className="mb-3 mt-1 flex items-center px-3">
|
<div className="mb-3 mt-1 flex items-center px-3">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="arrow-left"
|
icon="arrow-left"
|
||||||
title="Go back"
|
title={c('Action').t`Go back`}
|
||||||
className="mr-2 flex p-0 text-neutral"
|
className="mr-2 flex p-0 text-neutral"
|
||||||
onClick={handleGoBack}
|
onClick={handleGoBack}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
disabled={isRegistering}
|
disabled={isRegistering}
|
||||||
/>
|
/>
|
||||||
<div className="text-base font-bold">{captchaURL ? 'Human verification' : 'Confirm password'}</div>
|
<div className="text-base font-bold">
|
||||||
|
{captchaURL ? c('Title').t`Human verification` : c('Title').t`Confirm password`}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{captchaURL ? <div className="p-[10px]">{captchaIframe}</div> : confirmPasswordForm}
|
{captchaURL ? <div className="p-[10px]">{captchaIframe}</div> : confirmPasswordForm}
|
||||||
{showNoMergeConfirmation && (
|
{showNoMergeConfirmation && (
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import Icon from '@/Components/Icon/Icon'
|
|||||||
import IconButton from '@/Components/Button/IconButton'
|
import IconButton from '@/Components/Button/IconButton'
|
||||||
import AdvancedOptions from './AdvancedOptions'
|
import AdvancedOptions from './AdvancedOptions'
|
||||||
import HorizontalSeparator from '../Shared/HorizontalSeparator'
|
import HorizontalSeparator from '../Shared/HorizontalSeparator'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
setMenuPane: (pane: AccountMenuPane) => void
|
setMenuPane: (pane: AccountMenuPane) => void
|
||||||
@@ -101,12 +102,12 @@ const CreateAccount: FunctionComponent<Props> = ({ setMenuPane, email, setEmail,
|
|||||||
<div className="mb-3 mt-1 flex items-center px-3">
|
<div className="mb-3 mt-1 flex items-center px-3">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="arrow-left"
|
icon="arrow-left"
|
||||||
title="Go back"
|
title={c('Action').t`Go back`}
|
||||||
className="mr-2 flex p-0 text-neutral"
|
className="mr-2 flex p-0 text-neutral"
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
/>
|
/>
|
||||||
<div className="text-base font-bold">Create account</div>
|
<div className="text-base font-bold">{c('Title').t`Create account`}</div>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={handleRegisterFormSubmit} className="mb-1 px-3">
|
<form onSubmit={handleRegisterFormSubmit} className="mb-1 px-3">
|
||||||
<DecoratedInput
|
<DecoratedInput
|
||||||
@@ -115,7 +116,7 @@ const CreateAccount: FunctionComponent<Props> = ({ setMenuPane, email, setEmail,
|
|||||||
left={[<Icon type="email" className="text-neutral" />]}
|
left={[<Icon type="email" className="text-neutral" />]}
|
||||||
onChange={handleEmailChange}
|
onChange={handleEmailChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Email"
|
placeholder={c('Label').t`Email`}
|
||||||
ref={emailInputRef}
|
ref={emailInputRef}
|
||||||
type="email"
|
type="email"
|
||||||
value={email}
|
value={email}
|
||||||
@@ -126,11 +127,17 @@ const CreateAccount: FunctionComponent<Props> = ({ setMenuPane, email, setEmail,
|
|||||||
left={[<Icon type="password" className="text-neutral" />]}
|
left={[<Icon type="password" className="text-neutral" />]}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Password"
|
placeholder={c('Label').t`Password`}
|
||||||
ref={passwordInputRef}
|
ref={passwordInputRef}
|
||||||
value={password}
|
value={password}
|
||||||
/>
|
/>
|
||||||
<Button className="mt-1" label="Next" primary onClick={handleRegisterFormSubmit} fullWidth={true} />
|
<Button
|
||||||
|
className="mt-1"
|
||||||
|
label={c('Action').t`Next`}
|
||||||
|
primary
|
||||||
|
onClick={handleRegisterFormSubmit}
|
||||||
|
fullWidth={true}
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
<HorizontalSeparator classes="my-2" />
|
<HorizontalSeparator classes="my-2" />
|
||||||
<AdvancedOptions onPrivateUsernameModeChange={onPrivateUsernameChange} />
|
<AdvancedOptions onPrivateUsernameModeChange={onPrivateUsernameChange} />
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { useApplication } from '../ApplicationProvider'
|
|||||||
import MenuSection from '../Menu/MenuSection'
|
import MenuSection from '../Menu/MenuSection'
|
||||||
import { TOGGLE_COMMAND_PALETTE, TOGGLE_KEYBOARD_SHORTCUTS_MODAL, isMobilePlatform } from '@standardnotes/ui-services'
|
import { TOGGLE_COMMAND_PALETTE, TOGGLE_KEYBOARD_SHORTCUTS_MODAL, isMobilePlatform } from '@standardnotes/ui-services'
|
||||||
import { KeyboardShortcutIndicator } from '../KeyboardShortcutIndicator/KeyboardShortcutIndicator'
|
import { KeyboardShortcutIndicator } from '../KeyboardShortcutIndicator/KeyboardShortcutIndicator'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
mainApplicationGroup: WebApplicationGroup
|
mainApplicationGroup: WebApplicationGroup
|
||||||
@@ -138,12 +139,12 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({ setMenuPane, closeMenu,
|
|||||||
<>
|
<>
|
||||||
<div className="mb-1 px-4 md:px-3">
|
<div className="mb-1 px-4 md:px-3">
|
||||||
<div className="mb-3 text-base text-foreground lg:text-sm">
|
<div className="mb-3 text-base text-foreground lg:text-sm">
|
||||||
You’re offline. Sign in to sync your notes and preferences across all your devices and enable end-to-end
|
{c('Info')
|
||||||
encryption.
|
.t`You’re offline. Sign in to sync your notes and preferences across all your devices and enable end-to-end encryption.`}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center text-passive-1">
|
<div className="flex items-center text-passive-1">
|
||||||
<Icon type="cloud-off" className={`mr-2 ${MenuItemIconSize}`} />
|
<Icon type="cloud-off" className={`mr-2 ${MenuItemIconSize}`} />
|
||||||
<span className="text-lg font-semibold lg:text-sm">Offline</span>
|
<span className="text-lg font-semibold lg:text-sm">{c('Status').t`Offline`}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -166,11 +167,11 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({ setMenuPane, closeMenu,
|
|||||||
<>
|
<>
|
||||||
<MenuItem onClick={activateRegisterPane}>
|
<MenuItem onClick={activateRegisterPane}>
|
||||||
<Icon type="user" className={iconClassName} />
|
<Icon type="user" className={iconClassName} />
|
||||||
Create free account
|
{c('Action').t`Create free account`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem onClick={activateSignInPane}>
|
<MenuItem onClick={activateSignInPane}>
|
||||||
<Icon type="signIn" className={iconClassName} />
|
<Icon type="signIn" className={iconClassName} />
|
||||||
Sign in
|
{c('Action').t`Sign in`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { useApplication } from '../ApplicationProvider'
|
|||||||
import { useCaptcha } from '@/Hooks/useCaptcha'
|
import { useCaptcha } from '@/Hooks/useCaptcha'
|
||||||
import MergeLocalDataCheckbox from './MergeLocalDataCheckbox'
|
import MergeLocalDataCheckbox from './MergeLocalDataCheckbox'
|
||||||
import ConfirmNoMergeDialog from './ConfirmNoMergeDialog'
|
import ConfirmNoMergeDialog from './ConfirmNoMergeDialog'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
setMenuPane: (pane: AccountMenuPane) => void
|
setMenuPane: (pane: AccountMenuPane) => void
|
||||||
@@ -252,7 +253,7 @@ const SignInPane: FunctionComponent<Props> = ({ setMenuPane }) => {
|
|||||||
className={{ container: `mb-2 ${error ? 'border-danger' : null}` }}
|
className={{ container: `mb-2 ${error ? 'border-danger' : null}` }}
|
||||||
left={[<Icon type="email" className="text-neutral" />]}
|
left={[<Icon type="email" className="text-neutral" />]}
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="Email"
|
placeholder={c('Label').t`Email`}
|
||||||
value={email}
|
value={email}
|
||||||
onChange={handleEmailChange}
|
onChange={handleEmailChange}
|
||||||
onFocus={resetInvalid}
|
onFocus={resetInvalid}
|
||||||
@@ -268,14 +269,14 @@ const SignInPane: FunctionComponent<Props> = ({ setMenuPane }) => {
|
|||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
onFocus={resetInvalid}
|
onFocus={resetInvalid}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Password"
|
placeholder={c('Label').t`Password`}
|
||||||
ref={passwordInputRef}
|
ref={passwordInputRef}
|
||||||
value={password}
|
value={password}
|
||||||
/>
|
/>
|
||||||
{error ? <div className="my-2 text-danger">{error}</div> : null}
|
{error ? <div className="my-2 text-danger">{error}</div> : null}
|
||||||
<Button
|
<Button
|
||||||
className="mb-3 mt-1"
|
className="mb-3 mt-1"
|
||||||
label={isSigningIn ? 'Signing in...' : 'Sign in'}
|
label={isSigningIn ? c('Action').t`Signing in...` : c('Action').t`Sign in`}
|
||||||
primary
|
primary
|
||||||
onClick={handleSignInFormSubmit}
|
onClick={handleSignInFormSubmit}
|
||||||
disabled={isSigningIn}
|
disabled={isSigningIn}
|
||||||
@@ -283,7 +284,7 @@ const SignInPane: FunctionComponent<Props> = ({ setMenuPane }) => {
|
|||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
name="is-ephemeral"
|
name="is-ephemeral"
|
||||||
label="Stay signed in"
|
label={c('Option').t`Stay signed in`}
|
||||||
checked={!isEphemeral}
|
checked={!isEphemeral}
|
||||||
disabled={isSigningIn || isRecoverySignIn}
|
disabled={isSigningIn || isRecoverySignIn}
|
||||||
onChange={handleEphemeralChange}
|
onChange={handleEphemeralChange}
|
||||||
@@ -325,13 +326,15 @@ const SignInPane: FunctionComponent<Props> = ({ setMenuPane }) => {
|
|||||||
<div className="mb-3 mt-1 flex items-center px-3">
|
<div className="mb-3 mt-1 flex items-center px-3">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="arrow-left"
|
icon="arrow-left"
|
||||||
title="Go back"
|
title={c('Action').t`Go back`}
|
||||||
className="mr-2 flex p-0 text-neutral"
|
className="mr-2 flex p-0 text-neutral"
|
||||||
onClick={() => setMenuPane(AccountMenuPane.GeneralMenu)}
|
onClick={() => setMenuPane(AccountMenuPane.GeneralMenu)}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
disabled={isSigningIn}
|
disabled={isSigningIn}
|
||||||
/>
|
/>
|
||||||
<div className="text-base font-bold">{showCaptcha ? 'Human verification' : 'Sign in'}</div>
|
<div className="text-base font-bold">
|
||||||
|
{showCaptcha ? c('Title').t`Human verification` : c('Title').t`Sign in`}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{showCaptcha ? <div className="p-[10px]">{captchaIframe}</div> : signInForm}
|
{showCaptcha ? <div className="p-[10px]">{captchaIframe}</div> : signInForm}
|
||||||
{showNoMergeConfirmation && (
|
{showNoMergeConfirmation && (
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { AccountIllustration } from '@standardnotes/icons'
|
|||||||
import { AccountMenuPane } from '@/Components/AccountMenu/AccountMenuPane'
|
import { AccountMenuPane } from '@/Components/AccountMenu/AccountMenuPane'
|
||||||
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
|
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
|
||||||
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
|
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -25,22 +26,24 @@ const Authentication: FunctionComponent<Props> = ({ application }) => {
|
|||||||
application.accountMenuController.setShow(true)
|
application.accountMenuController.setShow(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loginLink = (
|
||||||
|
<button className="cursor-pointer border-0 bg-default p-0 text-info underline" onClick={clickSignIn}>
|
||||||
|
{c('Action').t`Sign in`}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PreferencesGroup>
|
<PreferencesGroup>
|
||||||
<PreferencesSegment>
|
<PreferencesSegment>
|
||||||
<div className="flex flex-col items-center px-4 md:px-12">
|
<div className="flex flex-col items-center px-4 md:px-12">
|
||||||
<AccountIllustration className="mb-3" />
|
<AccountIllustration className="mb-3" />
|
||||||
<Title>You're not signed in</Title>
|
<Title>{c('Title').t`You're not signed in`}</Title>
|
||||||
<div className="mb-3 text-center text-base lg:text-sm">
|
<div className="mb-3 text-center text-base lg:text-sm">
|
||||||
Sign in to sync your notes and preferences across all your devices and enable end-to-end encryption.
|
{c('Info')
|
||||||
</div>
|
.t`Sign in to sync your notes and preferences across all your devices and enable end-to-end encryption.`}
|
||||||
<Button primary label="Create free account" onClick={clickRegister} className="mb-3" />
|
|
||||||
<div className="text-base lg:text-sm">
|
|
||||||
Already have an account?{' '}
|
|
||||||
<button className="cursor-pointer border-0 bg-default p-0 text-info underline" onClick={clickSignIn}>
|
|
||||||
Sign in
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<Button primary label={c('Action').t`Create free account`} onClick={clickRegister} className="mb-3" />
|
||||||
|
<div className="text-base lg:text-sm">{c('Info').jt`Already have an account? ${loginLink}`}</div>
|
||||||
</div>
|
</div>
|
||||||
</PreferencesSegment>
|
</PreferencesSegment>
|
||||||
</PreferencesGroup>
|
</PreferencesGroup>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { BlueDotIcon, CircleIcon, DiamondIcon, CreateAccountIllustration } from
|
|||||||
import { useCaptcha } from '@/Hooks/useCaptcha'
|
import { useCaptcha } from '@/Hooks/useCaptcha'
|
||||||
import { AccountMenuPane } from '../../AccountMenu/AccountMenuPane'
|
import { AccountMenuPane } from '../../AccountMenu/AccountMenuPane'
|
||||||
import { isErrorResponse } from '@standardnotes/snjs'
|
import { isErrorResponse } from '@standardnotes/snjs'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -150,19 +151,19 @@ const CreateAccount: FunctionComponent<Props> = ({ application }) => {
|
|||||||
className={`min-w-auto md:min-w-90 ${isEmailInvalid ? 'mb-2' : 'mb-4'}`}
|
className={`min-w-auto md:min-w-90 ${isEmailInvalid ? 'mb-2' : 'mb-4'}`}
|
||||||
id="purchase-sign-in-email"
|
id="purchase-sign-in-email"
|
||||||
type="email"
|
type="email"
|
||||||
label="Email"
|
label={c('Label').t`Email`}
|
||||||
value={email}
|
value={email}
|
||||||
onChange={handleEmailChange}
|
onChange={handleEmailChange}
|
||||||
ref={emailInputRef}
|
ref={emailInputRef}
|
||||||
disabled={isCreatingAccount}
|
disabled={isCreatingAccount}
|
||||||
isInvalid={isEmailInvalid}
|
isInvalid={isEmailInvalid}
|
||||||
/>
|
/>
|
||||||
{isEmailInvalid ? <div className="mb-4 text-danger">Please provide a valid email.</div> : null}
|
{isEmailInvalid ? <div className="mb-4 text-danger">{c('Error').t`Please provide a valid email.`}</div> : null}
|
||||||
<FloatingLabelInput
|
<FloatingLabelInput
|
||||||
className="min-w-auto mb-4 md:min-w-90"
|
className="min-w-auto mb-4 md:min-w-90"
|
||||||
id="purchase-create-account-password"
|
id="purchase-create-account-password"
|
||||||
type="password"
|
type="password"
|
||||||
label="Password"
|
label={c('Label').t`Password`}
|
||||||
value={password}
|
value={password}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
ref={passwordInputRef}
|
ref={passwordInputRef}
|
||||||
@@ -172,7 +173,7 @@ const CreateAccount: FunctionComponent<Props> = ({ application }) => {
|
|||||||
className={`min-w-auto md:min-w-90 ${isPasswordNotMatching ? 'mb-2' : 'mb-4'}`}
|
className={`min-w-auto md:min-w-90 ${isPasswordNotMatching ? 'mb-2' : 'mb-4'}`}
|
||||||
id="create-account-confirm"
|
id="create-account-confirm"
|
||||||
type="password"
|
type="password"
|
||||||
label="Repeat password"
|
label={c('Label').t`Repeat password`}
|
||||||
value={confirmPassword}
|
value={confirmPassword}
|
||||||
onChange={handleConfirmPasswordChange}
|
onChange={handleConfirmPasswordChange}
|
||||||
ref={confirmPasswordInputRef}
|
ref={confirmPasswordInputRef}
|
||||||
@@ -180,7 +181,7 @@ const CreateAccount: FunctionComponent<Props> = ({ application }) => {
|
|||||||
isInvalid={isPasswordNotMatching}
|
isInvalid={isPasswordNotMatching}
|
||||||
/>
|
/>
|
||||||
{isPasswordNotMatching ? (
|
{isPasswordNotMatching ? (
|
||||||
<div className="mb-4 text-danger">Passwords don't match. Please try again.</div>
|
<div className="mb-4 text-danger">{c('Error').t`Passwords don't match. Please try again.`}</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -197,8 +198,10 @@ const CreateAccount: FunctionComponent<Props> = ({ application }) => {
|
|||||||
<DiamondIcon className="absolute -right-2 top-0 -z-[1] h-18 w-18 translate-x-1/2" />
|
<DiamondIcon className="absolute -right-2 top-0 -z-[1] h-18 w-18 translate-x-1/2" />
|
||||||
|
|
||||||
<div className="mr-0 lg:mr-12">
|
<div className="mr-0 lg:mr-12">
|
||||||
<h1 className="mb-2 mt-0 text-2xl font-bold">Create your free account</h1>
|
// translator: Full sentence: "Create your free account"
|
||||||
<div className="mb-4 text-sm font-medium">to continue to Standard Notes.</div>
|
<h1 className="mb-2 mt-0 text-2xl font-bold">{c('Title').t`Create your free account`}</h1>
|
||||||
|
// translator: Full sentence: "Create your free account to continue to Standard Notes."
|
||||||
|
<div className="mb-4 text-sm font-medium">{c('Info').t`to continue to Standard Notes.`}</div>
|
||||||
{captchaURL ? captchaIframe : CreateAccountForm}
|
{captchaURL ? captchaIframe : CreateAccountForm}
|
||||||
<div className="flex flex-col-reverse items-start justify-between md:flex-row md:items-center">
|
<div className="flex flex-col-reverse items-start justify-between md:flex-row md:items-center">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
@@ -207,7 +210,8 @@ const CreateAccount: FunctionComponent<Props> = ({ application }) => {
|
|||||||
disabled={isCreatingAccount}
|
disabled={isCreatingAccount}
|
||||||
className="mb-2 flex cursor-pointer items-start border-0 bg-default p-0 font-medium text-info hover:underline"
|
className="mb-2 flex cursor-pointer items-start border-0 bg-default p-0 font-medium text-info hover:underline"
|
||||||
>
|
>
|
||||||
Sign in instead
|
// translator: "Instead" here refers to "instead of creating an account"
|
||||||
|
{c('Action').t`Sign in instead`}
|
||||||
</button>
|
</button>
|
||||||
{!application.isNativeIOS() && (
|
{!application.isNativeIOS() && (
|
||||||
<button
|
<button
|
||||||
@@ -215,14 +219,14 @@ const CreateAccount: FunctionComponent<Props> = ({ application }) => {
|
|||||||
disabled={isCreatingAccount}
|
disabled={isCreatingAccount}
|
||||||
className="flex cursor-pointer items-start border-0 bg-default p-0 font-medium text-info hover:underline"
|
className="flex cursor-pointer items-start border-0 bg-default p-0 font-medium text-info hover:underline"
|
||||||
>
|
>
|
||||||
Subscribe without account
|
{c('Action').t`Subscribe without account`}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
className="mb-4 py-2.5 md:mb-0"
|
className="mb-4 py-2.5 md:mb-0"
|
||||||
primary
|
primary
|
||||||
label={isCreatingAccount ? 'Creating account...' : 'Create account'}
|
label={isCreatingAccount ? c('Action').t`Creating account...` : c('Action').t`Create account`}
|
||||||
onClick={handleCreateAccount}
|
onClick={handleCreateAccount}
|
||||||
disabled={isCreatingAccount}
|
disabled={isCreatingAccount}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { isEmailValid } from '@/Utils'
|
|||||||
import { BlueDotIcon, CircleIcon, DiamondIcon } from '@standardnotes/icons'
|
import { BlueDotIcon, CircleIcon, DiamondIcon } from '@standardnotes/icons'
|
||||||
import { isErrorResponse, getCaptchaHeader } from '@standardnotes/snjs'
|
import { isErrorResponse, getCaptchaHeader } from '@standardnotes/snjs'
|
||||||
import { useCaptcha } from '@/Hooks/useCaptcha'
|
import { useCaptcha } from '@/Hooks/useCaptcha'
|
||||||
|
import { c } from 'ttag'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -102,7 +103,7 @@ const SignIn: FunctionComponent<Props> = ({ application }) => {
|
|||||||
if ((err as Error).toString().includes('Invalid email or password')) {
|
if ((err as Error).toString().includes('Invalid email or password')) {
|
||||||
setIsEmailInvalid(true)
|
setIsEmailInvalid(true)
|
||||||
setIsPasswordInvalid(true)
|
setIsPasswordInvalid(true)
|
||||||
setOtherErrorMessage('Invalid email or password.')
|
setOtherErrorMessage(c('Error').t`Invalid email or password.`)
|
||||||
setPassword('')
|
setPassword('')
|
||||||
} else {
|
} else {
|
||||||
application.alerts.alert(err as string).catch(console.error)
|
application.alerts.alert(err as string).catch(console.error)
|
||||||
@@ -119,7 +120,7 @@ const SignIn: FunctionComponent<Props> = ({ application }) => {
|
|||||||
className={`min-w-auto sm:min-w-90 ${isEmailInvalid && !otherErrorMessage ? 'mb-2' : 'mb-4'}`}
|
className={`min-w-auto sm:min-w-90 ${isEmailInvalid && !otherErrorMessage ? 'mb-2' : 'mb-4'}`}
|
||||||
id="purchase-sign-in-email"
|
id="purchase-sign-in-email"
|
||||||
type="email"
|
type="email"
|
||||||
label="Email"
|
label={c('Label').t`Email`}
|
||||||
value={email}
|
value={email}
|
||||||
onChange={handleEmailChange}
|
onChange={handleEmailChange}
|
||||||
ref={emailInputRef}
|
ref={emailInputRef}
|
||||||
@@ -127,13 +128,13 @@ const SignIn: FunctionComponent<Props> = ({ application }) => {
|
|||||||
isInvalid={isEmailInvalid}
|
isInvalid={isEmailInvalid}
|
||||||
/>
|
/>
|
||||||
{isEmailInvalid && !otherErrorMessage ? (
|
{isEmailInvalid && !otherErrorMessage ? (
|
||||||
<div className="mb-4 text-danger">Please provide a valid email.</div>
|
<div className="mb-4 text-danger">{c('Error').t`Please provide a valid email.`}</div>
|
||||||
) : null}
|
) : null}
|
||||||
<FloatingLabelInput
|
<FloatingLabelInput
|
||||||
className={`min-w-auto sm:min-w-90 ${otherErrorMessage ? 'mb-2' : 'mb-4'}`}
|
className={`min-w-auto sm:min-w-90 ${otherErrorMessage ? 'mb-2' : 'mb-4'}`}
|
||||||
id="purchase-sign-in-password"
|
id="purchase-sign-in-password"
|
||||||
type="password"
|
type="password"
|
||||||
label="Password"
|
label={c('Label').t`Password`}
|
||||||
value={password}
|
value={password}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
ref={passwordInputRef}
|
ref={passwordInputRef}
|
||||||
@@ -145,7 +146,7 @@ const SignIn: FunctionComponent<Props> = ({ application }) => {
|
|||||||
<Button
|
<Button
|
||||||
className={`${isSigningIn ? 'min-w-30' : 'min-w-24'} mb-5 py-2.5`}
|
className={`${isSigningIn ? 'min-w-30' : 'min-w-24'} mb-5 py-2.5`}
|
||||||
primary
|
primary
|
||||||
label={isSigningIn ? 'Signing in...' : 'Sign in'}
|
label={isSigningIn ? c('Action').t`Signing in...` : c('Action').t`Sign in`}
|
||||||
onClick={handleSignIn}
|
onClick={handleSignIn}
|
||||||
disabled={isSigningIn}
|
disabled={isSigningIn}
|
||||||
/>
|
/>
|
||||||
@@ -163,17 +164,18 @@ const SignIn: FunctionComponent<Props> = ({ application }) => {
|
|||||||
<DiamondIcon className="absolute -right-2 top-0 -z-[1] h-18 w-18 translate-x-1/2" />
|
<DiamondIcon className="absolute -right-2 top-0 -z-[1] h-18 w-18 translate-x-1/2" />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h1 className="mb-2 mt-0 text-2xl font-bold">Sign in</h1>
|
<h1 className="mb-2 mt-0 text-2xl font-bold">{c('Title').t`Sign in`}</h1>
|
||||||
<div className="mb-4 text-sm font-medium">to continue to Standard Notes.</div>
|
<div className="mb-4 text-sm font-medium">{c('Info').t`to continue to Standard Notes.`}</div>
|
||||||
{showCaptcha ? captchaIframe : signInForm}
|
{showCaptcha ? captchaIframe : signInForm}
|
||||||
<div className="text-sm font-medium text-passive-1">
|
<div className="text-sm font-medium text-passive-1">
|
||||||
Don’t have an account yet?{' '}
|
{c('Info').jt`Don’t have an account yet? ${(
|
||||||
<a
|
<a
|
||||||
className={`text-info ${isSigningIn ? 'cursor-not-allowed' : 'cursor-pointer '}`}
|
className={`text-info ${isSigningIn ? 'cursor-not-allowed' : 'cursor-pointer '}`}
|
||||||
onClick={handleCreateAccountInstead}
|
onClick={handleCreateAccountInstead}
|
||||||
>
|
>
|
||||||
Create account
|
{c('Action').t`Create account`}
|
||||||
</a>
|
</a>
|
||||||
|
)}`}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
30
yarn.lock
30
yarn.lock
@@ -9239,6 +9239,7 @@ __metadata:
|
|||||||
tailwindcss: ^3.4.0
|
tailwindcss: ^3.4.0
|
||||||
ts-jest: ^29.0.3
|
ts-jest: ^29.0.3
|
||||||
ts-loader: ^9.4.2
|
ts-loader: ^9.4.2
|
||||||
|
ttag: ^1.8.12
|
||||||
typescript: "*"
|
typescript: "*"
|
||||||
unicode-script: ^1.2.0
|
unicode-script: ^1.2.0
|
||||||
webextension-polyfill: ^0.10.0
|
webextension-polyfill: ^0.10.0
|
||||||
@@ -14484,6 +14485,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"dedent@npm:1.5.1":
|
||||||
|
version: 1.5.1
|
||||||
|
resolution: "dedent@npm:1.5.1"
|
||||||
|
peerDependencies:
|
||||||
|
babel-plugin-macros: ^3.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
babel-plugin-macros:
|
||||||
|
optional: true
|
||||||
|
checksum: c3c300a14edf1bdf5a873f9e4b22e839d62490bc5c8d6169c1f15858a1a76733d06a9a56930e963d677a2ceeca4b6b0894cc5ea2f501aa382ca5b92af3413c2a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"dedent@npm:^1.0.0":
|
"dedent@npm:^1.0.0":
|
||||||
version: 1.3.0
|
version: 1.3.0
|
||||||
resolution: "dedent@npm:1.3.0"
|
resolution: "dedent@npm:1.3.0"
|
||||||
@@ -24214,6 +24227,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"plural-forms@npm:^0.5.3":
|
||||||
|
version: 0.5.5
|
||||||
|
resolution: "plural-forms@npm:0.5.5"
|
||||||
|
checksum: 97e1ff5bb63c6aaad1150a7118a5d17dcbe19aa194be464b5384f5aad6480e299edc40afa22784ebbd2a7265790eab91872d633eddd53d866d47e3d721107a43
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"pod-install@npm:^0.3.5":
|
"pod-install@npm:^0.3.5":
|
||||||
version: 0.3.7
|
version: 0.3.7
|
||||||
resolution: "pod-install@npm:0.3.7"
|
resolution: "pod-install@npm:0.3.7"
|
||||||
@@ -28394,6 +28414,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ttag@npm:^1.8.12":
|
||||||
|
version: 1.8.12
|
||||||
|
resolution: "ttag@npm:1.8.12"
|
||||||
|
dependencies:
|
||||||
|
dedent: 1.5.1
|
||||||
|
plural-forms: ^0.5.3
|
||||||
|
checksum: 7bb7713fdcd846c69884eadb28cf27df0043a2f91a0350a8270d55da2c87f362a1406d8ffae890b99f0fec7691e8955c47ac95a2e6c89f6dac3154a380ff71ca
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tuf-js@npm:^1.1.7":
|
"tuf-js@npm:^1.1.7":
|
||||||
version: 1.1.7
|
version: 1.1.7
|
||||||
resolution: "tuf-js@npm:1.1.7"
|
resolution: "tuf-js@npm:1.1.7"
|
||||||
|
|||||||
Reference in New Issue
Block a user