import { useState } from 'react' import { deleteCustomEmoji } from '../api/customEmoji' import { useAuth } from '../context/AuthContext' import { useCustomEmoji } from '../context/CustomEmojiContext' import type { CustomEmoji } from '../types' import { CustomEmojiUploadModal } from './CustomEmojiUploadModal' import { EmojiGlyph } from './MessageContent' import './Modal.css' interface CustomEmojiManageModalProps { onClose: () => void } // Moved out of the reaction/composer emoji picker -- that grid packs items // 9-to-a-row with a delete "x" overlapping the glyph itself, which on a // touch screen is far too easy to hit by accident while just trying to // react. A dedicated list with a normal-sized "Delete" button (plus the // same confirm() every other destructive action in this app uses) needs a // deliberate tap to actually delete something. export function CustomEmojiManageModal({ onClose }: CustomEmojiManageModalProps) { const { user } = useAuth() const { list, refresh } = useCustomEmoji() const [uploadOpen, setUploadOpen] = useState(false) const [deletingId, setDeletingId] = useState(null) async function handleDelete(emoji: CustomEmoji) { if (!confirm(`Delete :${emoji.shortcode}:? This can't be undone.`)) return setDeletingId(emoji.id) try { await deleteCustomEmoji(emoji.id) await refresh() } finally { setDeletingId(null) } } return (
e.stopPropagation()}>

Custom emoji

Site emoji
{list.length === 0 ? (

No custom emoji yet.

) : ( list.map((emoji) => { const canDelete = user?.id === emoji.uploaded_by || user?.is_site_admin return (
:{emoji.shortcode}:
Added {new Date(emoji.created_at).toLocaleDateString()}
{canDelete && ( )}
) }) )}
{uploadOpen && ( setUploadOpen(false)} onUploaded={() => { refresh() setUploadOpen(false) }} /> )}
) }