diff --git a/ui/commands.go b/ui/commands.go index bba1644..bc07779 100644 --- a/ui/commands.go +++ b/ui/commands.go @@ -101,7 +101,29 @@ func cmdUnknownCommand(cmd *Command) { } func cmdHelp(cmd *Command) { - cmd.Reply("Known command. Don't try \"/help\" for help.") + cmd.Reply(`/help - Show the temporary help message. + +/quit - Quit gomuks. +/clearcache - Clear cache and quit gomuks. +/logout - Log out of Matrix. + +/me - Send an emote message. +/rainbow - Send a rainbow message (markdown not supported). + +/join - Join a room. +/leave - Leave the current room. + +/invite - Invite a user. +/kick [reason] - Kick a user. +/ban [reason] - Ban a user. +/unban - Unban a user. + +/send - Send a custom event to the given room. +/msend - Send a custom event to the current room. +/setstate - Send a custom event to the given room. +/msetstate - Send a custom event to the current room. + +/toggle - Temporary command to toggle various UI features.`) } func cmdLeave(cmd *Command) { @@ -126,14 +148,14 @@ func cmdInvite(cmd *Command) { func cmdBan(cmd *Command) { if len(cmd.Args) < 1 { - cmd.Reply("Usage: /ban ") + cmd.Reply("Usage: /ban [reason]") return } reason := "you are the weakest link, goodbye!" if len(cmd.Args) >= 2 { - reason = strings.Join(cmd.Args[1:]," ") + reason = strings.Join(cmd.Args[1:], " ") } - _, err := cmd.Matrix.Client().BanUser(cmd.Room.MxRoom().ID, &mautrix.ReqBanUser{reason,cmd.Args[0]}) + _, err := cmd.Matrix.Client().BanUser(cmd.Room.MxRoom().ID, &mautrix.ReqBanUser{reason, cmd.Args[0]}) if err != nil { debug.Print("Error in ban call:", err) cmd.Reply("Failed to ban user:", err) @@ -155,14 +177,14 @@ func cmdUnban(cmd *Command) { func cmdKick(cmd *Command) { if len(cmd.Args) < 1 { - cmd.Reply("Usage: /kick ") + cmd.Reply("Usage: /kick [reason]") return } reason := "you are the weakest link, goodbye!" if len(cmd.Args) >= 2 { - reason = strings.Join(cmd.Args[1:]," ") + reason = strings.Join(cmd.Args[1:], " ") } - _, err := cmd.Matrix.Client().KickUser(cmd.Room.MxRoom().ID, &mautrix.ReqKickUser{reason,cmd.Args[0]}) + _, err := cmd.Matrix.Client().KickUser(cmd.Room.MxRoom().ID, &mautrix.ReqKickUser{reason, cmd.Args[0]}) if err != nil { debug.Print("Error in kick call:", err) debug.Print("Failed to kick user:", err) @@ -192,7 +214,7 @@ func cmdMSendEvent(cmd *Command) { cmd.Reply("Usage: /msend ") return } - cmd.Args = append([]string{cmd.Room.MxRoom().ID},cmd.Args...) + cmd.Args = append([]string{cmd.Room.MxRoom().ID}, cmd.Args...) cmdSendEvent(cmd) } @@ -230,7 +252,7 @@ func cmdMSetState(cmd *Command) { cmd.Reply("Usage: /msetstate ") return } - cmd.Args = append([]string{cmd.Room.MxRoom().ID},cmd.Args...) + cmd.Args = append([]string{cmd.Room.MxRoom().ID}, cmd.Args...) cmdSetState(cmd) } diff --git a/ui/room-list.go b/ui/room-list.go index 259e315..c8e43a6 100644 --- a/ui/room-list.go +++ b/ui/room-list.go @@ -382,6 +382,9 @@ func (list *RoomList) OnPasteEvent(event mauview.PasteEvent) bool { } func (list *RoomList) OnMouseEvent(event mauview.MouseEvent) bool { + if event.HasMotion() { + return false + } switch event.Buttons() { case tcell.WheelUp: list.AddScrollOffset(-WheelScrollOffsetDiff) @@ -411,7 +414,7 @@ func (list *RoomList) clickRoom(line, column int, mod bool) bool { trl := list.items[tag] if line--; line == -1 { trl.ToggleCollapse() - break + return true } if trl.IsCollapsed() { diff --git a/ui/room-view.go b/ui/room-view.go index 7c561cc..bc9c0cc 100644 --- a/ui/room-view.go +++ b/ui/room-view.go @@ -24,6 +24,7 @@ import ( "strings" "time" + "github.com/kyokomi/emoji" "github.com/mattn/go-runewidth" "maunium.net/go/gomuks/debug" @@ -57,6 +58,8 @@ type RoomView struct { ulBorderScreen *mauview.ProxyScreen ulScreen *mauview.ProxyScreen + inputSubmitFunc func(room *RoomView, text string) + prevScreen mauview.Screen parent *MainView @@ -125,12 +128,7 @@ func (view *RoomView) LoadHistory(matrix ifc.MatrixContainer, dir string) (int, } func (view *RoomView) SetInputSubmitFunc(fn func(room *RoomView, text string)) *RoomView { - // FIXME - /*view.input.SetDoneFunc(func(key tcell.Key) { - if key == tcell.KeyEnter { - fn(view, view.input.GetText()) - } - })*/ + view.inputSubmitFunc = fn return view } @@ -249,11 +247,27 @@ func (view *RoomView) Draw(screen mauview.Screen) { } func (view *RoomView) OnKeyEvent(event mauview.KeyEvent) bool { + msgView := view.MessageView() + switch event.Key() { + case tcell.KeyPgUp: + if msgView.IsAtTop() { + go view.parent.LoadHistory(view.Room.ID) + } + msgView.AddScrollOffset(+msgView.Height() / 2) + return true + case tcell.KeyPgDn: + msgView.AddScrollOffset(-msgView.Height() / 2) + return true + case tcell.KeyEnter: + if event.Modifiers() & tcell.ModShift == 0 && event.Modifiers() & tcell.ModCtrl == 0 && view.inputSubmitFunc != nil { + view.inputSubmitFunc(view, view.input.GetText()) + return true + } + } return view.input.OnKeyEvent(event) } func (view *RoomView) OnPasteEvent(event mauview.PasteEvent) bool { - debug.Print("PASTE EVENT", event) return view.input.OnPasteEvent(event) } @@ -320,6 +334,20 @@ func (view *RoomView) autocompleteRoom(existingText string) (completions []compl return } +func (view *RoomView) autocompleteEmoji(word string) (completions []string) { + if len(word) == 0 || word[0] != ':' { + return + } + for name, value := range emoji.CodeMap() { + if name == word { + return []string{value} + } else if strings.HasPrefix(name, word) { + completions = append(completions, name) + } + } + return +} + func (view *RoomView) InputTabComplete(text string, cursorOffset int) { debug.Print("Tab completing", cursorOffset, text) str := runewidth.Truncate(text, cursorOffset, "") @@ -344,6 +372,8 @@ func (view *RoomView) InputTabComplete(text string, cursorOffset int) { } } + strCompletions = append(strCompletions, view.autocompleteEmoji(word)...) + if len(strCompletions) > 0 { strCompletion = util.LongestCommonPrefix(strCompletions) sort.Sort(sort.StringSlice(strCompletions)) diff --git a/ui/view-main.go b/ui/view-main.go index d36a510..f726af5 100644 --- a/ui/view-main.go +++ b/ui/view-main.go @@ -231,58 +231,30 @@ func (view *MainView) OnKeyEvent(event mauview.KeyEvent) bool { case k == tcell.KeyEnd: msgView := view.currentRoom.MessageView() msgView.AddScrollOffset(-msgView.TotalHeight()) - case k == tcell.KeyCtrlN: - return view.flex.OnKeyEvent(tcell.NewEventKey(tcell.KeyEnter, '\n', event.Modifiers())) + case c == 'n' || k == tcell.KeyCtrlN: + return view.flex.OnKeyEvent(tcell.NewEventKey(tcell.KeyEnter, '\n', event.Modifiers()|tcell.ModShift)) case c == 'a': view.SwitchRoom(view.roomList.NextWithActivity()) - case c == 'l': + case c == 'l' || k == tcell.KeyCtrlL: view.ShowBare(view.currentRoom) default: goto defaultHandler } return true - } else if k == tcell.KeyAltDown || k == tcell.KeyCtrlDown { - view.SwitchRoom(view.roomList.Next()) - return true - } else if k == tcell.KeyAltUp || k == tcell.KeyCtrlUp { - view.SwitchRoom(view.roomList.Previous()) - return true - } else if view.currentRoom != nil && - (k == tcell.KeyPgUp || k == tcell.KeyPgDn || - k == tcell.KeyUp || k == tcell.KeyDown || - k == tcell.KeyEnd || k == tcell.KeyHome) { - // TODO these should be in the RoomView key handler - msgView := view.currentRoom.MessageView() - - if msgView.IsAtTop() && (k == tcell.KeyPgUp || k == tcell.KeyUp) { - go view.LoadHistory(view.currentRoom.Room.ID) - } - - switch k { - case tcell.KeyPgUp: - msgView.AddScrollOffset(msgView.Height() / 2) - case tcell.KeyPgDn: - msgView.AddScrollOffset(-msgView.Height() / 2) - default: - goto defaultHandler - } - return true - } else if k == tcell.KeyEnter { - view.InputSubmit(view.currentRoom, view.currentRoom.input.GetText()) - return true } defaultHandler: if view.config.Preferences.HideRoomList { - debug.Print("Key event going to default handler (direct to roomview)", event) return view.roomView.OnKeyEvent(event) } - debug.Print("Key event going to default handler (flex)", event) return view.flex.OnKeyEvent(event) } const WheelScrollOffsetDiff = 3 func (view *MainView) OnMouseEvent(event mauview.MouseEvent) bool { + if event.HasMotion() { + return false + } if view.modal != nil { return view.modal.OnMouseEvent(event) } @@ -290,27 +262,6 @@ func (view *MainView) OnMouseEvent(event mauview.MouseEvent) bool { return view.roomView.OnMouseEvent(event) } return view.flex.OnMouseEvent(event) - /*if event.Buttons() == tcell.ButtonNone || event.HasMotion() { - return false - } - - view.BumpFocus(view.currentRoom) - - x, y := event.Position() - - switch { - case x >= 27: - view.roomView.OnMouseEvent(mauview.OffsetMouseEvent(event, -27, 0)) - view.roomView.Focus() - view.focused = view.roomView - case x <= 25: - view.roomList.OnMouseEvent(event) - view.roomList.Focus() - view.focused = view.roomList - default: - debug.Print("Unhandled mouse event:", event.Buttons(), event.Modifiers(), x, y) - } - return false*/ } func (view *MainView) OnPasteEvent(event mauview.PasteEvent) bool {