mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Merge pull request #1851 from warrickct/simplify-onboarding
Combining registration steps.
This commit is contained in:
commit
eed48094fe
|
@ -340,7 +340,7 @@
|
|||
"createAccount": "Create account",
|
||||
"signIn": "Sign In",
|
||||
"yourUniqueSessionID": "Say hello to your Session ID",
|
||||
"allUsersAreRandomly...": "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.",
|
||||
"signupSessionIDBlurb": "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.",
|
||||
"getStarted": "Get started",
|
||||
"createSessionID": "Create Session ID",
|
||||
"recoveryPhrase": "Recovery Phrase",
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
color: themed('textColor');
|
||||
}
|
||||
font-weight: bold;
|
||||
padding: 12px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
&__welcome-session {
|
||||
|
@ -278,7 +278,7 @@
|
|||
|
||||
&-description-long,
|
||||
&-signin-device-pairing-header {
|
||||
padding-top: 10px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 20px;
|
||||
@include themify($themes) {
|
||||
@include session-color-subtle(themed('textColor'));
|
||||
|
|
|
@ -9,7 +9,7 @@ import { SessionButton, SessionButtonColor, SessionButtonType } from '../session
|
|||
import { SessionIconButton, SessionIconSize, SessionIconType } from '../session/icon';
|
||||
import { PillDivider } from '../session/PillDivider';
|
||||
import { SyncUtils, ToastUtils, UserUtils } from '../../session/utils';
|
||||
import { MAX_USERNAME_LENGTH } from '../session/registration/RegistrationTabs';
|
||||
import { MAX_USERNAME_LENGTH } from '../session/registration/RegistrationStages';
|
||||
import { SessionSpinner } from '../session/SessionSpinner';
|
||||
import { ConversationModel, ConversationTypeEnum } from '../../models/conversation';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { AccentText } from './AccentText';
|
||||
|
||||
import { RegistrationTabs } from './registration/RegistrationTabs';
|
||||
import { RegistrationStages } from './registration/RegistrationStages';
|
||||
import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
|
||||
import { SessionToastContainer } from './SessionToastContainer';
|
||||
import { lightTheme, SessionTheme } from '../../state/ducks/SessionTheme';
|
||||
|
@ -36,7 +36,7 @@ export const SessionRegistrationView = () => {
|
|||
<AccentText />
|
||||
</div>
|
||||
<div className="session-content-registration">
|
||||
<RegistrationTabs theme={lightTheme} />
|
||||
<RegistrationStages />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import React from 'react';
|
||||
|
||||
import React, { createContext, useEffect, useState } from 'react';
|
||||
import { PromiseUtils, StringUtils, ToastUtils, UserUtils } from '../../../session/utils';
|
||||
import { getConversationController } from '../../../session/conversations';
|
||||
import { createOrUpdateItem, removeAll } from '../../../data/data';
|
||||
import { SignUpTab } from './SignUpTab';
|
||||
import { SignInTab } from './SignInTab';
|
||||
import { TabLabel, TabType } from './TabLabel';
|
||||
import { trigger } from '../../../shims/events';
|
||||
import {
|
||||
generateMnemonic,
|
||||
|
@ -21,12 +19,6 @@ import { getSwarmPollingInstance } from '../../../session/snode_api/swarmPolling
|
|||
export const MAX_USERNAME_LENGTH = 20;
|
||||
// tslint:disable: use-simple-attributes
|
||||
|
||||
interface State {
|
||||
selectedTab: TabType;
|
||||
generatedRecoveryPhrase: string;
|
||||
hexGeneratedPubKey: string;
|
||||
}
|
||||
|
||||
export async function resetRegistration() {
|
||||
await removeAll();
|
||||
await window.storage.reset();
|
||||
|
@ -158,45 +150,39 @@ export async function signInWithLinking(signInDetails: { userRecoveryPhrase: str
|
|||
window?.log?.warn('exception during registration:', e);
|
||||
}
|
||||
}
|
||||
export class RegistrationTabs extends React.Component<any, State> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedTab: TabType.SignUp,
|
||||
generatedRecoveryPhrase: '',
|
||||
hexGeneratedPubKey: '',
|
||||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
void this.generateMnemonicAndKeyPair();
|
||||
export enum RegistrationPhase {
|
||||
Start,
|
||||
SignIn,
|
||||
SignUp,
|
||||
}
|
||||
|
||||
interface RegistrationPhaseContext {
|
||||
registrationPhase: RegistrationPhase;
|
||||
setRegistrationPhase: (phase: RegistrationPhase) => void;
|
||||
generatedRecoveryPhrase: string;
|
||||
hexGeneratedPubKey: string;
|
||||
}
|
||||
|
||||
export const RegistrationContext = createContext<RegistrationPhaseContext>({
|
||||
registrationPhase: RegistrationPhase.Start,
|
||||
setRegistrationPhase: () => undefined,
|
||||
generatedRecoveryPhrase: '',
|
||||
hexGeneratedPubKey: '',
|
||||
});
|
||||
|
||||
export const RegistrationStages = () => {
|
||||
const [generatedRecoveryPhrase, setGeneratedRecoveryPhrase] = useState('');
|
||||
const [hexGeneratedPubKey, setHexGeneratedPubKey] = useState('');
|
||||
const [registrationPhase, setRegistrationPhase] = useState(RegistrationPhase.Start);
|
||||
|
||||
useEffect(() => {
|
||||
void generateMnemonicAndKeyPair();
|
||||
void resetRegistration();
|
||||
}
|
||||
}, []);
|
||||
|
||||
public render() {
|
||||
const { selectedTab } = this.state;
|
||||
|
||||
return (
|
||||
<div className="session-registration-container">
|
||||
<div className="session-registration__tab-container">
|
||||
<TabLabel
|
||||
type={TabType.SignUp}
|
||||
isSelected={selectedTab === TabType.SignUp}
|
||||
onSelect={this.handleTabSelect}
|
||||
/>
|
||||
<TabLabel
|
||||
type={TabType.SignIn}
|
||||
isSelected={selectedTab === TabType.SignIn}
|
||||
onSelect={this.handleTabSelect}
|
||||
/>
|
||||
</div>
|
||||
{this.renderSections()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private async generateMnemonicAndKeyPair() {
|
||||
if (this.state.generatedRecoveryPhrase === '') {
|
||||
const generateMnemonicAndKeyPair = async () => {
|
||||
if (generatedRecoveryPhrase === '') {
|
||||
const mnemonic = await generateMnemonic();
|
||||
|
||||
let seedHex = mn_decode(mnemonic);
|
||||
|
@ -208,32 +194,28 @@ export class RegistrationTabs extends React.Component<any, State> {
|
|||
}
|
||||
const seed = fromHex(seedHex);
|
||||
const keyPair = await sessionGenerateKeyPair(seed);
|
||||
const hexGeneratedPubKey = StringUtils.decode(keyPair.pubKey, 'hex');
|
||||
const newHexPubKey = StringUtils.decode(keyPair.pubKey, 'hex');
|
||||
|
||||
this.setState({
|
||||
generatedRecoveryPhrase: mnemonic,
|
||||
hexGeneratedPubKey, // our 'frontend' sessionID
|
||||
});
|
||||
setGeneratedRecoveryPhrase(mnemonic);
|
||||
setHexGeneratedPubKey(newHexPubKey); // our 'frontend' sessionID
|
||||
}
|
||||
}
|
||||
|
||||
private readonly handleTabSelect = (tabType: TabType): void => {
|
||||
this.setState({
|
||||
selectedTab: tabType,
|
||||
});
|
||||
};
|
||||
|
||||
private renderSections() {
|
||||
const { selectedTab, generatedRecoveryPhrase, hexGeneratedPubKey } = this.state;
|
||||
if (selectedTab === TabType.SignUp) {
|
||||
return (
|
||||
<SignUpTab
|
||||
generatedRecoveryPhrase={generatedRecoveryPhrase}
|
||||
hexGeneratedPubKey={hexGeneratedPubKey}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <SignInTab />;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className="session-registration-container">
|
||||
<RegistrationContext.Provider
|
||||
value={{
|
||||
registrationPhase,
|
||||
setRegistrationPhase,
|
||||
generatedRecoveryPhrase,
|
||||
hexGeneratedPubKey,
|
||||
}}
|
||||
>
|
||||
{(registrationPhase === RegistrationPhase.Start ||
|
||||
registrationPhase === RegistrationPhase.SignUp) && <SignUpTab />}
|
||||
{(registrationPhase === RegistrationPhase.Start ||
|
||||
registrationPhase === RegistrationPhase.SignIn) && <SignInTab />}
|
||||
</RegistrationContext.Provider>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -2,7 +2,7 @@ import classNames from 'classnames';
|
|||
import React from 'react';
|
||||
import { lightTheme } from '../../../state/ducks/SessionTheme';
|
||||
import { SessionInput } from '../SessionInput';
|
||||
import { MAX_USERNAME_LENGTH } from './RegistrationTabs';
|
||||
import { MAX_USERNAME_LENGTH } from './RegistrationStages';
|
||||
|
||||
const DisplayNameInput = (props: {
|
||||
stealAutoFocus?: boolean;
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { Flex } from '../../basic/Flex';
|
||||
import { SpacerLG } from '../../basic/Text';
|
||||
import { SessionButton, SessionButtonColor, SessionButtonType } from '../SessionButton';
|
||||
import { SessionSpinner } from '../SessionSpinner';
|
||||
import { signInWithLinking, signInWithRecovery } from './RegistrationTabs';
|
||||
import {
|
||||
RegistrationContext,
|
||||
RegistrationPhase,
|
||||
signInWithLinking,
|
||||
signInWithRecovery,
|
||||
} from './RegistrationStages';
|
||||
import { RegistrationUserDetails } from './RegistrationUserDetails';
|
||||
import { TermsAndConditions } from './TermsAndConditions';
|
||||
|
||||
|
@ -80,14 +85,14 @@ const SignInButtons = (props: {
|
|||
<div>
|
||||
<RestoreUsingRecoveryPhraseButton onRecoveryButtonClicked={props.onRecoveryButtonClicked} />
|
||||
<SpacerLG />
|
||||
<div className="or">{window.i18n('or')}</div>
|
||||
<SpacerLG />
|
||||
<LinkDeviceButton onLinkDeviceButtonClicked={props.onLinkDeviceButtonClicked} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const SignInTab = () => {
|
||||
const { setRegistrationPhase } = useContext(RegistrationContext);
|
||||
|
||||
const [signInMode, setSignInMode] = useState(SignInMode.Default);
|
||||
const [recoveryPhrase, setRecoveryPhrase] = useState('');
|
||||
const [recoveryPhraseError, setRecoveryPhraseError] = useState(undefined as string | undefined);
|
||||
|
@ -153,12 +158,14 @@ export const SignInTab = () => {
|
|||
<SignInButtons
|
||||
signInMode={signInMode}
|
||||
onRecoveryButtonClicked={() => {
|
||||
setRegistrationPhase(RegistrationPhase.SignIn);
|
||||
setSignInMode(SignInMode.UsingRecoveryPhrase);
|
||||
setRecoveryPhrase('');
|
||||
setDisplayName('');
|
||||
setIsLoading(false);
|
||||
}}
|
||||
onLinkDeviceButtonClicked={() => {
|
||||
setRegistrationPhase(RegistrationPhase.SignIn);
|
||||
setSignInMode(SignInMode.LinkDevice);
|
||||
setRecoveryPhrase('');
|
||||
setDisplayName('');
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { SessionButton, SessionButtonColor, SessionButtonType } from '../SessionButton';
|
||||
import { SessionIdEditable } from '../SessionIdEditable';
|
||||
import { signUp } from './RegistrationTabs';
|
||||
import { RegistrationContext, RegistrationPhase, signUp } from './RegistrationStages';
|
||||
import { RegistrationUserDetails } from './RegistrationUserDetails';
|
||||
import { TermsAndConditions } from './TermsAndConditions';
|
||||
|
||||
|
@ -11,12 +11,6 @@ export enum SignUpMode {
|
|||
EnterDetails,
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
// tslint:disable: react-unused-props-and-state
|
||||
generatedRecoveryPhrase: string;
|
||||
hexGeneratedPubKey: string;
|
||||
}
|
||||
|
||||
const CreateSessionIdButton = ({ createSessionID }: { createSessionID: any }) => {
|
||||
return (
|
||||
<SessionButton
|
||||
|
@ -40,10 +34,8 @@ const ContinueSignUpButton = ({ continueSignUp }: { continueSignUp: any }) => {
|
|||
};
|
||||
|
||||
const SignUpDefault = (props: { createSessionID: () => void }) => {
|
||||
const allUsersAreRandomly = window.i18n('allUsersAreRandomly...');
|
||||
return (
|
||||
<div className="session-registration__content">
|
||||
<div className="session-description-long">{allUsersAreRandomly}</div>
|
||||
<CreateSessionIdButton createSessionID={props.createSessionID} />
|
||||
</div>
|
||||
);
|
||||
|
@ -55,23 +47,26 @@ const SignUpSessionIDShown = (props: { continueSignUp: () => void }) => {
|
|||
<div className="session-registration__unique-session-id">
|
||||
{window.i18n('yourUniqueSessionID')}
|
||||
</div>
|
||||
|
||||
<SessionIdEditable editable={false} placeholder={undefined} />
|
||||
<div className="session-description-long">{window.i18n('signupSessionIDBlurb')}</div>
|
||||
<ContinueSignUpButton continueSignUp={props.continueSignUp} />
|
||||
<TermsAndConditions />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const SignUpTab = (props: Props) => {
|
||||
const [signUpMode, setSignUpMode] = useState(SignUpMode.Default);
|
||||
export const SignUpTab = () => {
|
||||
const { setRegistrationPhase, generatedRecoveryPhrase, hexGeneratedPubKey } = useContext(
|
||||
RegistrationContext
|
||||
);
|
||||
|
||||
const [signUpMode, setSignUpMode] = useState(SignUpMode.Default);
|
||||
const [displayName, setDisplayName] = useState('');
|
||||
const [displayNameError, setDisplayNameError] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (signUpMode === SignUpMode.SessionIDShown) {
|
||||
window.Session.setNewSessionID(props.hexGeneratedPubKey);
|
||||
window.Session.setNewSessionID(hexGeneratedPubKey);
|
||||
}
|
||||
}, [signUpMode]);
|
||||
|
||||
|
@ -80,6 +75,7 @@ export const SignUpTab = (props: Props) => {
|
|||
<SignUpDefault
|
||||
createSessionID={() => {
|
||||
setSignUpMode(SignUpMode.SessionIDShown);
|
||||
setRegistrationPhase(RegistrationPhase.SignUp);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -104,7 +100,7 @@ export const SignUpTab = (props: Props) => {
|
|||
const signUpWithDetails = async () => {
|
||||
await signUp({
|
||||
displayName,
|
||||
generatedRecoveryPhrase: props.generatedRecoveryPhrase,
|
||||
generatedRecoveryPhrase: generatedRecoveryPhrase,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue