Reaction rendering
Reactions can now be rendered inline. This can be toggled via the `ShowReactionsInline` configuration field.
This commit is contained in:
parent
041a8423a7
commit
42a4104c45
|
@ -145,6 +145,9 @@ type Config struct {
|
|||
// application, as there are some childish goons that deem it funny
|
||||
// to impersonate people or change their name every 5 minutes.
|
||||
ShowNicknames bool
|
||||
// ShowReactionsInline decides whether reactions are displayed below a
|
||||
// message.
|
||||
ShowReactionsInline bool
|
||||
|
||||
// FileHandlers allow registering specific file-handers for certain
|
||||
FileOpenHandlers map[string]string
|
||||
|
@ -208,6 +211,7 @@ func createDefaultConfig() *Config {
|
|||
IndicateChannelAccessRestriction: false,
|
||||
ShowBottomBar: true,
|
||||
ShowNicknames: true,
|
||||
ShowReactionsInline: true,
|
||||
FileOpenHandlers: make(map[string]string),
|
||||
FileOpenSaveFilesPermanently: false,
|
||||
FileDownloadSaveLocation: "~/Downloads",
|
||||
|
|
|
@ -245,3 +245,51 @@ func ReplaceMentions(message *discordgo.Message) string {
|
|||
}
|
||||
return strings.NewReplacer(replaceInstructions...).Replace(message.Content)
|
||||
}
|
||||
|
||||
// HandleReactionAdd adds a new reaction to a message or updates the count if
|
||||
// that message already has a reaction with that same emoji.
|
||||
func HandleReactionAdd(state *discordgo.State,
|
||||
message *discordgo.Message,
|
||||
newReaction *discordgo.MessageReactionAdd) {
|
||||
for _, reaction := range message.Reactions {
|
||||
//Only custom emojis have IDs and non custom unes have unique names.
|
||||
if reaction.Emoji.ID == newReaction.Emoji.ID && reaction.Emoji.Name == newReaction.Emoji.Name {
|
||||
//Match found, so we can add one to the count.
|
||||
reaction.Count++
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME Better look up emoji in cache if possible?
|
||||
message.Reactions = append(message.Reactions, &discordgo.MessageReactions{
|
||||
Count: 1,
|
||||
Emoji: &newReaction.Emoji,
|
||||
Me: newReaction.UserID == state.User.ID,
|
||||
})
|
||||
}
|
||||
|
||||
// HandleReactionRemove removes an existing reaction to a message or updates
|
||||
// the count if the same message still has reactions with the same emoji left.
|
||||
func HandleReactionRemove(state *discordgo.State,
|
||||
message *discordgo.Message,
|
||||
newReaction *discordgo.MessageReactionRemove) {
|
||||
for index, reaction := range message.Reactions {
|
||||
//Only custom emojis have IDs and non custom unes have unique names.
|
||||
if reaction.Emoji.ID == newReaction.Emoji.ID && reaction.Emoji.Name == newReaction.Emoji.Name {
|
||||
if reaction.Count <= 1 {
|
||||
message.Reactions = append(message.Reactions[:index], message.Reactions[index+1:]...)
|
||||
//No more reactions of that emoji would be left, therefore we remove the array entry.
|
||||
} else {
|
||||
//Only a single user removed his reaction, so we keep the array entry.
|
||||
reaction.Count--
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HandleReactionRemoveAll removes all reactions from all users in a message.
|
||||
func HandleReactionRemoveAll(state *discordgo.State,
|
||||
message *discordgo.Message) {
|
||||
message.Reactions = message.Reactions[0:0]
|
||||
}
|
||||
|
|
|
@ -714,8 +714,32 @@ func (chatView *ChatView) formatDefaultMessageText(message *discordgo.Message) s
|
|||
}
|
||||
}
|
||||
|
||||
var reactionText string
|
||||
if len(message.Reactions) > 0 {
|
||||
var reactionBuilder strings.Builder
|
||||
reactionBuilder.Grow(10 + len(message.Reactions)*8)
|
||||
reactionBuilder.WriteString("\nReactions: ")
|
||||
for rIndex, reaction := range message.Reactions {
|
||||
if reaction.Emoji.Name != "" {
|
||||
reactionBuilder.WriteString(tviewutil.Escape(reaction.Emoji.Name))
|
||||
if reaction.Me {
|
||||
reactionBuilder.WriteString("[::r]")
|
||||
}
|
||||
reactionBuilder.WriteRune('-')
|
||||
reactionBuilder.WriteString(strconv.FormatInt(int64(reaction.Count), 10))
|
||||
if reaction.Me {
|
||||
reactionBuilder.WriteString("[::-]")
|
||||
}
|
||||
if rIndex != len(message.Reactions)-1 {
|
||||
reactionBuilder.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
}
|
||||
reactionText = reactionBuilder.String()
|
||||
}
|
||||
|
||||
if !hasRichEmbed {
|
||||
return messageText
|
||||
return messageText + reactionText
|
||||
}
|
||||
|
||||
var messageBuffer strings.Builder
|
||||
|
@ -808,7 +832,7 @@ func (chatView *ChatView) formatDefaultMessageText(message *discordgo.Message) s
|
|||
embedBuffer.WriteRune('\n')
|
||||
}
|
||||
|
||||
return messageBuffer.String()
|
||||
return messageBuffer.String() + reactionText
|
||||
}
|
||||
|
||||
func parseCustomEmojis(text string) string {
|
||||
|
|
68
ui/window.go
68
ui/window.go
|
@ -742,6 +742,7 @@ func NewWindow(app *tview.Application, session *discordgo.Session, readyEvent *d
|
|||
|
||||
window.registerMessageEventHandler(messageInputChan, messageEditChan, messageDeleteChan, messageBulkDeleteChan)
|
||||
window.startMessageHandlerRoutines(messageInputChan, messageEditChan, messageDeleteChan, messageBulkDeleteChan)
|
||||
window.registerReactionEventHandlers()
|
||||
|
||||
window.userList = NewUserTree(window.session.State)
|
||||
|
||||
|
@ -1653,6 +1654,73 @@ func (window *Window) registerMessageEventHandler(input, edit, delete chan *disc
|
|||
})
|
||||
}
|
||||
|
||||
// registerReactionEventHandlers are responsible for updating the cache if
|
||||
// reactions are added or removed and updating the chatview if needed.
|
||||
func (window *Window) registerReactionEventHandlers() {
|
||||
window.session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageReactionAdd) {
|
||||
message, stateError := s.State.Message(m.ChannelID, m.MessageID)
|
||||
if message != nil && stateError == nil {
|
||||
s.State.Lock()
|
||||
defer func() {
|
||||
selectedChannel := window.selectedChannel
|
||||
if selectedChannel != nil && selectedChannel.ID == m.ChannelID {
|
||||
window.app.QueueUpdateDraw(func() {
|
||||
window.chatView.Lock()
|
||||
defer window.chatView.Unlock()
|
||||
|
||||
window.chatView.UpdateMessage(message)
|
||||
})
|
||||
}
|
||||
}()
|
||||
defer s.State.Unlock()
|
||||
|
||||
discordutil.HandleReactionAdd(s.State, message, m)
|
||||
}
|
||||
})
|
||||
|
||||
window.session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageReactionRemove) {
|
||||
message, stateError := s.State.Message(m.ChannelID, m.MessageID)
|
||||
if message != nil && stateError == nil {
|
||||
s.State.Lock()
|
||||
defer func() {
|
||||
selectedChannel := window.selectedChannel
|
||||
if selectedChannel != nil && selectedChannel.ID == m.ChannelID {
|
||||
window.app.QueueUpdateDraw(func() {
|
||||
window.chatView.Lock()
|
||||
defer window.chatView.Unlock()
|
||||
|
||||
window.chatView.UpdateMessage(message)
|
||||
})
|
||||
}
|
||||
}()
|
||||
defer s.State.Unlock()
|
||||
|
||||
discordutil.HandleReactionRemove(s.State, message, m)
|
||||
}
|
||||
})
|
||||
|
||||
window.session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageReactionRemoveAll) {
|
||||
message, stateError := s.State.Message(m.ChannelID, m.MessageID)
|
||||
if message != nil && stateError == nil {
|
||||
s.State.Lock()
|
||||
defer func() {
|
||||
selectedChannel := window.selectedChannel
|
||||
if selectedChannel != nil && selectedChannel.ID == m.ChannelID {
|
||||
window.app.QueueUpdateDraw(func() {
|
||||
window.chatView.Lock()
|
||||
defer window.chatView.Unlock()
|
||||
|
||||
window.chatView.UpdateMessage(message)
|
||||
})
|
||||
}
|
||||
}()
|
||||
defer s.State.Unlock()
|
||||
|
||||
discordutil.HandleReactionRemoveAll(s.State, message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// QueueUpdateDrawSynchronized is meant to be used by goroutines that aren't
|
||||
// the main goroutine in order to wait for the UI-Thread to execute the given
|
||||
// If this method is ever called from the main thread, the application will
|
||||
|
|
Loading…
Reference in New Issue