import React, { useCallback, useEffect, useState } from 'react'; import { Box, Text, Spinner } from 'folds'; import { Method } from 'matrix-js-sdk'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; import { SettingTile } from '../../../components/setting-tile'; import { DECORATION_CATEGORIES, DECORATION_CDN, decorationUrl, } from '../../lotus/avatarDecorations'; import { invalidateDecorationCache } from '../../../hooks/useAvatarDecoration'; const PROFILE_FIELD = 'io.lotus.avatar_decoration'; const CELL_SIZE = 72; function DecorationPreviewCell({ slug, name, selected, onSelect, }: { slug: string; name: string; selected: boolean; onSelect: (slug: string) => void; }) { return ( ); } export function ProfileDecoration() { const mx = useMatrixClient(); const userId = mx.getUserId()!; const [current, setCurrent] = useState(null); const [selected, setSelected] = useState(null); useEffect(() => { mx.http .authedRequest>( Method.Get, `/profile/${encodeURIComponent(userId)}/${PROFILE_FIELD}`, ) .then((res) => { const val = (res[PROFILE_FIELD] as string | undefined) ?? null; setCurrent(val); setSelected(val); }) .catch(() => { setCurrent(null); setSelected(null); }); }, [mx, userId]); const [saveState, save] = useAsyncCallback( useCallback( async (slug: string | null) => { await mx.http.authedRequest( Method.Put, `/profile/${encodeURIComponent(userId)}/${PROFILE_FIELD}`, undefined, { [PROFILE_FIELD]: slug ?? '' }, ); setCurrent(slug); invalidateDecorationCache(userId); }, [mx, userId], ), ); const saving = saveState.status === AsyncStatus.Loading; const hasChanges = selected !== current; const handleSelect = (slug: string) => { setSelected((prev) => (prev === slug ? null : slug)); }; const handleClear = () => setSelected(null); const handleSave = () => { if (!hasChanges || saving) return; save(selected); }; return ( Avatar Decoration } description={ Shown on your avatar to all Lotus Chat users. } > {/* Current selection preview */}
{selected && ( Selected decoration preview )}
{selected ? (DECORATION_CATEGORIES.flatMap((c) => c.decorations).find( (d) => d.slug === selected, )?.name ?? selected) : 'None'} {selected && ( )} {hasChanges && ( )}
{saveState.status === AsyncStatus.Error && ( Failed to save. Try again. )} {/* Category grid */}
{DECORATION_CATEGORIES.map((category) => (
{category.label}
{category.decorations.map((d) => ( ))}
))}
); }