8bd498a4d7
Private emojis stored in the encrypted .content of kind 30030 EmojiPackEvents were honest about being private but useless: they never appeared in the `:` autocomplete or the reaction menu, even for the pack owner. This wires up async decryption so pack owners actually see their private emojis everywhere public ones already show. - quartz: add EmojiPackEvent.publicEmojis() / privateEmojis(signer) / allEmojis(signer) helpers, mirroring BookmarkListEvent's public/private accessor split. privateEmojis() returns null for non-author signers, which preserves the rule that foreign packs cannot expose private entries. - commons: EmojiPackState.mergePack becomes suspend (mergePackWithPrivate) and decrypts inside the existing combineTransform hot path; the StateFlow consumers (account.emoji.myEmojis → EmojiSuggestionState) get private entries automatically once decryption resolves. The combiner already runs on Dispatchers.IO so the suspending decrypt does not block the UI. - amethyst: RenderEmojiPack uses produceState to seed with the public list immediately and replace with the merged list once allEmojis(signer) resolves — keeps the reaction-menu gallery responsive. - AddEmojiDialog explainer + KDoc no longer claim private emojis are invisible; OwnedEmojiPacksState.toOwnedEmojiPack uses the new accessors. - Test EmojiPackEventTest covers public/private/all access including the foreign-signer case. https://claude.ai/code/session_01SNG3nj8ZZDChggTsg1qznn