// Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { MouseEvent, ReactNode } from 'react'; import React, { useCallback, useState } from 'react'; import classNames from 'classnames'; import { ConfirmationDialog } from './ConfirmationDialog.dom.js'; import { CustomColorEditor } from './CustomColorEditor.dom.js'; import { Modal } from './Modal.dom.js'; import type { ConversationColorType, CustomColorType, } from '../types/Colors.std.js'; import { ConversationColors } from '../types/Colors.std.js'; import type { ConversationType } from '../state/ducks/conversations.preload.js'; import type { LocalizerType } from '../types/Util.std.js'; import { SampleMessageBubbles } from './SampleMessageBubbles.dom.js'; import { PanelRow } from './conversation/conversation-details/PanelRow.dom.js'; import { getCustomColorStyle } from '../util/getCustomColorStyle.dom.js'; import { useDelayedRestoreFocus } from '../hooks/useRestoreFocus.dom.js'; import { AxoDropdownMenu } from '../axo/AxoDropdownMenu.dom.js'; import { tw } from '../axo/tw.dom.js'; type CustomColorDataType = { id?: string; value?: CustomColorType; }; export type PropsDataType = { conversationId?: string; customColors?: Record; getConversationsWithCustomColor: (colorId: string) => Array; i18n: LocalizerType; isGlobal?: boolean; selectedColor?: ConversationColorType; selectedCustomColor: CustomColorDataType; }; type PropsActionType = { addCustomColor: (color: CustomColorType, conversationId?: string) => unknown; colorSelected: (payload: { conversationId: string; conversationColor?: ConversationColorType; customColorData?: { id: string; value: CustomColorType; }; }) => unknown; editCustomColor: (colorId: string, color: CustomColorType) => unknown; removeCustomColor: (colorId: string) => unknown; removeCustomColorOnConversations: (colorId: string) => unknown; resetAllChatColors: () => unknown; resetDefaultChatColor: () => unknown; setGlobalDefaultConversationColor: ( color: ConversationColorType, customColorData?: { id: string; value: CustomColorType; } ) => unknown; }; export type PropsType = PropsDataType & PropsActionType; export function ChatColorPicker({ addCustomColor, colorSelected, conversationId, customColors = {}, editCustomColor, getConversationsWithCustomColor, i18n, isGlobal = false, removeCustomColor, removeCustomColorOnConversations, resetAllChatColors, resetDefaultChatColor, selectedColor = ConversationColors[0], selectedCustomColor, setGlobalDefaultConversationColor, }: PropsType): JSX.Element { const [confirmResetAll, setConfirmResetAll] = useState(false); const [confirmResetWhat, setConfirmResetWhat] = useState(false); const [customColorToEdit, setCustomColorToEdit] = useState< CustomColorDataType | undefined >(undefined); const [focusRef] = useDelayedRestoreFocus(); const onSelectColor = ( conversationColor: ConversationColorType, customColorData?: { id: string; value: CustomColorType } ): void => { if (conversationId) { colorSelected({ conversationId, conversationColor, customColorData, }); } else { setGlobalDefaultConversationColor(conversationColor, customColorData); } }; const renderCustomColorEditorWrapper = () => ( setCustomColorToEdit(undefined)} onSave={(color: CustomColorType) => { if (customColorToEdit?.id) { editCustomColor(customColorToEdit.id, color); onSelectColor('custom', { id: customColorToEdit.id, value: color, }); } else { addCustomColor(color, conversationId); } }} /> ); return (
{customColorToEdit ? renderCustomColorEditorWrapper() : null} {confirmResetWhat ? ( { resetDefaultChatColor(); resetAllChatColors(); }, style: 'affirmative', text: i18n('icu:ChatColorPicker__resetAll'), }, ]} i18n={i18n} onClose={() => { setConfirmResetWhat(false); }} title={i18n('icu:ChatColorPicker__resetDefault')} > {i18n('icu:ChatColorPicker__confirm-reset-message')} ) : null} {confirmResetAll ? ( { setConfirmResetAll(false); }} title={i18n('icu:ChatColorPicker__resetAll')} > {i18n('icu:ChatColorPicker__confirm-reset-message')} ) : null}
{ConversationColors.map((color, i) => (

{conversationId ? ( { colorSelected({ conversationId }); }} /> ) : null} { if (isGlobal) { setConfirmResetWhat(true); } else { setConfirmResetAll(true); } }} />
); } type CustomColorBubblePropsType = { color: CustomColorType; colorId: string; getConversationsWithCustomColor: (colorId: string) => Array; i18n: LocalizerType; isSelected: boolean; onDelete: () => unknown; onDupe: () => unknown; onEdit: () => unknown; onChoose: () => unknown; }; function CustomColorBubble({ color, colorId, getConversationsWithCustomColor, i18n, isSelected, onDelete, onDupe, onEdit, onChoose, }: CustomColorBubblePropsType): JSX.Element { const [confirmDeleteCount, setConfirmDeleteCount] = useState< number | undefined >(undefined); const handleClick = useCallback( (event: MouseEvent) => { if (!isSelected) { onChoose(); event.currentTarget.focus(); } }, [isSelected, onChoose] ); const handleDelete = useCallback(() => { const conversations = getConversationsWithCustomColor(colorId); if (!conversations.length) { onDelete(); } else { setConfirmDeleteCount(conversations.length); } }, [getConversationsWithCustomColor, colorId, onDelete]); return ( <> {confirmDeleteCount != null && ( { setConfirmDeleteCount(undefined); }} title={i18n('icu:ChatColorPicker__delete--title')} > {i18n('icu:ChatColorPicker__delete--message', { num: confirmDeleteCount, })} )}