diff --git a/web/modals/threads/thread-settings-general-tab.css b/web/modals/threads/thread-settings-general-tab.css index a6b5dc690..70a6ed961 100644 --- a/web/modals/threads/thread-settings-general-tab.css +++ b/web/modals/threads/thread-settings-general-tab.css @@ -1,38 +1,42 @@ div.form_title { padding: 6px 6px 0 0; font-size: 14px; font-weight: 600; vertical-align: top; color: var(--fg); } div.form_content { display: flex; font-family: var(--font-stack); color: var(--fg); margin-top: 4px; margin-bottom: 8px; } div.form_content input { margin-bottom: 4px; } div.form_content textarea { padding: 12px; background: var(--modal-bg); color: var(--fg); border: 1px solid var(--border-color); font-size: var(--m-font-16); border-radius: 4px; width: 100%; } div.form_textarea_container { margin-top: 1px; } div.edit_thread_color_container { margin-top: -5px; } 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 index e6e937c05..1266e72f3 100644 --- a/web/modals/threads/thread-settings-general-tab.react.js +++ b/web/modals/threads/thread-settings-general-tab.react.js @@ -1,115 +1,177 @@ // @flow 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'; type ThreadSettingsGeneralTabProps = { +inputDisabled: boolean, +threadInfo: ThreadInfo, +threadNamePlaceholder: string, +queuedChanges: ThreadChanges, +setQueuedChanges: SetState, + +setErrorMessage: SetState, }; function ThreadSettingsGeneralTab( props: ThreadSettingsGeneralTabProps, ): React.Node { const { inputDisabled, threadInfo, 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; setQueuedChanges( Object.freeze({ ...queuedChanges, name: firstLine( target.value !== threadInfo.name ? target.value : undefined, ), }), ); }, [queuedChanges, setQueuedChanges, threadInfo.name], ); const onChangeDescription = React.useCallback( (event: SyntheticEvent) => { const target = event.currentTarget; setQueuedChanges( Object.freeze({ ...queuedChanges, description: target.value !== threadInfo.description ? target.value : undefined, }), ); }, [queuedChanges, setQueuedChanges, threadInfo.description], ); const onChangeColor = React.useCallback( (color: string) => { setQueuedChanges( Object.freeze({ ...queuedChanges, color: color !== threadInfo.color ? color : undefined, }), ); }, [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 (
Thread name
Description