import { Avatar, Box, Button, Chip, color, Icon, Icons, Input, Spinner, Text, TextArea, } from 'folds'; import React, { FormEventHandler, useCallback, useMemo, useState } from 'react'; import { useAtomValue } from 'jotai'; import Linkify from 'linkify-react'; import classNames from 'classnames'; import { JoinRule, MatrixError } from 'matrix-js-sdk'; import { SequenceCard } from '../../../components/sequence-card'; import { SequenceCardStyle } from '../../room-settings/styles.css'; import { useRoom } from '../../../hooks/useRoom'; import { useRoomAvatar, useRoomJoinRule, useRoomName, useRoomTopic, } from '../../../hooks/useRoomMeta'; import { mDirectAtom } from '../../../state/mDirectList'; import { BreakWord, LineClamp3 } from '../../../styles/Text.css'; import { LINKIFY_OPTS } from '../../../plugins/react-custom-html-parser'; import { RoomAvatar, RoomIcon } from '../../../components/room-avatar'; import { mxcUrlToHttp } from '../../../utils/matrix'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication'; import { IPowerLevels, usePowerLevelsAPI } from '../../../hooks/usePowerLevels'; import { StateEvent } from '../../../../types/matrix/room'; import { CompactUploadCardRenderer } from '../../../components/upload-card'; import { useObjectURL } from '../../../hooks/useObjectURL'; import { createUploadAtom, UploadSuccess } from '../../../state/upload'; import { useFilePicker } from '../../../hooks/useFilePicker'; import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; import { useAlive } from '../../../hooks/useAlive'; type RoomProfileEditProps = { canEditAvatar: boolean; canEditName: boolean; canEditTopic: boolean; avatar?: string; name: string; topic: string; onClose: () => void; }; export function RoomProfileEdit({ canEditAvatar, canEditName, canEditTopic, avatar, name, topic, onClose, }: RoomProfileEditProps) { const room = useRoom(); const mx = useMatrixClient(); const alive = useAlive(); const useAuthentication = useMediaAuthentication(); const joinRule = useRoomJoinRule(room); const [roomAvatar, setRoomAvatar] = useState(avatar); const avatarUrl = roomAvatar ? mxcUrlToHttp(mx, roomAvatar, useAuthentication) ?? undefined : undefined; const [imageFile, setImageFile] = useState(); const avatarFileUrl = useObjectURL(imageFile); const uploadingAvatar = avatarFileUrl ? roomAvatar === avatar : false; const uploadAtom = useMemo(() => { if (imageFile) return createUploadAtom(imageFile); return undefined; }, [imageFile]); const pickFile = useFilePicker(setImageFile, false); const handleRemoveUpload = useCallback(() => { setImageFile(undefined); setRoomAvatar(avatar); }, [avatar]); const handleUploaded = useCallback((upload: UploadSuccess) => { setRoomAvatar(upload.mxc); }, []); const [submitState, submit] = useAsyncCallback( useCallback( async (roomAvatarMxc?: string | null, roomName?: string, roomTopic?: string) => { if (roomAvatarMxc !== undefined) { await mx.sendStateEvent(room.roomId, StateEvent.RoomAvatar as any, { url: roomAvatarMxc, }); } if (roomName !== undefined) { await mx.sendStateEvent(room.roomId, StateEvent.RoomName as any, { name: roomName }); } if (roomTopic !== undefined) { await mx.sendStateEvent(room.roomId, StateEvent.RoomTopic as any, { topic: roomTopic }); } }, [mx, room.roomId] ) ); const submitting = submitState.status === AsyncStatus.Loading; const handleSubmit: FormEventHandler = (evt) => { evt.preventDefault(); if (uploadingAvatar) return; const target = evt.target as HTMLFormElement | undefined; const nameInput = target?.nameInput as HTMLInputElement | undefined; const topicTextArea = target?.topicTextArea as HTMLTextAreaElement | undefined; if (!nameInput || !topicTextArea) return; const roomName = nameInput.value.trim(); const roomTopic = topicTextArea.value.trim(); if (roomAvatar === avatar && roomName === name && roomTopic === topic) { return; } submit( roomAvatar === avatar ? undefined : roomAvatar || null, roomName === name ? undefined : roomName, roomTopic === topic ? undefined : roomTopic ).then(() => { if (alive()) { onClose(); } }); }; return ( Avatar {uploadAtom ? ( ) : ( {!roomAvatar && avatar && ( )} {roomAvatar && ( )} )} ( )} /> Name Topic