/* * Copyright (C) 2026 Fluxer Contributors * * This file is part of Fluxer. * * Fluxer is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Fluxer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Fluxer. If not, see . */ import * as ModalActionCreators from '@app/actions/ModalActionCreators'; import {Message} from '@app/components/channel/Message'; import styles from '@app/components/modals/ConfirmModal.module.css'; import * as Modal from '@app/components/modals/Modal'; import {Button} from '@app/components/uikit/button/Button'; import {MessageRecord} from '@app/records/MessageRecord'; import ChannelStore from '@app/stores/ChannelStore'; import type {ModalProps} from '@app/utils/modals/ModalUtils'; import {MessagePreviewContext} from '@fluxer/constants/src/ChannelConstants'; import {useLingui} from '@lingui/react/macro'; import {observer} from 'mobx-react-lite'; import React, {useCallback, useMemo, useRef, useState} from 'react'; interface ConfirmModalCheckboxProps { checked?: boolean; onChange?: (checked: boolean) => void; } type ConfirmModalPrimaryVariant = 'primary' | 'danger-primary'; type ConfirmModalProps = | { title: React.ReactNode; description: React.ReactNode; message?: MessageRecord; primaryText: React.ReactNode; primaryVariant?: ConfirmModalPrimaryVariant; secondaryText?: React.ReactNode | false; size?: ModalProps['size']; onPrimary: (checkboxChecked?: boolean) => Promise | void; onSecondary?: (checkboxChecked?: boolean) => void; checkboxContent?: React.ReactElement; } | { title: React.ReactNode; description: React.ReactNode; message?: MessageRecord; primaryText?: never; primaryVariant?: never; secondaryText?: React.ReactNode | false; size?: ModalProps['size']; onPrimary?: never; onSecondary?: (checkboxChecked?: boolean) => void; checkboxContent?: React.ReactElement; }; export const ConfirmModal = observer( ({ title, description, message, primaryText, primaryVariant = 'danger-primary', secondaryText, size = 'small', onPrimary, onSecondary, checkboxContent, }: ConfirmModalProps) => { const {t} = useLingui(); const [submitting, setSubmitting] = useState(false); const [checkboxChecked, setCheckboxChecked] = useState(false); const initialFocusRef = useRef(null); const previewBehaviorOverrides = useMemo( () => ({ isEditing: false, isHighlight: false, disableContextMenu: true, disableContextMenuTracking: true, contextMenuOpen: false, }), [], ); const messageSnapshot = useMemo(() => { if (!message) return undefined; return new MessageRecord(message.toJSON()); }, [message?.id]); const handlePrimaryClick = useCallback(async () => { if (!onPrimary) { return; } setSubmitting(true); try { await onPrimary(checkboxChecked); ModalActionCreators.pop(); } finally { setSubmitting(false); } }, [onPrimary, checkboxChecked]); const handleSecondaryClick = useCallback(() => { if (onSecondary) { onSecondary(checkboxChecked); } ModalActionCreators.pop(); }, [onSecondary, checkboxChecked]); return ( {description} {React.isValidElement(checkboxContent) && React.cloneElement(checkboxContent, { checked: checkboxChecked, onChange: (value: boolean) => setCheckboxChecked(value), })} {messageSnapshot && (
)}
{secondaryText !== false && ( )} {onPrimary && primaryText && ( )}
); }, );