Mention window and mention revamp.
MODIFY
internal/ui/editor.go
internal/ui/editor.go
@@ -33,9 +33,12 @@ type Editor struct {
internalTextView *tview.TextView
inputCapture func(event *tcell.EventKey) *tcell.EventKey
- mentionCharacterHandler func(event *tcell.EventKey) *tcell.EventKey
+ mentionShowHandler func(namePart string)
+ mentionHideHandler func()
heightRequestHandler func(requestHeight int)
requestedHeight int
+ currentMentionBeginIdx int
+ currentMentionEndIdx int
}
// NewEditor Instanciates a ready to use text editor.
@@ -248,10 +251,36 @@ func NewEditor() *Editor {
editor.setAndFixText(fmt.Sprintf("[\"left\"]%s%s[\"\"][\"selection\"]%s[\"\"][\"right\"]%s[\"\"]",
string(left), string(character), string(selection), string(right)))
}
+ }
+
+ atIndex := -1
+ newLeft := editor.internalTextView.GetRegionText("left")
+ for i := len(newLeft) - 1; i >= 0; i-- {
+ if newLeft[i] == ' ' {
+ break
+ }
- if character == '@' && editor.mentionCharacterHandler != nil {
- editor.mentionCharacterHandler(event)
+ if newLeft[i] == '@' {
+ atIndex = i
+ break
+ }
}
+
+ if atIndex != -1 {
+ lookup := editor.GetText()[atIndex+1:]
+ endIndex := strings.Index(lookup, " ")
+
+ if endIndex == -1 {
+ endIndex = len(lookup)
+ }
+
+ editor.currentMentionBeginIdx = atIndex + 1
+ editor.currentMentionEndIdx = endIndex + atIndex
+ editor.mentionShowHandler(lookup[:endIndex])
+ } else {
+ editor.currentMentionBeginIdx = 0
+ editor.currentMentionEndIdx = 0
+ editor.mentionHideHandler()
}
editor.triggerHeightRequestIfNeccessary()
@@ -330,8 +359,20 @@ func (editor *Editor) SetInputCapture(captureFunc func(event *tcell.EventKey) *t
editor.inputCapture = captureFunc
}
-func (editor *Editor) SetMentionCharacterHandler(handlerFunc func(event *tcell.EventKey) *tcell.EventKey) {
- editor.mentionCharacterHandler = handlerFunc
+// SetMentionShowHandler sets the handler for when a mention is being requested
+func (editor *Editor) SetMentionShowHandler(handlerFunc func(namePart string)) {
+ editor.mentionShowHandler = handlerFunc
+}
+
+// SetMentionHideHandler sets the handler for when a mention is no longer being requested
+func (editor *Editor) SetMentionHideHandler(handlerFunc func()) {
+ editor.mentionHideHandler = handlerFunc
+}
+
+// GetCurrentMentionIndices gets the starting and ending indices of the input box text
+// which are to be replaced
+func (editor *Editor) GetCurrentMentionIndices() (int, int) {
+ return editor.currentMentionBeginIdx, editor.currentMentionEndIdx
}
// GetText returns the text without color tags, region tags and so on.

MODIFY
internal/ui/window.go
internal/ui/window.go
@@ -95,8 +95,14 @@ func NewWindow(app *tview.Application, discord *discordgo.Session) (*Window, err
return nil, discordError
}
- mentionWindow := tview.NewTreeView()
- mentionWindow.SetCycleSelection(true)
+ mentionWindowRootNode := tview.NewTreeNode("")
+ mentionWindow := tview.NewTreeView().
+ SetVimBindingsEnabled(false).
+ SetRoot(mentionWindowRootNode).
+ SetTopLevel(1).
+ SetCycleSelection(true)
+ mentionWindow.SetBorder(true)
+ mentionWindow.SetBorderSides(false, true, false, true)
window.leftArea = tview.NewPages()
@@ -434,6 +440,47 @@ func NewWindow(app *tview.Application, discord *discordgo.Session) (*Window, err
window.chatArea.ResizeItem(window.messageInput.GetPrimitive(), maths.Min(height, 20), 0)
})
+ window.messageInput.SetMentionShowHandler(func(namePart string) {
+ mentionWindow.GetRoot().ClearChildren()
+ window.commandView.commandOutput.Clear()
+
+ if window.selectedChannel != nil {
+ guild, discordError := window.session.State.Guild(window.selectedGuild.ID)
+ if discordError == nil {
+ for _, user := range guild.Members {
+ if strings.Contains(strings.ToUpper(user.Nick), strings.ToUpper(namePart)) || strings.Contains(strings.ToUpper(user.User.Username)+"#"+user.User.Discriminator, strings.ToUpper(namePart)) {
+ userName := user.User.Username + "#" + user.User.Discriminator
+ userNodeText := "\t" + userName
+ if len(user.Nick) > 0 {
+ userNodeText += " | " + user.Nick
+ }
+ userNode := tview.NewTreeNode(userNodeText)
+ userNode.SetReference(userName)
+ mentionWindow.GetRoot().AddChild(userNode)
+ }
+ }
+ }
+ }
+
+ if mentionWindow.GetRoot().GetChildren() != nil {
+ numChildren := len(mentionWindow.GetRoot().GetChildren())
+ if numChildren > 10 {
+ numChildren = 10
+ }
+ window.chatArea.ResizeItem(mentionWindow, numChildren, 0)
+ if numChildren > 0 {
+ mentionWindow.SetCurrentNode(mentionWindow.GetRoot().GetChildren()[0])
+ }
+ }
+ mentionWindow.SetVisible(mentionWindow.GetRoot().GetChildren() != nil)
+ window.app.SetFocus(mentionWindow)
+ })
+
+ window.messageInput.SetMentionHideHandler(func() {
+ mentionWindow.SetVisible(false)
+ window.app.SetFocus(window.messageInput.GetPrimitive())
+ })
+
window.messageInput.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
messageToSend := window.messageInput.GetText()
@@ -476,26 +523,11 @@ func NewWindow(app *tview.Application, discord *discordgo.Session) (*Window, err
//Replace formatter characters and replace emoji codes.
messageToSend = emoji.Sprintf(strings.Replace(messageToSend, "%", "%%", -1))
- if strings.Contains(messageToSend, "@") {
- messageToSend = mentionRegex.
- ReplaceAllStringFunc(messageToSend, func(part string) string {
- return strings.ToLower(part)
- })
-
- if window.selectedGuild != nil {
members, discordError := window.session.State.Members(window.selectedGuild.ID)
if discordError == nil {
+ if window.selectedGuild != nil {
for _, member := range members {
- if member.Nick != "" {
- messageToSend = strings.Replace(messageToSend, "@"+strings.ToLower(member.Nick), "<@"+member.User.ID+">", -1)
- }
-
- messageToSend = strings.Replace(messageToSend, "@"+strings.ToLower(member.User.Username), "<@"+member.User.ID+">", -1)
- }
- }
- } else if window.selectedChannel != nil {
- for _, user := range window.selectedChannel.Recipients {
- messageToSend = strings.Replace(messageToSend, "@"+strings.ToLower(user.Username), "<@"+user.ID+">", -1)
+ messageToSend = strings.Replace(messageToSend, "@"+member.User.Username+"#"+member.User.Discriminator, "<@"+member.User.ID+">", -1)
}
}
}
@@ -729,6 +761,26 @@ func NewWindow(app *tview.Application, discord *discordgo.Session) (*Window, err
}
mentionWindow.SetVisible(false)
+ mentionWindow.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
+ switch key := event.Key(); key {
+ case tcell.KeyRune, tcell.KeyDelete, tcell.KeyBackspace, tcell.KeyBackspace2, tcell.KeyLeft, tcell.KeyRight:
+ window.messageInput.internalTextView.GetInputCapture()(event)
+ return nil
+ }
+ return event
+ })
+ mentionWindow.SetSelectedFunc(func(node *tview.TreeNode) {
+ beginIdx, endIdx := window.messageInput.GetCurrentMentionIndices()
+ if beginIdx != endIdx {
+ data, ok := node.GetReference().(string)
+ if ok {
+ oldText := window.messageInput.GetText()
+ newText := oldText[:beginIdx] + strings.TrimSpace(data) + oldText[endIdx+1:] + " "
+ window.messageInput.SetText(newText)
+ }
+ }
+ window.messageInput.mentionHideHandler()
+ })
window.chatArea.AddItem(window.channelTitle, 2, 0, false)
window.chatArea.AddItem(window.messageContainer, 0, 1, false)

Mention window and mention revamp.