import { create } from 'zustand'; import { api, type SpaceEmoji, type SpaceSticker } from '../api/client'; /** * Emojis e figurinhas por espaço. * * Carregados uma vez por espaço e mantidos em memória: o render de mensagem * consulta o mapa a cada `:nome:` encontrado, e uma busca por requisição * tornaria cada mensagem uma cascata de chamadas. */ interface ExpressionState { emojisBySpace: Map; stickersBySpace: Map; loaded: Set; load: (spaceId: string) => Promise; emojiByName: (spaceId: string, name: string) => SpaceEmoji | undefined; setEmojis: (spaceId: string, emojis: SpaceEmoji[]) => void; setStickers: (spaceId: string, stickers: SpaceSticker[]) => void; } export const useExpressionStore = create((set, get) => ({ emojisBySpace: new Map(), stickersBySpace: new Map(), loaded: new Set(), load: async (spaceId) => { if (!spaceId || get().loaded.has(spaceId)) return; // Marcado antes da resposta: entrar num espaço dispara vários renders, e // sem isso a mesma busca sairia várias vezes em paralelo. set((s) => ({ loaded: new Set(s.loaded).add(spaceId) })); try { const [{ emojis }, { stickers }] = await Promise.all([ api.expressions.emojis(spaceId), api.expressions.stickers(spaceId), ]); set((s) => ({ emojisBySpace: new Map(s.emojisBySpace).set(spaceId, emojis), stickersBySpace: new Map(s.stickersBySpace).set(spaceId, stickers), })); } catch { // Sem emojis próprios a conversa segue: `:nome:` fica como texto. set((s) => { const loaded = new Set(s.loaded); loaded.delete(spaceId); return { loaded }; }); } }, emojiByName: (spaceId, name) => get().emojisBySpace.get(spaceId)?.find((e) => e.name === name), setEmojis: (spaceId, emojis) => set((s) => ({ emojisBySpace: new Map(s.emojisBySpace).set(spaceId, emojis) })), setStickers: (spaceId, stickers) => set((s) => ({ stickersBySpace: new Map(s.stickersBySpace).set(spaceId, stickers) })), }));