Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3509269
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
30 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/native/profile/profile-screen.react.js b/native/profile/profile-screen.react.js
index d7dfa3c72..d2d798a65 100644
--- a/native/profile/profile-screen.react.js
+++ b/native/profile/profile-screen.react.js
@@ -1,626 +1,631 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { View, Text, Platform, ScrollView } from 'react-native';
import uuid from 'uuid';
import {
logOutActionTypes,
useLogOut,
usePrimaryDeviceLogOut,
useSecondaryDeviceLogOut,
} from 'lib/actions/user-actions.js';
import { useStringForUser } from 'lib/hooks/ens-cache.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import { getOwnPrimaryDeviceID } from 'lib/selectors/user-selectors.js';
import { accountHasPassword } from 'lib/shared/account-utils.js';
import {
type OutboundDMOperationSpecification,
dmOperationSpecificationTypes,
} from 'lib/shared/dm-ops/dm-op-utils.js';
import { useProcessAndSendDMOperation } from 'lib/shared/dm-ops/process-dm-ops.js';
import type { LogOutResult } from 'lib/types/account-types.js';
import type { DMCreateThreadOperation } from 'lib/types/dm-ops';
import { thickThreadTypes } from 'lib/types/thread-types-enum.js';
import { type CurrentUserInfo } from 'lib/types/user-types.js';
import { getContentSigningKey } from 'lib/utils/crypto-utils.js';
import { useCurrentUserFID } from 'lib/utils/farcaster-utils.js';
import {
useDispatchActionPromise,
type DispatchActionPromise,
} from 'lib/utils/redux-promise-utils.js';
import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js';
import type { ProfileNavigationProp } from './profile.react.js';
import { deleteNativeCredentialsFor } from '../account/native-credentials.js';
import EditUserAvatar from '../avatars/edit-user-avatar.react.js';
import Action from '../components/action-row.react.js';
import Button from '../components/button.react.js';
import EditSettingButton from '../components/edit-setting-button.react.js';
import SingleLine from '../components/single-line.react.js';
import type { NavigationRoute } from '../navigation/route-names.js';
import {
EditPasswordRouteName,
DeleteAccountRouteName,
BuildInfoRouteName,
DevToolsRouteName,
AppearancePreferencesRouteName,
FriendListRouteName,
BlockListRouteName,
PrivacyPreferencesRouteName,
DefaultNotificationsPreferencesRouteName,
LinkedDevicesRouteName,
BackupMenuRouteName,
KeyserverSelectionListRouteName,
TunnelbrokerMenuRouteName,
FarcasterAccountSettingsRouteName,
} from '../navigation/route-names.js';
import { useSelector } from '../redux/redux-utils.js';
import { type Colors, useColors, useStyles } from '../themes/colors.js';
import Alert from '../utils/alert.js';
+import { useShowVersionUnsupportedAlert } from '../utils/hooks.js';
import { useStaffCanSee } from '../utils/staff-utils.js';
type ProfileRowProps = {
+content: string,
+onPress: () => void,
+danger?: boolean,
};
function ProfileRow(props: ProfileRowProps): React.Node {
const { content, onPress, danger } = props;
return (
<Action.Row onPress={onPress}>
<Action.Text danger={danger} content={content} />
<Action.Icon name="ios-arrow-forward" />
</Action.Row>
);
}
const unboundStyles = {
avatarSection: {
alignItems: 'center',
paddingVertical: 16,
},
container: {
flex: 1,
},
content: {
flex: 1,
},
deleteAccountButton: {
paddingHorizontal: 24,
paddingVertical: 12,
},
editPasswordButton: {
paddingTop: Platform.OS === 'android' ? 3 : 2,
},
header: {
color: 'panelBackgroundLabel',
fontSize: 12,
fontWeight: '400',
paddingBottom: 3,
paddingHorizontal: 24,
},
label: {
color: 'panelForegroundTertiaryLabel',
fontSize: 16,
paddingRight: 12,
},
loggedInLabel: {
color: 'panelForegroundTertiaryLabel',
fontSize: 16,
},
logOutText: {
color: 'link',
fontSize: 16,
paddingLeft: 6,
},
row: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
},
scrollView: {
backgroundColor: 'panelBackground',
},
scrollViewContentContainer: {
paddingTop: 24,
},
paddedRow: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 24,
paddingVertical: 10,
},
section: {
backgroundColor: 'panelForeground',
borderBottomWidth: 1,
borderColor: 'panelForegroundBorder',
borderTopWidth: 1,
marginBottom: 24,
paddingVertical: 1,
},
unpaddedSection: {
backgroundColor: 'panelForeground',
borderBottomWidth: 1,
borderColor: 'panelForegroundBorder',
borderTopWidth: 1,
marginBottom: 24,
},
username: {
color: 'panelForegroundLabel',
flex: 1,
},
value: {
color: 'panelForegroundLabel',
fontSize: 16,
textAlign: 'right',
},
};
type BaseProps = {
+navigation: ProfileNavigationProp<'ProfileScreen'>,
+route: NavigationRoute<'ProfileScreen'>,
};
type Props = {
...BaseProps,
+currentUserInfo: ?CurrentUserInfo,
+primaryDeviceID: ?string,
+logOutLoading: boolean,
+colors: Colors,
+styles: $ReadOnly<typeof unboundStyles>,
+dispatchActionPromise: DispatchActionPromise,
+logOut: () => Promise<LogOutResult>,
+logOutPrimaryDevice: () => Promise<LogOutResult>,
+logOutSecondaryDevice: () => Promise<LogOutResult>,
+staffCanSee: boolean,
+stringForUser: ?string,
+isAccountWithPassword: boolean,
+onCreateDMThread: () => Promise<void>,
+currentUserFID: ?string,
};
class ProfileScreen extends React.PureComponent<Props> {
get loggedOutOrLoggingOut(): boolean {
return (
!this.props.currentUserInfo ||
this.props.currentUserInfo.anonymous ||
this.props.logOutLoading
);
}
render(): React.Node {
let developerTools,
defaultNotifications,
keyserverSelection,
tunnelbrokerMenu;
const { staffCanSee } = this.props;
if (staffCanSee) {
developerTools = (
<ProfileRow content="Developer tools" onPress={this.onPressDevTools} />
);
defaultNotifications = (
<ProfileRow
content="Default Notifications"
onPress={this.onPressDefaultNotifications}
/>
);
keyserverSelection = (
<ProfileRow
content="Keyservers"
onPress={this.onPressKeyserverSelection}
/>
);
tunnelbrokerMenu = (
<ProfileRow
content="Tunnelbroker menu"
onPress={this.onPressTunnelbrokerMenu}
/>
);
}
let backupMenu;
if (staffCanSee) {
backupMenu = (
<ProfileRow content="Backup menu" onPress={this.onPressBackupMenu} />
);
}
let passwordEditionUI;
if (accountHasPassword(this.props.currentUserInfo)) {
passwordEditionUI = (
<Action.Row>
<Text style={this.props.styles.label}>Password</Text>
<Text
style={[this.props.styles.content, this.props.styles.value]}
numberOfLines={1}
>
••••••••••••••••
</Text>
<EditSettingButton
onPress={this.onPressEditPassword}
canChangeSettings={true}
style={this.props.styles.editPasswordButton}
/>
</Action.Row>
);
}
let linkedDevices;
if (__DEV__) {
linkedDevices = (
<ProfileRow content="Linked devices" onPress={this.onPressDevices} />
);
}
let farcasterAccountSettings;
if (usingCommServicesAccessToken || __DEV__) {
farcasterAccountSettings = (
<ProfileRow
content="Farcaster account"
onPress={this.onPressFaracsterAccount}
/>
);
}
let experimentalLogoutActions;
if (__DEV__) {
experimentalLogoutActions = (
<>
<ProfileRow
danger
content="Log out (new flow)"
onPress={this.onPressNewLogout}
/>
</>
);
}
let dmActions;
if (staffCanSee) {
dmActions = (
<>
<ProfileRow
content="Create a new local DM thread"
onPress={this.onPressCreateThread}
/>
</>
);
}
return (
<View style={this.props.styles.container}>
<ScrollView
contentContainerStyle={this.props.styles.scrollViewContentContainer}
style={this.props.styles.scrollView}
>
<Text style={this.props.styles.header}>USER AVATAR</Text>
<View
style={[this.props.styles.section, this.props.styles.avatarSection]}
>
<EditUserAvatar
userID={this.props.currentUserInfo?.id}
fid={this.props.currentUserFID}
/>
</View>
<Text style={this.props.styles.header}>ACCOUNT</Text>
<View style={this.props.styles.section}>
<Action.Row>
<Text style={this.props.styles.loggedInLabel}>Logged in as </Text>
<SingleLine
style={[this.props.styles.label, this.props.styles.username]}
>
{this.props.stringForUser}
</SingleLine>
<Button
onPress={this.onPressLogOut}
disabled={this.loggedOutOrLoggingOut}
>
<Text style={this.props.styles.logOutText}>Log out</Text>
</Button>
</Action.Row>
{passwordEditionUI}
</View>
<View style={this.props.styles.section}>
<ProfileRow
content="Friend list"
onPress={this.onPressFriendList}
/>
<ProfileRow content="Block list" onPress={this.onPressBlockList} />
</View>
<Text style={this.props.styles.header}>PREFERENCES</Text>
<View style={this.props.styles.section}>
<ProfileRow content="Appearance" onPress={this.onPressAppearance} />
<ProfileRow content="Privacy" onPress={this.onPressPrivacy} />
{defaultNotifications}
{backupMenu}
{tunnelbrokerMenu}
</View>
<View style={this.props.styles.section}>
{farcasterAccountSettings}
{linkedDevices}
{keyserverSelection}
<ProfileRow content="Build info" onPress={this.onPressBuildInfo} />
{developerTools}
{experimentalLogoutActions}
{dmActions}
</View>
<View style={this.props.styles.unpaddedSection}>
<ProfileRow
content="Delete account..."
danger
onPress={this.onPressDeleteAccount}
/>
</View>
</ScrollView>
</View>
);
}
onPressLogOut = () => {
if (this.loggedOutOrLoggingOut) {
return;
}
if (!this.props.isAccountWithPassword) {
Alert.alert(
'Log out',
'Are you sure you want to log out?',
[
{ text: 'No', style: 'cancel' },
{
text: 'Yes',
onPress: this.logOutWithoutDeletingNativeCredentialsWrapper,
style: 'destructive',
},
],
{ cancelable: true },
);
return;
}
const alertTitle =
Platform.OS === 'ios' ? 'Keep Login Info in Keychain' : 'Keep Login Info';
const alertDescription =
'We will automatically fill out log-in forms with your credentials ' +
'in the app.';
Alert.alert(
alertTitle,
alertDescription,
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Keep',
onPress: this.logOutWithoutDeletingNativeCredentialsWrapper,
},
{
text: 'Remove',
onPress: this.logOutAndDeleteNativeCredentialsWrapper,
style: 'destructive',
},
],
{ cancelable: true },
);
};
onPressNewLogout = () => {
void (async () => {
if (this.loggedOutOrLoggingOut) {
return;
}
const { primaryDeviceID } = this.props;
const currentDeviceID = await getContentSigningKey();
const isPrimaryDevice = currentDeviceID === primaryDeviceID;
let alertTitle, alertMessage, onPressAction;
if (isPrimaryDevice) {
alertTitle = 'Log out all devices?';
alertMessage =
'This device is your primary device, ' +
'so logging out will cause all of your other devices to log out too.';
onPressAction = this.logOutPrimaryDevice;
} else {
alertTitle = 'Log out?';
alertMessage = 'Are you sure you want to log out of this device?';
onPressAction = this.logOutSecondaryDevice;
}
Alert.alert(
alertTitle,
alertMessage,
[
{ text: 'No', style: 'cancel' },
{
text: 'Yes',
onPress: onPressAction,
style: 'destructive',
},
],
{ cancelable: true },
);
})();
};
logOutWithoutDeletingNativeCredentialsWrapper = () => {
if (this.loggedOutOrLoggingOut) {
return;
}
this.logOut();
};
logOutAndDeleteNativeCredentialsWrapper = async () => {
if (this.loggedOutOrLoggingOut) {
return;
}
await this.deleteNativeCredentials();
this.logOut();
};
logOut() {
void this.props.dispatchActionPromise(
logOutActionTypes,
this.props.logOut(),
);
}
logOutPrimaryDevice = async () => {
if (this.loggedOutOrLoggingOut) {
return;
}
void this.props.dispatchActionPromise(
logOutActionTypes,
this.props.logOutPrimaryDevice(),
);
};
logOutSecondaryDevice = async () => {
if (this.loggedOutOrLoggingOut) {
return;
}
void this.props.dispatchActionPromise(
logOutActionTypes,
this.props.logOutSecondaryDevice(),
);
};
async deleteNativeCredentials() {
await deleteNativeCredentialsFor();
}
onPressEditPassword = () => {
this.props.navigation.navigate({ name: EditPasswordRouteName });
};
onPressDeleteAccount = () => {
this.props.navigation.navigate({ name: DeleteAccountRouteName });
};
onPressFaracsterAccount = () => {
this.props.navigation.navigate({ name: FarcasterAccountSettingsRouteName });
};
onPressDevices = () => {
this.props.navigation.navigate({ name: LinkedDevicesRouteName });
};
onPressBuildInfo = () => {
this.props.navigation.navigate({ name: BuildInfoRouteName });
};
onPressDevTools = () => {
this.props.navigation.navigate({ name: DevToolsRouteName });
};
onPressAppearance = () => {
this.props.navigation.navigate({ name: AppearancePreferencesRouteName });
};
onPressPrivacy = () => {
this.props.navigation.navigate({ name: PrivacyPreferencesRouteName });
};
onPressDefaultNotifications = () => {
this.props.navigation.navigate({
name: DefaultNotificationsPreferencesRouteName,
});
};
onPressFriendList = () => {
this.props.navigation.navigate({ name: FriendListRouteName });
};
onPressBlockList = () => {
this.props.navigation.navigate({ name: BlockListRouteName });
};
onPressBackupMenu = () => {
this.props.navigation.navigate({ name: BackupMenuRouteName });
};
onPressTunnelbrokerMenu = () => {
this.props.navigation.navigate({ name: TunnelbrokerMenuRouteName });
};
onPressKeyserverSelection = () => {
this.props.navigation.navigate({ name: KeyserverSelectionListRouteName });
};
onPressCreateThread = () => {
void this.props.onCreateDMThread();
};
}
const logOutLoadingStatusSelector =
createLoadingStatusSelector(logOutActionTypes);
const ConnectedProfileScreen: React.ComponentType<BaseProps> =
React.memo<BaseProps>(function ConnectedProfileScreen(props: BaseProps) {
const currentUserInfo = useSelector(state => state.currentUserInfo);
const primaryDeviceID = useSelector(getOwnPrimaryDeviceID);
const logOutLoading =
useSelector(logOutLoadingStatusSelector) === 'loading';
const colors = useColors();
const styles = useStyles(unboundStyles);
- const callLogOut = useLogOut();
const callPrimaryDeviceLogOut = usePrimaryDeviceLogOut();
const callSecondaryDeviceLogOut = useSecondaryDeviceLogOut();
const dispatchActionPromise = useDispatchActionPromise();
const staffCanSee = useStaffCanSee();
const stringForUser = useStringForUser(currentUserInfo);
const isAccountWithPassword = useSelector(state =>
accountHasPassword(state.currentUserInfo),
);
const currentUserID = useCurrentUserFID();
+ const showVersionUnsupportedAlert = useShowVersionUnsupportedAlert(false);
+ const callLogOut = useLogOut({
+ handleUseNewFlowResponse: showVersionUnsupportedAlert,
+ });
+
const userID = useSelector(
state => state.currentUserInfo && state.currentUserInfo.id,
);
const processAndSendDMOperation = useProcessAndSendDMOperation();
const onCreateDMThread = React.useCallback(async () => {
invariant(userID, 'userID should be set');
const op: DMCreateThreadOperation = {
type: 'create_thread',
threadID: uuid.v4(),
creatorID: userID,
time: Date.now(),
threadType: thickThreadTypes.LOCAL,
memberIDs: [],
roleID: uuid.v4(),
newMessageID: uuid.v4(),
};
const specification: OutboundDMOperationSpecification = {
type: dmOperationSpecificationTypes.OUTBOUND,
op,
recipients: {
type: 'self_devices',
},
};
await processAndSendDMOperation(specification);
}, [processAndSendDMOperation, userID]);
return (
<ProfileScreen
{...props}
currentUserInfo={currentUserInfo}
primaryDeviceID={primaryDeviceID}
logOutLoading={logOutLoading}
colors={colors}
styles={styles}
logOut={callLogOut}
logOutPrimaryDevice={callPrimaryDeviceLogOut}
logOutSecondaryDevice={callSecondaryDeviceLogOut}
dispatchActionPromise={dispatchActionPromise}
staffCanSee={staffCanSee}
stringForUser={stringForUser}
isAccountWithPassword={isAccountWithPassword}
onCreateDMThread={onCreateDMThread}
currentUserFID={currentUserID}
/>
);
});
export default ConnectedProfileScreen;
diff --git a/web/settings/account-settings.react.js b/web/settings/account-settings.react.js
index 460a9e4aa..28abe8225 100644
--- a/web/settings/account-settings.react.js
+++ b/web/settings/account-settings.react.js
@@ -1,356 +1,365 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import uuid from 'uuid';
import {
useLogOut,
logOutActionTypes,
useSecondaryDeviceLogOut,
} from 'lib/actions/user-actions.js';
import { useModalContext } from 'lib/components/modal-provider.react.js';
import SWMansionIcon from 'lib/components/swmansion-icon.react.js';
import { useStringForUser } from 'lib/hooks/ens-cache.js';
import { accountHasPassword } from 'lib/shared/account-utils.js';
import {
dmOperationSpecificationTypes,
type OutboundDMOperationSpecification,
} from 'lib/shared/dm-ops/dm-op-utils.js';
import { useProcessAndSendDMOperation } from 'lib/shared/dm-ops/process-dm-ops.js';
import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { useTunnelbroker } from 'lib/tunnelbroker/tunnelbroker-context.js';
import type { DMCreateThreadOperation } from 'lib/types/dm-ops.js';
import { thickThreadTypes } from 'lib/types/thread-types-enum.js';
import {
createOlmSessionsWithOwnDevices,
getContentSigningKey,
} from 'lib/utils/crypto-utils.js';
import { isDev } from 'lib/utils/dev-utils.js';
import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js';
import css from './account-settings.css';
import AppearanceChangeModal from './appearance-change-modal.react.js';
import BackupTestRestoreModal from './backup-test-restore-modal.react.js';
import PasswordChangeModal from './password-change-modal.js';
import BlockListModal from './relationship/block-list-modal.react.js';
import FriendListModal from './relationship/friend-list-modal.react.js';
import TunnelbrokerMessagesScreen from './tunnelbroker-message-list.react.js';
import TunnelbrokerTestScreen from './tunnelbroker-test.react.js';
import EditUserAvatar from '../avatars/edit-user-avatar.react.js';
import Button from '../components/button.react.js';
+import VersionUnsupportedModal from '../modals/version-unsupported-modal.react.js';
import { useSelector } from '../redux/redux-utils.js';
import { useStaffCanSee } from '../utils/staff-utils.js';
function AccountSettings(): React.Node {
- const sendLogoutRequest = useLogOut();
+ const { pushModal, popModal } = useModalContext();
+
+ const logOutOptions = React.useMemo(() => {
+ const showVersionUnsupportedModal = () => {
+ pushModal(<VersionUnsupportedModal />);
+ };
+ return { handleUseNewFlowResponse: showVersionUnsupportedModal };
+ }, [pushModal]);
+ const sendLogoutRequest = useLogOut(logOutOptions);
+
const sendSecondaryDeviceLogoutRequest = useSecondaryDeviceLogOut();
const dispatchActionPromise = useDispatchActionPromise();
const logOutUser = React.useCallback(
() => dispatchActionPromise(logOutActionTypes, sendLogoutRequest()),
[dispatchActionPromise, sendLogoutRequest],
);
const logOutSecondaryDevice = React.useCallback(
() =>
dispatchActionPromise(
logOutActionTypes,
sendSecondaryDeviceLogoutRequest(),
),
[dispatchActionPromise, sendSecondaryDeviceLogoutRequest],
);
const identityContext = React.useContext(IdentityClientContext);
const userID = useSelector(state => state.currentUserInfo?.id);
const [deviceID, setDeviceID] = React.useState<?string>();
React.useEffect(() => {
void (async () => {
const contentSigningKey = await getContentSigningKey();
setDeviceID(contentSigningKey);
})();
}, []);
- const { pushModal, popModal } = useModalContext();
const showPasswordChangeModal = React.useCallback(
() => pushModal(<PasswordChangeModal />),
[pushModal],
);
const openFriendList = React.useCallback(
() => pushModal(<FriendListModal />),
[pushModal],
);
const openBlockList = React.useCallback(
() => pushModal(<BlockListModal />),
[pushModal],
);
const isAccountWithPassword = useSelector(state =>
accountHasPassword(state.currentUserInfo),
);
const currentUserInfo = useSelector(state => state.currentUserInfo);
const stringForUser = useStringForUser(currentUserInfo);
const staffCanSee = useStaffCanSee();
const { sendMessageToDevice, socketState, addListener, removeListener } =
useTunnelbroker();
const openTunnelbrokerModal = React.useCallback(
() =>
pushModal(
<TunnelbrokerTestScreen
sendMessageToDevice={sendMessageToDevice}
onClose={popModal}
/>,
),
[popModal, pushModal, sendMessageToDevice],
);
const openTunnelbrokerMessagesModal = React.useCallback(
() =>
pushModal(
<TunnelbrokerMessagesScreen
addListener={addListener}
removeListener={removeListener}
onClose={popModal}
/>,
),
[addListener, popModal, pushModal, removeListener],
);
const onCreateOlmSessions = React.useCallback(async () => {
if (!identityContext) {
return;
}
const authMetadata = await identityContext.getAuthMetadata();
try {
await createOlmSessionsWithOwnDevices(
authMetadata,
identityContext.identityClient,
sendMessageToDevice,
);
} catch (e) {
console.log(`Error creating olm sessions with own devices: ${e.message}`);
}
}, [identityContext, sendMessageToDevice]);
const openBackupTestRestoreModal = React.useCallback(
() => pushModal(<BackupTestRestoreModal onClose={popModal} />),
[popModal, pushModal],
);
const processAndSendDMOperation = useProcessAndSendDMOperation();
const onCreateDMThread = React.useCallback(async () => {
invariant(userID, 'userID should be set');
const op: DMCreateThreadOperation = {
type: 'create_thread',
threadID: uuid.v4(),
creatorID: userID,
time: Date.now(),
threadType: thickThreadTypes.LOCAL,
memberIDs: [],
roleID: uuid.v4(),
newMessageID: uuid.v4(),
};
const specification: OutboundDMOperationSpecification = {
type: dmOperationSpecificationTypes.OUTBOUND,
op,
recipients: {
type: 'self_devices',
},
};
await processAndSendDMOperation(specification);
}, [processAndSendDMOperation, userID]);
const showAppearanceModal = React.useCallback(
() => pushModal(<AppearanceChangeModal />),
[pushModal],
);
if (!currentUserInfo || currentUserInfo.anonymous) {
return null;
}
let changePasswordSection;
if (isAccountWithPassword) {
changePasswordSection = (
<li>
<span>Password</span>
<span className={css.passwordContainer}>
<span className={css.password}>******</span>
<a className={css.editPasswordLink} onClick={showPasswordChangeModal}>
<SWMansionIcon icon="edit-1" size={22} />
</a>
</span>
</li>
);
}
let experimentalLogOutSection;
if (isDev) {
experimentalLogOutSection = (
<li>
<span>Log out secondary device</span>
<Button variant="text" onClick={logOutSecondaryDevice}>
<p className={css.buttonText}>Log out</p>
</Button>
</li>
);
}
let preferences;
if (staffCanSee) {
preferences = (
<div className={css.preferencesContainer}>
<h4 className={css.preferencesHeader}>Preferences</h4>
<div className={css.content}>
<ul>
<li>
<span>Appearance</span>
<a className={css.editPasswordLink} onClick={showAppearanceModal}>
<SWMansionIcon icon="edit-1" size={22} />
</a>
</li>
</ul>
</div>
</div>
);
}
let tunnelbroker;
if (staffCanSee) {
tunnelbroker = (
<div className={css.preferencesContainer}>
<h4 className={css.preferencesHeader}>Tunnelbroker menu</h4>
<div className={css.content}>
<ul>
<li>
<span>Connected</span>
<span>{socketState.connected.toString()}</span>
</li>
<li>
<span>Send message to device</span>
<Button variant="text" onClick={openTunnelbrokerModal}>
<p className={css.buttonText}>Insert data</p>
</Button>
</li>
<li>
<span>Trace received messages</span>
<Button variant="text" onClick={openTunnelbrokerMessagesModal}>
<p className={css.buttonText}>Show list</p>
</Button>
</li>
<li>
<span>Create session with own devices</span>
<Button variant="text" onClick={onCreateOlmSessions}>
<p className={css.buttonText}>Create</p>
</Button>
</li>
</ul>
</div>
</div>
);
}
let backup;
if (staffCanSee) {
backup = (
<div className={css.preferencesContainer}>
<h4 className={css.preferencesHeader}>Backup menu</h4>
<div className={css.content}>
<ul>
<li>
<span>Test backup restore</span>
<Button variant="text" onClick={openBackupTestRestoreModal}>
<p className={css.buttonText}>Insert data</p>
</Button>
</li>
</ul>
</div>
</div>
);
}
let deviceData;
if (staffCanSee) {
deviceData = (
<div className={css.preferencesContainer}>
<h4 className={css.preferencesHeader}>Device ID</h4>
<div className={css.content}>
<ul>
<li>
<span>{deviceID}</span>
</li>
</ul>
</div>
<h4 className={css.preferencesHeader}>User ID</h4>
<div className={css.content}>
<ul>
<li>
<span>{userID}</span>
</li>
</ul>
</div>
</div>
);
}
let dms;
if (staffCanSee) {
dms = (
<div className={css.preferencesContainer}>
<h4 className={css.preferencesHeader}>DMs menu</h4>
<div className={css.content}>
<ul>
<li>
<span>Create a new local DM thread</span>
<Button variant="text" onClick={onCreateDMThread}>
<p className={css.buttonText}>Create</p>
</Button>
</li>
</ul>
</div>
</div>
);
}
return (
<div className={css.container}>
<div className={css.contentContainer}>
<h4 className={css.header}>My Account</h4>
<EditUserAvatar userID={currentUserInfo.id} />
<div className={css.content}>
<ul>
<li>
<p className={css.logoutContainer}>
<span className={css.logoutLabel}>{'Logged in as '}</span>
<span className={css.username}>{stringForUser}</span>
</p>
<Button variant="text" onClick={logOutUser}>
<p className={css.buttonText}>Log out</p>
</Button>
</li>
{experimentalLogOutSection}
{changePasswordSection}
<li>
<span>Friend List</span>
<Button variant="text" onClick={openFriendList}>
<p className={css.buttonText}>See List</p>
</Button>
</li>
<li>
<span>Block List</span>
<Button variant="text" onClick={openBlockList}>
<p className={css.buttonText}>See List</p>
</Button>
</li>
</ul>
</div>
{preferences}
{tunnelbroker}
{backup}
{deviceData}
{dms}
</div>
</div>
);
}
export default AccountSettings;
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 3:04 AM (5 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2690249
Default Alt Text
(30 KB)
Attached To
Mode
rCOMM Comm
Attached
Detach File
Event Timeline
Log In to Comment