// Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { FormEventHandler, FunctionComponent, useRef, useState, } from 'react'; import { LocalizerType } from '../../../types/Util'; import { Modal } from '../../Modal'; import { AvatarEditor } from '../../AvatarEditor'; import { AvatarPreview } from '../../AvatarPreview'; import { Button, ButtonVariant } from '../../Button'; import { Spinner } from '../../Spinner'; import { GroupDescriptionInput } from '../../GroupDescriptionInput'; import { GroupTitleInput } from '../../GroupTitleInput'; import { RequestState } from './util'; import { AvatarDataType, DeleteAvatarFromDiskActionType, ReplaceAvatarActionType, SaveAvatarToDiskActionType, } from '../../../types/Avatar'; import { AvatarColorType } from '../../../types/Colors'; type PropsType = { avatarColor?: AvatarColorType; avatarPath?: string; conversationId: string; groupDescription?: string; i18n: LocalizerType; initiallyFocusDescription: boolean; makeRequest: ( _: Readonly<{ avatar?: undefined | Uint8Array; description?: string; title?: undefined | string; }> ) => void; onClose: () => void; requestState: RequestState; title: string; deleteAvatarFromDisk: DeleteAvatarFromDiskActionType; replaceAvatar: ReplaceAvatarActionType; saveAvatarToDisk: SaveAvatarToDiskActionType; userAvatarData: Array; }; export const EditConversationAttributesModal: FunctionComponent = ({ avatarColor, avatarPath: externalAvatarPath, conversationId, groupDescription: externalGroupDescription = '', i18n, initiallyFocusDescription, makeRequest, onClose, requestState, title: externalTitle, deleteAvatarFromDisk, replaceAvatar, saveAvatarToDisk, userAvatarData, }) => { const focusDescriptionRef = useRef( initiallyFocusDescription ); const focusDescription = focusDescriptionRef.current; const startingTitleRef = useRef(externalTitle); const startingAvatarPathRef = useRef(externalAvatarPath); const [editingAvatar, setEditingAvatar] = useState(false); const [avatar, setAvatar] = useState(); const [rawTitle, setRawTitle] = useState(externalTitle); const [rawGroupDescription, setRawGroupDescription] = useState( externalGroupDescription ); const [hasAvatarChanged, setHasAvatarChanged] = useState(false); const trimmedTitle = rawTitle.trim(); const trimmedDescription = rawGroupDescription.trim(); const focusRef = (el: null | HTMLElement) => { if (el) { el.focus(); focusDescriptionRef.current = undefined; } }; const hasChangedExternally = startingAvatarPathRef.current !== externalAvatarPath || startingTitleRef.current !== externalTitle; const hasTitleChanged = trimmedTitle !== externalTitle.trim(); const hasGroupDescriptionChanged = externalGroupDescription.trim() !== trimmedDescription; const isRequestActive = requestState === RequestState.Active; const canSubmit = !isRequestActive && (hasChangedExternally || hasTitleChanged || hasAvatarChanged || hasGroupDescriptionChanged) && trimmedTitle.length > 0; const onSubmit: FormEventHandler = event => { event.preventDefault(); const request: { avatar?: undefined | Uint8Array; description?: string; title?: string; } = {}; if (hasAvatarChanged) { request.avatar = avatar; } if (hasTitleChanged) { request.title = trimmedTitle; } if (hasGroupDescriptionChanged) { request.description = trimmedDescription; } makeRequest(request); }; const avatarPathForPreview = hasAvatarChanged ? undefined : externalAvatarPath; let content: JSX.Element; if (editingAvatar) { content = ( { setHasAvatarChanged(false); setEditingAvatar(false); }} onSave={newAvatar => { setAvatar(newAvatar); setHasAvatarChanged(true); setEditingAvatar(false); }} userAvatarData={userAvatarData} replaceAvatar={replaceAvatar} saveAvatarToDisk={saveAvatarToDisk} /> ); } else { content = (
{ setEditingAvatar(true); }} style={{ height: 96, width: 96, }} />
{i18n('EditConversationAttributesModal__description-warning')}
{requestState === RequestState.InactiveWithError && (
{i18n('updateGroupAttributes__error-message')}
)} ); } return ( {content} ); };