EmojiPackProvider.tsx raw

   1  import { buildATag, createUserEmojiListDraftEvent } from '@/lib/draft-event'
   2  import { getReplaceableCoordinateFromEvent } from '@/lib/event'
   3  import client from '@/services/client.service'
   4  import { Event, kinds } from 'nostr-tools'
   5  import { createContext, useContext, useMemo } from 'react'
   6  import { useNostr } from './NostrProvider'
   7  
   8  type TEmojiPackContext = {
   9    emojiPackCoordinateSet: Set<string>
  10    addEmojiPack: (event: Event) => Promise<void>
  11    removeEmojiPack: (event: Event) => Promise<void>
  12  }
  13  
  14  const EmojiPackContext = createContext<TEmojiPackContext | undefined>(undefined)
  15  
  16  export const useEmojiPack = () => {
  17    const context = useContext(EmojiPackContext)
  18    if (!context) {
  19      throw new Error('useEmojiPack must be used within a EmojiPackProvider')
  20    }
  21    return context
  22  }
  23  
  24  export function EmojiPackProvider({ children }: { children: React.ReactNode }) {
  25    const {
  26      pubkey: accountPubkey,
  27      userEmojiListEvent,
  28      publish,
  29      updateUserEmojiListEvent
  30    } = useNostr()
  31    const emojiPackCoordinateSet = useMemo(() => {
  32      const set = new Set<string>()
  33      userEmojiListEvent?.tags.forEach((tag) => {
  34        if (tag[0] === 'a') {
  35          set.add(tag[1])
  36        }
  37      })
  38      return set
  39    }, [userEmojiListEvent])
  40  
  41    const addEmojiPack = async (event: Event) => {
  42      if (!accountPubkey || event.kind !== kinds.Emojisets) return
  43  
  44      const userEmojiListEvent = await client.fetchUserEmojiListEvent(accountPubkey)
  45      const currentTags = userEmojiListEvent?.tags || []
  46      const coordinate = getReplaceableCoordinateFromEvent(event)
  47  
  48      // Check if already exists
  49      if (currentTags.some((tag) => tag[0] === 'a' && tag[1] === coordinate)) {
  50        return
  51      }
  52  
  53      const newUserEmojiListDraftEvent = createUserEmojiListDraftEvent(
  54        [...currentTags, buildATag(event)],
  55        userEmojiListEvent?.content
  56      )
  57      const newUserEmojiListEvent = await publish(newUserEmojiListDraftEvent)
  58      await updateUserEmojiListEvent(newUserEmojiListEvent)
  59    }
  60  
  61    const removeEmojiPack = async (event: Event) => {
  62      if (!accountPubkey) return
  63  
  64      const userEmojiListEvent = await client.fetchUserEmojiListEvent(accountPubkey)
  65      if (!userEmojiListEvent) return
  66  
  67      const coordinate = getReplaceableCoordinateFromEvent(event)
  68      const newTags = userEmojiListEvent.tags.filter((tag) => tag[0] !== 'a' || tag[1] !== coordinate)
  69      if (newTags.length === userEmojiListEvent.tags.length) return
  70  
  71      const newUserEmojiListDraftEvent = createUserEmojiListDraftEvent(
  72        newTags,
  73        userEmojiListEvent.content
  74      )
  75      const newUserEmojiListEvent = await publish(newUserEmojiListDraftEvent)
  76      await updateUserEmojiListEvent(newUserEmojiListEvent)
  77    }
  78  
  79    return (
  80      <EmojiPackContext.Provider
  81        value={{
  82          emojiPackCoordinateSet,
  83          addEmojiPack,
  84          removeEmojiPack
  85        }}
  86      >
  87        {children}
  88      </EmojiPackContext.Provider>
  89    )
  90  }
  91