| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package chat
- import (
- "fmt"
- "log/slog"
- "github.com/ayn2op/discordo/internal/config"
- "github.com/ayn2op/tview"
- "github.com/ayn2op/tview/help"
- "github.com/ayn2op/tview/keybind"
- "github.com/ayn2op/tview/picker"
- "github.com/diamondburned/arikawa/v3/discord"
- )
- const emojiPickerLayerName = "emojiPicker"
- type emojiPicker struct {
- *picker.Model
- chatView *Model
- browseMode bool
- targetMessageID discord.MessageID
- targetChannelID discord.ChannelID
- }
- var _ help.KeyMap = (*emojiPicker)(nil)
- func newEmojiPicker(cfg *config.Config, chatView *Model) *emojiPicker {
- ep := &emojiPicker{Model: picker.NewModel(), chatView: chatView}
- ConfigurePicker(ep.Model, cfg, "Emoji")
- return ep
- }
- func (ep *emojiPicker) resetBrowse() { ep.browseMode = false }
- // commonEmoji returns a list of frequently used unicode emoji for the picker.
- var commonEmoji = []struct {
- emoji string
- names string
- }{
- {"👍", "thumbsup thumbs_up +1 like"},
- {"👎", "thumbsdown thumbs_down -1 dislike"},
- {"❤️", "heart love red_heart"},
- {"😂", "joy laughing tears"},
- {"😭", "sob crying"},
- {"😊", "blush smile happy"},
- {"😍", "heart_eyes love"},
- {"🤣", "rofl rolling"},
- {"🙂", "slightly_smiling_face"},
- {"😔", "pensive sad"},
- {"🔥", "fire lit hot"},
- {"✅", "white_check_mark check yes"},
- {"❌", "x cross no"},
- {"👀", "eyes look"},
- {"🎉", "tada party celebration"},
- {"💀", "skull dead"},
- {"🤔", "thinking hmm"},
- {"😐", "neutral_face"},
- {"🤷", "shrug"},
- {"👋", "wave hello hi"},
- {"🙏", "pray please thanks"},
- {"💯", "100 hundred perfect"},
- {"😎", "sunglasses cool"},
- {"🥳", "partying_face party"},
- {"😢", "cry sad"},
- {"😅", "sweat_smile nervous"},
- {"🤗", "hugs hugging"},
- {"😤", "triumph angry"},
- {"🥺", "pleading_face"},
- {"💪", "muscle strong flex"},
- {"✨", "sparkles stars"},
- {"💜", "purple_heart"},
- {"💙", "blue_heart"},
- {"💚", "green_heart"},
- {"🧡", "orange_heart"},
- {"💛", "yellow_heart"},
- {"🖤", "black_heart"},
- {"🤍", "white_heart"},
- {"⭐", "star"},
- {"🌟", "star2 glowing_star"},
- {"😮", "open_mouth surprised"},
- {"😱", "scream shocked"},
- {"😈", "smiling_imp devil"},
- {"💀", "skull"},
- {"🤡", "clown clown_face"},
- {"🫡", "salute saluting_face"},
- {"🫠", "melting_face"},
- {"💤", "zzz sleep"},
- {"🤝", "handshake"},
- {"🏳️", "white_flag surrender"},
- }
- func (ep *emojiPicker) update() {
- items := make(picker.Items, 0, len(commonEmoji)+50)
- for _, e := range commonEmoji {
- items = append(items, picker.Item{
- Text: e.emoji + " " + e.names[:min(len(e.names), indexOf(e.names, ' '))],
- FilterText: e.names,
- Reference: discord.APIEmoji(e.emoji),
- })
- }
- // Add guild custom emoji if available
- selectedChannel := ep.chatView.SelectedChannel()
- if selectedChannel != nil && selectedChannel.GuildID.IsValid() {
- emojis, err := ep.chatView.state.Cabinet.Emojis(selectedChannel.GuildID)
- if err == nil {
- for _, emoji := range emojis {
- if !emoji.Available {
- continue
- }
- items = append(items, picker.Item{
- Text: ":" + emoji.Name + ":",
- FilterText: emoji.Name,
- Reference: emoji.APIString(),
- })
- }
- }
- }
- ep.Model.SetItems(items)
- }
- func indexOf(s string, c byte) int {
- for i := range len(s) {
- if s[i] == c {
- return i
- }
- }
- return len(s)
- }
- func (ep *emojiPicker) HandleEvent(event tview.Event) tview.Command {
- switch event := event.(type) {
- case *tview.KeyEvent:
- if cmd, handled := pickerBrowseHandleKey(event, &ep.browseMode, ep.Model, func() { ep.chatView.closeEmojiPicker() }); handled {
- return cmd
- }
- case *picker.SelectedEvent:
- apiEmoji, ok := event.Reference.(discord.APIEmoji)
- if !ok {
- return nil
- }
- channelID := ep.targetChannelID
- messageID := ep.targetMessageID
- ep.chatView.closeEmojiPicker()
- return func() tview.Event {
- if err := ep.chatView.state.React(channelID, messageID, apiEmoji); err != nil {
- slog.Error("failed to add reaction", "err", err, "emoji", fmt.Sprint(apiEmoji))
- }
- return nil
- }
- case *picker.CancelEvent:
- ep.chatView.closeEmojiPicker()
- return nil
- }
- return ep.Model.HandleEvent(event)
- }
- func (ep *emojiPicker) ShortHelp() []keybind.Keybind {
- cfg := ep.chatView.cfg.Keybinds.Picker
- return []keybind.Keybind{cfg.Up.Keybind, cfg.Down.Keybind, cfg.Select.Keybind, cfg.Cancel.Keybind}
- }
- func (ep *emojiPicker) FullHelp() [][]keybind.Keybind {
- cfg := ep.chatView.cfg.Keybinds.Picker
- return [][]keybind.Keybind{
- {cfg.Up.Keybind, cfg.Down.Keybind, cfg.Top.Keybind, cfg.Bottom.Keybind},
- {cfg.Select.Keybind, cfg.Cancel.Keybind},
- }
- }
|