import { useCallback, useMemo } from 'react'; import { useMatrixClient } from './useMatrixClient'; import { useAccountData } from './useAccountData'; const PAARROT_EMOJI_USAGE_EVENT = 'paarrot.favemojis'; const MAX_TRACKED_EMOJIS = 50; export type EmojiUsageData = { [shortcode: string]: { count: number; lastUsed: number; }; }; /** * Hook for tracking emoji usage and storing favorites in Matrix account data * Stores emoji usage stats under paarrot.favemojis in user's account data */ export function useEmojiUsage() { const mx = useMatrixClient(); const event = useAccountData(PAARROT_EMOJI_USAGE_EVENT); const emojiUsage = useMemo((): EmojiUsageData => { const content = event?.getContent(); return content || {}; }, [event]); /** * Track emoji usage (max 1 per message as per spec) * @param shortcode - Emoji shortcode (e.g., 'thumbsup', 'smile') */ const trackEmojiUsage = useCallback( async (shortcode: string) => { const now = Date.now(); const currentUsage = { ...emojiUsage }; // Update or create emoji entry currentUsage[shortcode] = { count: (currentUsage[shortcode]?.count || 0) + 1, lastUsed: now, }; // Keep only top MAX_TRACKED_EMOJIS by usage count const entries = Object.entries(currentUsage); if (entries.length > MAX_TRACKED_EMOJIS) { entries.sort((a, b) => b[1].count - a[1].count); const topEmojis = entries.slice(0, MAX_TRACKED_EMOJIS); const newUsage: EmojiUsageData = {}; topEmojis.forEach(([key, value]) => { newUsage[key] = value; }); await mx.setAccountData(PAARROT_EMOJI_USAGE_EVENT, newUsage); } else { await mx.setAccountData(PAARROT_EMOJI_USAGE_EVENT, currentUsage); } }, [mx, emojiUsage] ); /** * Get most used emoji shortcode * @returns Shortcode of most used emoji, or undefined if none tracked */ const getMostUsedEmoji = useCallback((): string | undefined => { const entries = Object.entries(emojiUsage); if (entries.length === 0) return undefined; // Sort by count descending, then by lastUsed descending entries.sort((a, b) => { if (b[1].count !== a[1].count) { return b[1].count - a[1].count; } return b[1].lastUsed - a[1].lastUsed; }); return entries[0][0]; }, [emojiUsage]); /** * Get top N most used emojis * @param count - Number of top emojis to return * @returns Array of shortcodes sorted by usage */ const getTopEmojis = useCallback( (count: number = 10): string[] => { const entries = Object.entries(emojiUsage); entries.sort((a, b) => { if (b[1].count !== a[1].count) { return b[1].count - a[1].count; } return b[1].lastUsed - a[1].lastUsed; }); return entries.slice(0, count).map(([shortcode]) => shortcode); }, [emojiUsage] ); return { emojiUsage, trackEmojiUsage, getMostUsedEmoji, getTopEmojis, }; }