diff --git a/web/modals/threads/thread-settings-general-tab.css b/web/modals/threads/thread-settings-general-tab.css --- a/web/modals/threads/thread-settings-general-tab.css +++ b/web/modals/threads/thread-settings-general-tab.css @@ -36,3 +36,7 @@ div.color_title { margin-top: 4px; } + +.save_button { + width: 100%; +} diff --git a/web/modals/threads/thread-settings-general-tab.react.js b/web/modals/threads/thread-settings-general-tab.react.js --- a/web/modals/threads/thread-settings-general-tab.react.js +++ b/web/modals/threads/thread-settings-general-tab.react.js @@ -2,11 +2,21 @@ import * as React from 'react'; +import { + changeThreadSettingsActionTypes, + changeThreadSettings, +} from 'lib/actions/thread-actions'; import { type SetState } from 'lib/types/hook-types.js'; import { type ThreadInfo, type ThreadChanges } from 'lib/types/thread-types'; +import { + useDispatchActionPromise, + useServerCall, +} from 'lib/utils/action-utils'; import { firstLine } from 'lib/utils/string-utils'; +import Button from '../../components/button.react'; import Input from '../input.react.js'; +import { useModalContext } from '../modal-provider.react.js'; import ColorSelector from './color-selector.react.js'; import css from './thread-settings-general-tab.css'; @@ -16,6 +26,7 @@ +threadNamePlaceholder: string, +queuedChanges: ThreadChanges, +setQueuedChanges: SetState, + +setErrorMessage: SetState, }; function ThreadSettingsGeneralTab( props: ThreadSettingsGeneralTabProps, @@ -26,14 +37,24 @@ threadNamePlaceholder, queuedChanges, setQueuedChanges, + setErrorMessage, } = props; + const modalContext = useModalContext(); + const dispatchActionPromise = useDispatchActionPromise(); + const callChangeThreadSettings = useServerCall(changeThreadSettings); + const nameInputRef = React.useRef(); React.useEffect(() => { nameInputRef.current?.focus(); }, [inputDisabled]); + 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; @@ -75,6 +96,39 @@ [queuedChanges, setQueuedChanges, threadInfo.color], ); + const changeThreadSettingsAction = React.useCallback(async () => { + try { + const response = await callChangeThreadSettings({ + threadID: threadInfo.id, + changes: queuedChanges, + }); + modalContext.popModal(); + return response; + } catch (e) { + setErrorMessage('unknown_error'); + setQueuedChanges(Object.freeze({})); + throw e; + } + }, [ + callChangeThreadSettings, + modalContext, + queuedChanges, + setErrorMessage, + setQueuedChanges, + threadInfo.id, + ]); + + const onSubmit = React.useCallback( + (event: SyntheticEvent) => { + event.preventDefault(); + dispatchActionPromise( + changeThreadSettingsActionTypes, + changeThreadSettingsAction(), + ); + }, + [changeThreadSettingsAction, dispatchActionPromise], + ); + return (
@@ -108,6 +162,14 @@ onColorSelection={onChangeColor} />
+
); } diff --git a/web/modals/threads/thread-settings-modal.react.js b/web/modals/threads/thread-settings-modal.react.js --- a/web/modals/threads/thread-settings-modal.react.js +++ b/web/modals/threads/thread-settings-modal.react.js @@ -188,6 +188,7 @@ threadNamePlaceholder={namePlaceholder} queuedChanges={queuedChanges} setQueuedChanges={setQueuedChanges} + setErrorMessage={setErrorMessage} /> ); } else if (currentTabType === 'privacy') { @@ -210,7 +211,7 @@ } let buttons; - if (currentTabType !== 'delete') { + if (currentTabType === 'privacy') { buttons = (