diff --git a/web/modals/threads/settings/thread-settings-delete-confirmation-modal.css b/web/modals/threads/settings/thread-settings-delete-confirmation-modal.css new file mode 100644 --- /dev/null +++ b/web/modals/threads/settings/thread-settings-delete-confirmation-modal.css @@ -0,0 +1,14 @@ +.container { + padding: 0 40px 32px; + border-radius: 8px; + color: var(--modal-fg); +} +.text { + font-size: var(--xl-font-20); + padding: 5px 0px 20px; +} +.buttonContainer { + display: flex; + justify-content: flex-end; + gap: 24px; +} diff --git a/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js b/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js new file mode 100644 --- /dev/null +++ b/web/modals/threads/settings/thread-settings-delete-confirmation-modal.react.js @@ -0,0 +1,52 @@ +// @flow + +import * as React from 'react'; + +import { useModalContext } from 'lib/components/modal-provider.react.js'; + +import css from './thread-settings-delete-confirmation-modal.css'; +import Button from '../../../components/button.react.js'; +import Modal from '../../modal.react.js'; + +type BaseProps = { + +isCommunityRoot: boolean, + +onConfirmation: () => void, +}; + +function ThreadDeleteConfirmationModal({ + isCommunityRoot, + onConfirmation, +}: BaseProps): React.Node { + const { popModal } = useModalContext(); + const deletionTargetText = React.useMemo( + () => (isCommunityRoot ? 'Subchannels and threads' : 'Threads'), + [isCommunityRoot], + ); + + return ( + +
+

+ {deletionTargetText} within this chat will also be permanently + deleted. Are you sure you want to continue? +

+
+ + +
+
+
+ ); +} + +export default ThreadDeleteConfirmationModal; diff --git a/web/modals/threads/settings/thread-settings-delete-tab.react.js b/web/modals/threads/settings/thread-settings-delete-tab.react.js --- a/web/modals/threads/settings/thread-settings-delete-tab.react.js +++ b/web/modals/threads/settings/thread-settings-delete-tab.react.js @@ -8,7 +8,12 @@ } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; +import { + containedThreadInfos, + threadInfoSelector, +} from 'lib/selectors/thread-selectors.js'; import { type SetState } from 'lib/types/hook-types.js'; +import { threadTypeIsCommunityRoot } from 'lib/types/thread-types-enum.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; import { useDispatchActionPromise, @@ -16,8 +21,10 @@ } from 'lib/utils/action-utils.js'; import SubmitSection from './submit-section.react.js'; +import ThreadDeleteConfirmationModal from './thread-settings-delete-confirmation-modal.react.js'; import css from './thread-settings-delete-tab.css'; import { buttonThemes } from '../../../components/button.react.js'; +import { useSelector } from '../../../redux/redux-utils.js'; type ThreadSettingsDeleteTabProps = { +threadSettingsOperationInProgress: boolean, @@ -39,14 +46,35 @@ const modalContext = useModalContext(); const dispatchActionPromise = useDispatchActionPromise(); const callDeleteThread = useServerCall(deleteThread); + const containedThreads = useSelector( + state => containedThreadInfos(state)[threadInfo.id], + ); + const currentThreadType = useSelector( + state => threadInfoSelector(state)[threadInfo.id]?.type, + ); + const isCommunityRoot = React.useMemo( + () => threadTypeIsCommunityRoot(currentThreadType), + [currentThreadType], + ); + const shouldUseDeleteConfirmationModal = React.useMemo( + () => containedThreads?.length > 0, + [containedThreads?.length], + ); + const popThreadDeleteConfirmationModal = React.useCallback(() => { + if (shouldUseDeleteConfirmationModal) { + modalContext.popModal(); + } + }, [modalContext, shouldUseDeleteConfirmationModal]); const deleteThreadAction = React.useCallback(async () => { try { setErrorMessage(''); const response = await callDeleteThread(threadInfo.id); + popThreadDeleteConfirmationModal(); modalContext.popModal(); return response; } catch (e) { + popThreadDeleteConfirmationModal(); setErrorMessage( e.message === 'invalid_credentials' ? 'permission not granted' @@ -54,14 +82,36 @@ ); throw e; } - }, [callDeleteThread, modalContext, setErrorMessage, threadInfo.id]); - + }, [ + callDeleteThread, + modalContext, + popThreadDeleteConfirmationModal, + setErrorMessage, + threadInfo.id, + ]); + const dispatchDeleteThreadAction = React.useCallback(() => { + dispatchActionPromise(deleteThreadActionTypes, deleteThreadAction()); + }, [dispatchActionPromise, deleteThreadAction]); const onDelete = React.useCallback( (event: SyntheticEvent) => { event.preventDefault(); - dispatchActionPromise(deleteThreadActionTypes, deleteThreadAction()); + if (shouldUseDeleteConfirmationModal) { + modalContext.pushModal( + , + ); + } else { + dispatchDeleteThreadAction(); + } }, - [deleteThreadAction, dispatchActionPromise], + [ + dispatchDeleteThreadAction, + isCommunityRoot, + modalContext, + shouldUseDeleteConfirmationModal, + ], ); return (