diff --git a/web/modals/threads/settings/thread-settings-general-tab.react.js b/web/modals/threads/settings/thread-settings-general-tab.react.js --- a/web/modals/threads/settings/thread-settings-general-tab.react.js +++ b/web/modals/threads/settings/thread-settings-general-tab.react.js @@ -11,11 +11,8 @@ import { firstLine } from 'lib/utils/string-utils.js'; import { chatNameMaxLength } from 'lib/utils/validation-utils.js'; -import SubmitSection from './submit-section.react.js'; import css from './thread-settings-general-tab.css'; -import { useOnSaveGeneralThreadSettings } from './thread-settings-utils.js'; import EditThreadAvatar from '../../../avatars/edit-thread-avatar.react.js'; -import LoadingIndicator from '../../../loading-indicator.react.js'; import Input from '../../input.react.js'; import ColorSelector from '../color-selector.react.js'; @@ -25,8 +22,6 @@ +threadNamePlaceholder: string, +queuedChanges: ThreadChanges, +setQueuedChanges: SetState, - +setErrorMessage: SetState, - +errorMessage?: ?string, }; function ThreadSettingsGeneralTab( props: ThreadSettingsGeneralTabProps, @@ -37,8 +32,6 @@ threadNamePlaceholder, queuedChanges, setQueuedChanges, - setErrorMessage, - errorMessage, } = props; const nameInputRef = React.useRef(); @@ -47,11 +40,6 @@ nameInputRef.current?.focus(); }, [threadSettingsOperationInProgress]); - const changeQueued: boolean = React.useMemo( - () => Object.values(queuedChanges).some(v => v !== null && v !== undefined), - [queuedChanges], - ); - const onChangeName = React.useCallback( (event: SyntheticEvent) => { const target = event.currentTarget; @@ -92,27 +80,13 @@ [setQueuedChanges, threadInfo.color], ); - const onSaveGeneralThreadSettings = useOnSaveGeneralThreadSettings({ - threadInfo, - queuedChanges, - setQueuedChanges, - setErrorMessage, - }); - const threadNameInputDisabled = !threadHasPermission( threadInfo, threadPermissions.EDIT_THREAD_NAME, ); - const saveButtonContent = React.useMemo(() => { - if (threadSettingsOperationInProgress) { - return ; - } - return 'Save'; - }, [threadSettingsOperationInProgress]); - return ( -
+
@@ -153,15 +127,7 @@ />
- - {saveButtonContent} - - +
); } diff --git a/web/modals/threads/settings/thread-settings-modal.react.js b/web/modals/threads/settings/thread-settings-modal.react.js --- a/web/modals/threads/settings/thread-settings-modal.react.js +++ b/web/modals/threads/settings/thread-settings-modal.react.js @@ -29,6 +29,7 @@ import css from './thread-settings-modal.css'; import ThreadSettingsPrivacyTab from './thread-settings-privacy-tab.react.js'; import ThreadSettingsRelationshipTab from './thread-settings-relationship-tab.react.js'; +import ThreadSettingsSaveButton from './thread-settings-save-button.react.js'; import Tabs, { type TabData } from '../../../components/tabs.react.js'; import { useSelector } from '../../../redux/redux-utils.js'; import Modal from '../../modal.react.js'; @@ -56,6 +57,7 @@ state => threadInfoSelector(state)[props.threadID], ); const modalContext = useModalContext(); + // eslint-disable-next-line no-unused-vars const [errorMessage, setErrorMessage] = React.useState(''); const [currentTabType, setCurrentTabType] = React.useState('general'); @@ -197,20 +199,15 @@ threadNamePlaceholder={namePlaceholder} queuedChanges={queuedChanges} setQueuedChanges={setQueuedChanges} - setErrorMessage={setErrorMessage} - errorMessage={errorMessage} /> ); } if (currentTabType === 'privacy') { return ( ); } @@ -229,7 +226,6 @@ availableRelationshipActions, changeInProgress, currentTabType, - errorMessage, namePlaceholder, otherUserInfo, queuedChanges, @@ -241,6 +237,19 @@ return null; } + if (currentTabType === 'general' || currentTabType === 'privacy') { + return ( + + ); + } + if (currentTabType === 'relationship') { return
; } @@ -252,7 +261,7 @@ setErrorMessage={setErrorMessage} /> ); - }, [changeInProgress, currentTabType, threadInfo]); + }, [changeInProgress, currentTabType, queuedChanges, threadInfo]); if (!threadInfo) { return ( diff --git a/web/modals/threads/settings/thread-settings-privacy-tab.css b/web/modals/threads/settings/thread-settings-privacy-tab.css --- a/web/modals/threads/settings/thread-settings-privacy-tab.css +++ b/web/modals/threads/settings/thread-settings-privacy-tab.css @@ -8,8 +8,9 @@ padding: 12px 0; } -form.container { +div.container { display: flex; flex-direction: column; flex: 1; + color: var(--text-background-primary-default); } diff --git a/web/modals/threads/settings/thread-settings-privacy-tab.react.js b/web/modals/threads/settings/thread-settings-privacy-tab.react.js --- a/web/modals/threads/settings/thread-settings-privacy-tab.react.js +++ b/web/modals/threads/settings/thread-settings-privacy-tab.react.js @@ -9,9 +9,7 @@ import { threadTypes } from 'lib/types/thread-types-enum.js'; import { type ThreadChanges } from 'lib/types/thread-types.js'; -import SubmitSection from './submit-section.react.js'; import css from './thread-settings-privacy-tab.css'; -import { useOnSavePrivacyThreadSettings } from './thread-settings-utils.js'; import EnumSettingsOption from '../../../components/enum-settings-option.react.js'; const { COMMUNITY_OPEN_SUBTHREAD, COMMUNITY_SECRET_SUBTHREAD } = threadTypes; @@ -33,36 +31,14 @@ ]; type ThreadSettingsPrivacyTabProps = { - +threadSettingsOperationInProgress: boolean, +threadInfo: ThreadInfo, +queuedChanges: ThreadChanges, +setQueuedChanges: SetState, - +setErrorMessage: SetState, - +errorMessage?: ?string, }; function ThreadSettingsPrivacyTab( props: ThreadSettingsPrivacyTabProps, ): React.Node { - const { - threadSettingsOperationInProgress, - threadInfo, - queuedChanges, - setQueuedChanges, - setErrorMessage, - errorMessage, - } = props; - - const changeQueued: boolean = React.useMemo( - () => Object.values(queuedChanges).some(v => v !== null && v !== undefined), - [queuedChanges], - ); - - const onSavePrivacyThreadSettings = useOnSavePrivacyThreadSettings({ - threadInfo, - queuedChanges, - setQueuedChanges, - setErrorMessage, - }); + const { threadInfo, queuedChanges, setQueuedChanges } = props; const onOpenSelected = React.useCallback(() => { setQueuedChanges(prevQueuedChanges => @@ -99,7 +75,7 @@ ); return ( -
+
Chat type
- - - Save - - +
); } diff --git a/web/modals/threads/settings/thread-settings-save-button.react.js b/web/modals/threads/settings/thread-settings-save-button.react.js new file mode 100644 --- /dev/null +++ b/web/modals/threads/settings/thread-settings-save-button.react.js @@ -0,0 +1,79 @@ +// @flow + +import * as React from 'react'; + +import type { SetState } from 'lib/types/hook-types.js'; +import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import type { ThreadChanges } from 'lib/types/thread-types.js'; + +import { + useOnSaveGeneralThreadSettings, + useOnSavePrivacyThreadSettings, +} from './thread-settings-utils.js'; +import Button from '../../../components/button.react.js'; + +type Props = { + +activeTab: 'general' | 'privacy', + +threadInfo: ThreadInfo, + +queuedChanges: ThreadChanges, + +setQueuedChanges: SetState, + +setErrorMessage: SetState, + +threadSettingsOperationInProgress: boolean, +}; + +function ThreadSettingsSaveButton(props: Props): React.Node { + const { + activeTab, + threadInfo, + queuedChanges, + setQueuedChanges, + setErrorMessage, + threadSettingsOperationInProgress, + } = props; + + const onSaveGeneralThreadSettings = useOnSaveGeneralThreadSettings({ + threadInfo, + queuedChanges, + setQueuedChanges, + setErrorMessage, + }); + + const onSavePrivacyThreadSettings = useOnSavePrivacyThreadSettings({ + threadInfo, + queuedChanges, + setQueuedChanges, + setErrorMessage, + }); + + const changeQueued: boolean = React.useMemo( + () => Object.values(queuedChanges).some(v => v !== null && v !== undefined), + [queuedChanges], + ); + + const threadSettingsSaveButton = React.useMemo( + () => ( + + ), + [ + activeTab, + changeQueued, + onSaveGeneralThreadSettings, + onSavePrivacyThreadSettings, + threadSettingsOperationInProgress, + ], + ); + + return threadSettingsSaveButton; +} + +export default ThreadSettingsSaveButton;