diff --git a/ts/components/settings/SessionNotificationGroupSettings.tsx b/ts/components/settings/SessionNotificationGroupSettings.tsx index 1fd73d430..73dec2535 100644 --- a/ts/components/settings/SessionNotificationGroupSettings.tsx +++ b/ts/components/settings/SessionNotificationGroupSettings.tsx @@ -25,13 +25,9 @@ const StyledButtonContainer = styled.div` padding-inline-start: var(--margins-lg); `; -export const SessionNotificationGroupSettings = (props: { hasPassword: boolean | null }) => { +export const SessionNotificationGroupSettings = () => { const forceUpdate = useUpdate(); - if (props.hasPassword === null) { - return null; - } - const initialNotificationEnabled = window.getSettingValue(SettingsKey.settingsNotification) || NOTIFICATION.MESSAGE; diff --git a/ts/components/settings/SessionSettings.tsx b/ts/components/settings/SessionSettings.tsx index b9226112f..99e4867d7 100644 --- a/ts/components/settings/SessionSettings.tsx +++ b/ts/components/settings/SessionSettings.tsx @@ -1,23 +1,24 @@ import { shell } from 'electron'; -import React from 'react'; -import autoBind from 'auto-bind'; +import React, { useState } from 'react'; import styled from 'styled-components'; +import { useDispatch } from 'react-redux'; +import useMount from 'react-use/lib/useMount'; import { SettingsHeader } from './SessionSettingsHeader'; import { SessionIconButton } from '../icon'; import { SessionNotificationGroupSettings } from './SessionNotificationGroupSettings'; -import { CategoryConversations } from './section/CategoryConversations'; -import { SettingsCategoryPrivacy } from './section/CategoryPrivacy'; -import { SettingsCategoryAppearance } from './section/CategoryAppearance'; import { Data } from '../../data/data'; -import { SettingsCategoryPermissions } from './section/CategoryPermissions'; -import { SettingsCategoryHelp } from './section/CategoryHelp'; import { sessionPassword } from '../../state/ducks/modalDialog'; -import { PasswordAction } from '../dialog/SessionPasswordDialog'; import { SectionType, showLeftPaneSection } from '../../state/ducks/section'; +import { PasswordAction } from '../dialog/SessionPasswordDialog'; +import { SettingsCategoryAppearance } from './section/CategoryAppearance'; +import { CategoryConversations } from './section/CategoryConversations'; +import { SettingsCategoryHelp } from './section/CategoryHelp'; +import { SettingsCategoryPermissions } from './section/CategoryPermissions'; +import { SettingsCategoryPrivacy } from './section/CategoryPrivacy'; export function displayPasswordModal( passwordAction: PasswordAction, @@ -57,11 +58,6 @@ export interface SettingsViewProps { category: SessionSettingCategory; } -interface State { - hasPassword: boolean | null; - shouldLockSettings: boolean | null; -} - const StyledVersionInfo = styled.div` display: flex; justify-content: space-between; @@ -110,30 +106,27 @@ const SessionInfo = () => { const SettingInCategory = (props: { category: SessionSettingCategory; - hasPassword: boolean; onPasswordUpdated: (action: string) => void; + hasPassword: boolean; }) => { - const { category, hasPassword, onPasswordUpdated } = props; + const { category, onPasswordUpdated, hasPassword } = props; - if (hasPassword === null) { - return null; - } switch (category) { // special case for blocked user case SessionSettingCategory.Conversations: return ; case SessionSettingCategory.Appearance: - return ; + return ; case SessionSettingCategory.Notifications: - return ; + return ; case SessionSettingCategory.Privacy: return ( ); case SessionSettingCategory.Help: - return ; + return ; case SessionSettingCategory.Permissions: - return ; + return ; // these three down there have no options, they are just a button case SessionSettingCategory.ClearData: @@ -159,87 +152,48 @@ const StyledSettingsList = styled.div` flex-direction: column; `; -export class SessionSettingsView extends React.Component { - public settingsViewRef: React.RefObject; - - public constructor(props: any) { - super(props); - - this.state = { - hasPassword: null, - shouldLockSettings: true, - }; - - this.settingsViewRef = React.createRef(); - autoBind(this); +export const SessionSettingsView = (props: SettingsViewProps) => { + const { category } = props; + const dispatch = useDispatch(); + const [hasPassword, setHasPassword] = useState(true); + useMount(() => { + let isMounted = true; // eslint-disable-next-line more/no-then void Data.getPasswordHash().then(hash => { - this.setState({ - hasPassword: !!hash, - }); + if (isMounted) { + setHasPassword(!!hash); + } }); - } - - public componentDidUpdate(_: SettingsViewProps, _prevState: State) { - const oldShouldRenderPasswordLock = _prevState.shouldLockSettings && _prevState.hasPassword; - const newShouldRenderPasswordLock = this.state.shouldLockSettings && this.state.hasPassword; - - if ( - newShouldRenderPasswordLock && - newShouldRenderPasswordLock !== oldShouldRenderPasswordLock - ) { - displayPasswordModal('enter', action => { - if (action === 'enter') { - // Unlocked settings - this.setState({ - shouldLockSettings: false, - }); - } - }); - } - } - - public render() { - const { category } = this.props; - const shouldRenderPasswordLock = this.state.shouldLockSettings && this.state.hasPassword; - - return ( -
- {shouldRenderPasswordLock ? ( - <> - ) : ( - <> - - - - - - - - - )} -
- ); - } + return () => { + isMounted = false; + }; + }); - public onPasswordUpdated(action: string) { + function onPasswordUpdated(action: string) { if (action === 'set' || action === 'change') { - this.setState({ - hasPassword: true, - shouldLockSettings: true, - }); - window.inboxStore?.dispatch(showLeftPaneSection(SectionType.Message)); + setHasPassword(true); + dispatch(showLeftPaneSection(SectionType.Message)); } if (action === 'remove') { - this.setState({ - hasPassword: false, - }); + setHasPassword(false); } } -} + + return ( +
+ + + + + + + +
+ ); +}; diff --git a/ts/components/settings/section/CategoryAppearance.tsx b/ts/components/settings/section/CategoryAppearance.tsx index 9d889dedf..343c465a4 100644 --- a/ts/components/settings/section/CategoryAppearance.tsx +++ b/ts/components/settings/section/CategoryAppearance.tsx @@ -2,54 +2,51 @@ import React from 'react'; import useUpdate from 'react-use/lib/useUpdate'; import { SettingsKey } from '../../../data/settings-key'; -import { isHideMenuBarSupported } from '../../../types/Settings'; import { useHasFollowSystemThemeEnabled } from '../../../state/selectors/settings'; import { ensureThemeConsistency } from '../../../themes/SessionTheme'; +import { isHideMenuBarSupported } from '../../../types/Settings'; import { SessionToggleWithDescription } from '../SessionSettingListItem'; import { SettingsThemeSwitcher } from '../SettingsThemeSwitcher'; import { ZoomingSessionSlider } from '../ZoomingSessionSlider'; -export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null }) => { +export const SettingsCategoryAppearance = () => { const forceUpdate = useUpdate(); const isFollowSystemThemeEnabled = useHasFollowSystemThemeEnabled(); - if (props.hasPassword !== null) { - const isHideMenuBarActive = - window.getSettingValue(SettingsKey.settingsMenuBar) === undefined - ? true - : window.getSettingValue(SettingsKey.settingsMenuBar); + const isHideMenuBarActive = + window.getSettingValue(SettingsKey.settingsMenuBar) === undefined + ? true + : window.getSettingValue(SettingsKey.settingsMenuBar); - return ( - <> - - - {isHideMenuBarSupported() && ( - { - window.toggleMenuBar(); - forceUpdate(); - }} - title={window.i18n('hideMenuBarTitle')} - description={window.i18n('hideMenuBarDescription')} - active={isHideMenuBarActive} - /> - )} + return ( + <> + + + {isHideMenuBarSupported() && ( { - const toggledValue = !isFollowSystemThemeEnabled; - await window.setSettingValue(SettingsKey.hasFollowSystemThemeEnabled, toggledValue); - if (!isFollowSystemThemeEnabled) { - await ensureThemeConsistency(); - } + onClickToggle={() => { + window.toggleMenuBar(); + forceUpdate(); }} - title={window.i18n('matchThemeSystemSettingTitle')} - description={window.i18n('matchThemeSystemSettingDescription')} - active={isFollowSystemThemeEnabled} - dataTestId="enable-follow-system-theme" + title={window.i18n('hideMenuBarTitle')} + description={window.i18n('hideMenuBarDescription')} + active={isHideMenuBarActive} /> - - ); - } - return null; + )} + { + const toggledValue = !isFollowSystemThemeEnabled; + await window.setSettingValue(SettingsKey.hasFollowSystemThemeEnabled, toggledValue); + if (!isFollowSystemThemeEnabled) { + await ensureThemeConsistency(); + } + }} + title={window.i18n('matchThemeSystemSettingTitle')} + description={window.i18n('matchThemeSystemSettingDescription')} + active={isFollowSystemThemeEnabled} + dataTestId="enable-follow-system-theme" + /> + + ); }; diff --git a/ts/components/settings/section/CategoryHelp.tsx b/ts/components/settings/section/CategoryHelp.tsx index 2cd2ab041..9dfee2deb 100644 --- a/ts/components/settings/section/CategoryHelp.tsx +++ b/ts/components/settings/section/CategoryHelp.tsx @@ -4,38 +4,35 @@ import { SessionButtonShape, SessionButtonType } from '../../basic/SessionButton import { SessionSettingButtonItem, SessionSettingsTitleWithLink } from '../SessionSettingListItem'; -export const SettingsCategoryHelp = (props: { hasPassword: boolean | null }) => { - if (props.hasPassword !== null) { - return ( - <> - { - ipcRenderer.send('show-debug-log'); - }} - buttonShape={SessionButtonShape.Square} - buttonType={SessionButtonType.Solid} - buttonText={window.i18n('showDebugLog')} - title={window.i18n('reportIssue')} - description={window.i18n('shareBugDetails')} - /> - void shell.openExternal('https://getsession.org/survey')} - /> - void shell.openExternal('https://crowdin.com/project/session-desktop/')} - /> - void shell.openExternal('https://getsession.org/faq')} - /> - void shell.openExternal('https://sessionapp.zendesk.com/hc/en-us')} - /> - - ); - } - return null; +export const SettingsCategoryHelp = () => { + return ( + <> + { + ipcRenderer.send('show-debug-log'); + }} + buttonShape={SessionButtonShape.Square} + buttonType={SessionButtonType.Solid} + buttonText={window.i18n('showDebugLog')} + title={window.i18n('reportIssue')} + description={window.i18n('shareBugDetails')} + /> + void shell.openExternal('https://getsession.org/survey')} + /> + void shell.openExternal('https://crowdin.com/project/session-desktop/')} + /> + void shell.openExternal('https://getsession.org/faq')} + /> + void shell.openExternal('https://sessionapp.zendesk.com/hc/en-us')} + /> + + ); }; diff --git a/ts/components/settings/section/CategoryPermissions.tsx b/ts/components/settings/section/CategoryPermissions.tsx index cf55b0065..4473742ce 100644 --- a/ts/components/settings/section/CategoryPermissions.tsx +++ b/ts/components/settings/section/CategoryPermissions.tsx @@ -53,54 +53,51 @@ async function toggleStartInTray() { } } -export const SettingsCategoryPermissions = (props: { hasPassword: boolean | null }) => { +export const SettingsCategoryPermissions = () => { const forceUpdate = useUpdate(); const isStartInTrayActive = Boolean(window.getSettingValue(SettingsKey.settingsStartInTray)); - if (props.hasPassword !== null) { - return ( - <> - { - await window.toggleMediaPermissions(); - forceUpdate(); - }} - title={window.i18n('mediaPermissionsTitle')} - description={window.i18n('mediaPermissionsDescription')} - active={Boolean(window.getSettingValue('media-permissions'))} - dataTestId="enable-microphone" - /> - { - await toggleCallMediaPermissions(forceUpdate); - forceUpdate(); - }} - title={window.i18n('callMediaPermissionsTitle')} - description={window.i18n('callMediaPermissionsDescription')} - active={Boolean(window.getCallMediaPermissions())} - dataTestId="enable-calls" - /> - { - const old = Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate)); - await window.setSettingValue(SettingsKey.settingsAutoUpdate, !old); - forceUpdate(); - }} - title={window.i18n('autoUpdateSettingTitle')} - description={window.i18n('autoUpdateSettingDescription')} - active={Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate))} - /> - { - await toggleStartInTray(); - forceUpdate(); - }} - title={window.i18n('startInTrayTitle')} - description={window.i18n('startInTrayDescription')} - active={isStartInTrayActive} - /> - - ); - } - return null; + return ( + <> + { + await window.toggleMediaPermissions(); + forceUpdate(); + }} + title={window.i18n('mediaPermissionsTitle')} + description={window.i18n('mediaPermissionsDescription')} + active={Boolean(window.getSettingValue('media-permissions'))} + dataTestId="enable-microphone" + /> + { + await toggleCallMediaPermissions(forceUpdate); + forceUpdate(); + }} + title={window.i18n('callMediaPermissionsTitle')} + description={window.i18n('callMediaPermissionsDescription')} + active={Boolean(window.getCallMediaPermissions())} + dataTestId="enable-calls" + /> + { + const old = Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate)); + await window.setSettingValue(SettingsKey.settingsAutoUpdate, !old); + forceUpdate(); + }} + title={window.i18n('autoUpdateSettingTitle')} + description={window.i18n('autoUpdateSettingDescription')} + active={Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate))} + /> + { + await toggleStartInTray(); + forceUpdate(); + }} + title={window.i18n('startInTrayTitle')} + description={window.i18n('startInTrayDescription')} + active={isStartInTrayActive} + /> + + ); }; diff --git a/ts/components/settings/section/CategoryPrivacy.tsx b/ts/components/settings/section/CategoryPrivacy.tsx index 59e836d52..4c48f5426 100644 --- a/ts/components/settings/section/CategoryPrivacy.tsx +++ b/ts/components/settings/section/CategoryPrivacy.tsx @@ -61,66 +61,66 @@ export const SettingsCategoryPrivacy = (props: { const isLinkPreviewsOn = useHasLinkPreviewEnabled(); const areBlindedRequestsEnabled = useHasBlindedMsgRequestsEnabled(); - if (props.hasPassword !== null) { - return ( - <> - { - const old = Boolean(window.getSettingValue(SettingsKey.settingsReadReceipt)); - await window.setSettingValue(SettingsKey.settingsReadReceipt, !old); - forceUpdate(); - }} - title={window.i18n('readReceiptSettingTitle')} - description={window.i18n('readReceiptSettingDescription')} - active={window.getSettingValue(SettingsKey.settingsReadReceipt)} - dataTestId="enable-read-receipts" - /> - { - const old = Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator)); - await window.setSettingValue(SettingsKey.settingsTypingIndicator, !old); - forceUpdate(); - }} - title={window.i18n('typingIndicatorsSettingTitle')} - description={window.i18n('typingIndicatorsSettingDescription')} - active={Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator))} - childrenDescription={} - /> - { - void toggleLinkPreviews(isLinkPreviewsOn, forceUpdate); - }} - title={window.i18n('linkPreviewsTitle')} - description={window.i18n('linkPreviewDescription')} - active={isLinkPreviewsOn} - /> - { - const toggledValue = !areBlindedRequestsEnabled; - await window.setSettingValue(SettingsKey.hasBlindedMsgRequestsEnabled, toggledValue); - await SessionUtilUserProfile.insertUserProfileIntoWrapper( - UserUtils.getOurPubKeyStrFromCache() - ); - await ConfigurationSync.queueNewJobIfNeeded(); - forceUpdate(); + return ( + <> + { + const old = Boolean(window.getSettingValue(SettingsKey.settingsReadReceipt)); + await window.setSettingValue(SettingsKey.settingsReadReceipt, !old); + forceUpdate(); + }} + title={window.i18n('readReceiptSettingTitle')} + description={window.i18n('readReceiptSettingDescription')} + active={window.getSettingValue(SettingsKey.settingsReadReceipt)} + dataTestId="enable-read-receipts" + /> + { + const old = Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator)); + await window.setSettingValue(SettingsKey.settingsTypingIndicator, !old); + forceUpdate(); + }} + title={window.i18n('typingIndicatorsSettingTitle')} + description={window.i18n('typingIndicatorsSettingDescription')} + active={Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator))} + childrenDescription={} + /> + { + void toggleLinkPreviews(isLinkPreviewsOn, forceUpdate); + }} + title={window.i18n('linkPreviewsTitle')} + description={window.i18n('linkPreviewDescription')} + active={isLinkPreviewsOn} + /> + { + const toggledValue = !areBlindedRequestsEnabled; + await window.setSettingValue(SettingsKey.hasBlindedMsgRequestsEnabled, toggledValue); + await SessionUtilUserProfile.insertUserProfileIntoWrapper( + UserUtils.getOurPubKeyStrFromCache() + ); + await ConfigurationSync.queueNewJobIfNeeded(); + forceUpdate(); + }} + title={window.i18n('blindedMsgReqsSettingTitle')} + description={window.i18n('blindedMsgReqsSettingDesc')} + active={areBlindedRequestsEnabled} + /> + + {!props.hasPassword ? ( + { + displayPasswordModal('set', props.onPasswordUpdated); }} - title={window.i18n('blindedMsgReqsSettingTitle')} - description={window.i18n('blindedMsgReqsSettingDesc')} - active={areBlindedRequestsEnabled} + buttonText={window.i18n('setPassword')} + dataTestId={'set-password-button'} /> - - {!props.hasPassword && ( - { - displayPasswordModal('set', props.onPasswordUpdated); - }} - buttonText={window.i18n('setPassword')} - dataTestId={'set-password-button'} - /> - )} - {props.hasPassword && ( + ) : ( + <> + {/* We have a password, let's show the 'change' and 'remove' password buttons */} - )} - {props.hasPassword && ( - )} - - ); - } - return null; + + )} + + ); };