diff --git a/native/account/registration/connect-ethereum.react.js b/native/account/registration/connect-ethereum.react.js
index d1de62446..9d35d26c7 100644
--- a/native/account/registration/connect-ethereum.react.js
+++ b/native/account/registration/connect-ethereum.react.js
@@ -1,224 +1,227 @@
// @flow
import * as React from 'react';
import { Text, View } from 'react-native';
import {
exactSearchUser,
exactSearchUserActionTypes,
} from 'lib/actions/user-actions.js';
import type { SIWEResult } from 'lib/types/siwe-types.js';
import {
useServerCall,
useDispatchActionPromise,
} from 'lib/utils/action-utils.js';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import type { CoolOrNerdMode } from './registration-types.js';
import {
type NavigationRoute,
ExistingEthereumAccountRouteName,
UsernameSelectionRouteName,
} from '../../navigation/route-names.js';
import { useStyles } from '../../themes/colors.js';
import EthereumLogoDark from '../../vectors/ethereum-logo-dark.react.js';
import SIWEPanel from '../siwe-panel.react.js';
export type ConnectEthereumParams = {
+userSelections: {
+coolOrNerdMode: CoolOrNerdMode,
+keyserverUsername: string,
},
};
type PanelState = 'closed' | 'opening' | 'open' | 'closing';
type Props = {
+navigation: RegistrationNavigationProp<'ConnectEthereum'>,
+route: NavigationRoute<'ConnectEthereum'>,
};
function ConnectEthereum(props: Props): React.Node {
const { params } = props.route;
const { userSelections } = props.route.params;
const isNerdMode = userSelections.coolOrNerdMode === 'nerd';
const styles = useStyles(unboundStyles);
let body;
if (!isNerdMode) {
body = (
Connecting your Ethereum wallet allows you to use your ENS name and
avatar in the app. You’ll also be able to log in with your wallet
instead of a password.
);
} else {
body = (
<>
Connecting your Ethereum wallet has three benefits:
{'1. '}
Your peers will be able to cryptographically verify that your Comm
account is associated with your Ethereum wallet.
{'2. '}
You’ll be able to use your ENS name and avatar in the app.
{'3. '}
You can choose to skip setting a password, and to log in with your
Ethereum wallet instead.
>
);
}
const [panelState, setPanelState] = React.useState('closed');
const openPanel = React.useCallback(() => {
setPanelState('opening');
}, []);
const onPanelClosed = React.useCallback(() => {
setPanelState('closed');
}, []);
const onPanelClosing = React.useCallback(() => {
setPanelState('closing');
}, []);
const siwePanelSetLoading = React.useCallback(
(loading: boolean) => {
if (panelState === 'closing' || panelState === 'closed') {
return;
}
setPanelState(loading ? 'opening' : 'open');
},
[panelState],
);
const { navigate } = props.navigation;
const onSkip = React.useCallback(() => {
navigate<'UsernameSelection'>({
name: UsernameSelectionRouteName,
params,
});
}, [navigate, params]);
const exactSearchUserCall = useServerCall(exactSearchUser);
const dispatchActionPromise = useDispatchActionPromise();
const onSuccessfulWalletSignature = React.useCallback(
async (result: SIWEResult) => {
const searchPromise = exactSearchUserCall(result.address);
dispatchActionPromise(exactSearchUserActionTypes, searchPromise);
const { userInfo } = await searchPromise;
if (userInfo) {
navigate<'ExistingEthereumAccount'>({
name: ExistingEthereumAccountRouteName,
params: result,
});
} else {
// show avatar selection screen
}
},
[exactSearchUserCall, dispatchActionPromise, navigate],
);
let siwePanel;
if (panelState !== 'closed') {
siwePanel = (
);
}
return (
<>
Do you want to connect an Ethereum wallet?
{body}
{siwePanel}
>
);
}
const unboundStyles = {
scrollViewContentContainer: {
flexGrow: 1,
},
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
},
body: {
+ fontFamily: 'Arial',
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
paddingBottom: 16,
},
ethereumLogoContainer: {
flexGrow: 1,
alignItems: 'center',
justifyContent: 'center',
},
list: {
paddingBottom: 16,
},
listItem: {
flexDirection: 'row',
},
listItemNumber: {
+ fontFamily: 'Arial',
fontWeight: 'bold',
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
},
listItemContent: {
+ fontFamily: 'Arial',
flexShrink: 1,
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
},
};
export default ConnectEthereum;
diff --git a/native/account/registration/cool-or-nerd-mode-selection.react.js b/native/account/registration/cool-or-nerd-mode-selection.react.js
index 173813c4b..b5603aadd 100644
--- a/native/account/registration/cool-or-nerd-mode-selection.react.js
+++ b/native/account/registration/cool-or-nerd-mode-selection.react.js
@@ -1,128 +1,130 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { Text } from 'react-native';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import {
RegistrationTile,
RegistrationTileHeader,
} from './registration-tile.react.js';
import type { CoolOrNerdMode } from './registration-types.js';
import {
type NavigationRoute,
KeyserverSelectionRouteName,
} from '../../navigation/route-names.js';
import { useStyles } from '../../themes/colors.js';
type Props = {
+navigation: RegistrationNavigationProp<'CoolOrNerdModeSelection'>,
+route: NavigationRoute<'CoolOrNerdModeSelection'>,
};
function CoolOrNerdModeSelection(props: Props): React.Node {
const [currentSelection, setCurrentSelection] =
React.useState();
const selectCool = React.useCallback(() => {
setCurrentSelection('cool');
}, []);
const selectNerd = React.useCallback(() => {
setCurrentSelection('nerd');
}, []);
const { navigate } = props.navigation;
const onSubmit = React.useCallback(() => {
invariant(
currentSelection,
'Button should be disabled if currentSelection is not set',
);
navigate<'KeyserverSelection'>({
name: KeyserverSelectionRouteName,
params: { userSelections: { coolOrNerdMode: currentSelection } },
});
}, [navigate, currentSelection]);
const buttonState = currentSelection ? 'enabled' : 'disabled';
const styles = useStyles(unboundStyles);
return (
To begin, choose your fighter
Do you want Comm to choose reasonable defaults for you, or do you want
to see all the options and make the decisions yourself?
This setting will affect behavior throughout the app, but you can
change it later in your settings.
🤓
Nerd mode
We present more options and talk through their security and privacy
implications in detail.
😎
Cool mode
We select reasonable defaults for you.
);
}
const unboundStyles = {
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
},
body: {
+ fontFamily: 'Arial',
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
paddingBottom: 16,
},
tileTitleText: {
flex: 1,
fontSize: 18,
color: 'panelForegroundLabel',
},
tileBody: {
+ fontFamily: 'Arial',
fontSize: 13,
color: 'panelForegroundSecondaryLabel',
},
emojiIcon: {
fontSize: 32,
bottom: 1,
marginRight: 5,
},
};
export default CoolOrNerdModeSelection;
diff --git a/native/account/registration/existing-ethereum-account.react.js b/native/account/registration/existing-ethereum-account.react.js
index 06c160bc3..a1c2be4bc 100644
--- a/native/account/registration/existing-ethereum-account.react.js
+++ b/native/account/registration/existing-ethereum-account.react.js
@@ -1,129 +1,130 @@
// @flow
import * as React from 'react';
import { Text, View, Alert } from 'react-native';
import { siweAuthActionTypes } from 'lib/actions/siwe-actions.js';
import { useENSName } from 'lib/hooks/ens-cache.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import type { SIWEResult } from 'lib/types/siwe-types.js';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import type { NavigationRoute } from '../../navigation/route-names.js';
import { useSelector } from '../../redux/redux-utils.js';
import { useStyles } from '../../themes/colors.js';
import { useSIWEServerCall } from '../siwe-hooks.js';
const siweAuthLoadingStatusSelector =
createLoadingStatusSelector(siweAuthActionTypes);
export type ExistingEthereumAccountParams = SIWEResult;
type Props = {
+navigation: RegistrationNavigationProp<'ExistingEthereumAccount'>,
+route: NavigationRoute<'ExistingEthereumAccount'>,
};
function ExistingEthereumAccount(props: Props): React.Node {
const siweServerCallParams = React.useMemo(() => {
const onServerCallFailure = () => {
Alert.alert('Unknown error', 'Uhh... try again?', [{ text: 'OK' }], {
cancelable: false,
});
};
return { onFailure: onServerCallFailure };
}, []);
const siweServerCall = useSIWEServerCall(siweServerCallParams);
const { params } = props.route;
const onProceedToLogIn = React.useCallback(() => {
siweServerCall(params);
}, [siweServerCall, params]);
const siweAuthCallLoading = useSelector(
state => siweAuthLoadingStatusSelector(state) === 'loading',
);
const { address } = params;
const walletIdentifier = useENSName(address);
const walletIdentifierTitle =
walletIdentifier === address ? 'Ethereum wallet' : 'ENS name';
const { goBack } = props.navigation;
const styles = useStyles(unboundStyles);
return (
Account already exists for wallet
You can proceed to log in with this wallet, or go back and use a
different wallet.
{walletIdentifierTitle}
{walletIdentifier}
);
}
const unboundStyles = {
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
},
body: {
+ fontFamily: 'Arial',
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
paddingBottom: 40,
},
walletTile: {
backgroundColor: 'panelForeground',
borderRadius: 8,
padding: 24,
alignItems: 'center',
},
walletIdentifierTitleText: {
fontSize: 17,
color: 'panelForegroundLabel',
textAlign: 'center',
},
walletIdentifier: {
backgroundColor: 'panelSecondaryForeground',
paddingVertical: 8,
paddingHorizontal: 24,
borderRadius: 56,
marginTop: 8,
alignItems: 'center',
},
walletIdentifierText: {
fontSize: 15,
color: 'panelForegroundLabel',
},
};
export default ExistingEthereumAccount;
diff --git a/native/account/registration/keyserver-selection.react.js b/native/account/registration/keyserver-selection.react.js
index 2bb9c28e9..8307c2385 100644
--- a/native/account/registration/keyserver-selection.react.js
+++ b/native/account/registration/keyserver-selection.react.js
@@ -1,165 +1,167 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { Text } from 'react-native';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import RegistrationTextInput from './registration-text-input.react.js';
import {
RegistrationTile,
RegistrationTileHeader,
} from './registration-tile.react.js';
import type { CoolOrNerdMode } from './registration-types.js';
import CommIcon from '../../components/comm-icon.react.js';
import {
type NavigationRoute,
ConnectEthereumRouteName,
} from '../../navigation/route-names.js';
import { useStyles, useColors } from '../../themes/colors.js';
type Selection = 'ashoat' | 'custom';
export type KeyserverSelectionParams = {
+userSelections: {
+coolOrNerdMode: CoolOrNerdMode,
},
};
type Props = {
+navigation: RegistrationNavigationProp<'KeyserverSelection'>,
+route: NavigationRoute<'KeyserverSelection'>,
};
// eslint-disable-next-line no-unused-vars
function KeyserverSelection(props: Props): React.Node {
const [customKeyserver, setCustomKeyserver] = React.useState('');
const customKeyserverTextInputRef = React.useRef();
const [currentSelection, setCurrentSelection] = React.useState();
const selectAshoat = React.useCallback(() => {
setCurrentSelection('ashoat');
customKeyserverTextInputRef.current?.blur();
}, []);
const customKeyserverEmpty = !customKeyserver;
const selectCustom = React.useCallback(() => {
setCurrentSelection('custom');
if (customKeyserverEmpty) {
customKeyserverTextInputRef.current?.focus();
}
}, [customKeyserverEmpty]);
const onCustomKeyserverFocus = React.useCallback(() => {
setCurrentSelection('custom');
}, []);
let keyserverUsername;
if (currentSelection === 'ashoat') {
keyserverUsername = 'ashoat';
} else if (currentSelection === 'custom' && customKeyserver) {
keyserverUsername = customKeyserver;
}
const buttonState = keyserverUsername ? 'enabled' : 'disabled';
const { navigate } = props.navigation;
const { coolOrNerdMode } = props.route.params.userSelections;
const onSubmit = React.useCallback(() => {
invariant(
keyserverUsername,
'Button should be disabled if keyserverUsername is not set',
);
navigate<'ConnectEthereum'>({
name: ConnectEthereumRouteName,
params: { userSelections: { coolOrNerdMode, keyserverUsername } },
});
}, [navigate, coolOrNerdMode, keyserverUsername]);
const styles = useStyles(unboundStyles);
const colors = useColors();
return (
Select a keyserver to join
Chat communities on Comm are hosted on keyservers, which are
user-operated backends.
Keyservers allow Comm to offer strong privacy guarantees without
sacrificing functionality.
ashoat
Ashoat is Comm’s founder, and his keyserver currently hosts most of
the communities on Comm.
Enter a keyserver
);
}
const unboundStyles = {
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
},
body: {
+ fontFamily: 'Arial',
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
paddingBottom: 16,
},
tileTitleText: {
flex: 1,
fontSize: 18,
color: 'panelForegroundLabel',
},
tileBody: {
+ fontFamily: 'Arial',
fontSize: 13,
color: 'panelForegroundSecondaryLabel',
},
cloud: {
marginRight: 8,
},
};
export default KeyserverSelection;