From 3c21281adaccafebe818cfb34b17ec688c94bd32 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 1 Mar 2020 17:11:56 +0200 Subject: Implement selecting message to reply/react to with keyboard --- ui/commands.go | 14 ++------ ui/messages/base.go | 15 +++++--- ui/room-view.go | 98 ++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 92 insertions(+), 35 deletions(-) diff --git a/ui/commands.go b/ui/commands.go index c7f0301..9ef0577 100644 --- a/ui/commands.go +++ b/ui/commands.go @@ -147,19 +147,14 @@ const ( ) func cmdReply(cmd *Command) { - cmd.Room.selecting = true - cmd.Room.selectReason = SelectReply - cmd.Room.selectContent = strings.Join(cmd.Args, " ") - cmd.Room.OnSelect(cmd.Room.MessageView().selected) + cmd.Room.StartSelecting(SelectReply, strings.Join(cmd.Args, " ")) } func cmdRedact(cmd *Command) { cmd.Reply("Not yet implemented 3:") // This needs to be implemented in RoomView's OnSelect method - //cmd.Room.selecting = true - //cmd.Room.selectReason = SelectRedact - //cmd.Room.OnSelect(cmd.Room.MessageView().selected) + //cmd.Room.StartSelecting(SelectRedact, "") } func cmdReact(cmd *Command) { @@ -168,10 +163,7 @@ func cmdReact(cmd *Command) { return } - cmd.Room.selecting = true - cmd.Room.selectReason = SelectReact - cmd.Room.selectContent = strings.Join(cmd.Args, " ") - cmd.Room.OnSelect(cmd.Room.MessageView().selected) + cmd.Room.StartSelecting(SelectReact, strings.Join(cmd.Args, " ")) } func cmdTags(cmd *Command) { diff --git a/ui/messages/base.go b/ui/messages/base.go index 4d82b00..e86b85c 100644 --- a/ui/messages/base.go +++ b/ui/messages/base.go @@ -85,6 +85,13 @@ type UIMessage struct { Renderer MessageRenderer } +func (msg *UIMessage) GetEvent() *event.Event { + if msg == nil { + return nil + } + return msg.Event +} + const DateFormat = "January _2, 2006" const TimeFormat = "15:04:05" @@ -314,9 +321,9 @@ func (msg *UIMessage) DrawReactions(screen mauview.Screen) { } func (msg *UIMessage) Draw(screen mauview.Screen) { - screen = msg.DrawReply(screen) - msg.Renderer.Draw(screen) - msg.DrawReactions(screen) + proxyScreen := msg.DrawReply(screen) + msg.Renderer.Draw(proxyScreen) + msg.DrawReactions(proxyScreen) if msg.IsSelected { w, h := screen.Size() for x := 0; x < w; x++ { @@ -324,7 +331,7 @@ func (msg *UIMessage) Draw(screen mauview.Screen) { mainc, combc, style, _ := screen.GetContent(x, y) _, bg, _ := style.Decompose() if bg == tcell.ColorDefault { - screen.SetContent(x, y, mainc, combc, style.Background(tcell.ColorLightSkyBlue)) + screen.SetContent(x, y, mainc, combc, style.Background(tcell.ColorDarkGreen)) } } } diff --git a/ui/room-view.go b/ui/room-view.go index 07aaef9..0e728a3 100644 --- a/ui/room-view.go +++ b/ui/room-view.go @@ -154,10 +154,29 @@ func (view *RoomView) Focus() { } func (view *RoomView) Blur() { - view.MessageView().SetSelected(nil) + view.StopSelecting() view.input.Blur() } +func (view *RoomView) StartSelecting(reason SelectReason, content string) { + view.selecting = true + view.selectReason = reason + view.selectContent = content + msgView := view.MessageView() + if msgView.selected != nil { + view.OnSelect(msgView.selected) + } else { + view.input.Blur() + view.SelectPrevious() + } +} + +func (view *RoomView) StopSelecting() { + view.selecting = false + view.selectContent = "" + view.MessageView().SetSelected(nil) +} + func (view *RoomView) OnSelect(message *messages.UIMessage) { if !view.selecting || message == nil { return @@ -176,6 +195,7 @@ func (view *RoomView) OnSelect(message *messages.UIMessage) { view.selecting = false view.selectContent = "" view.MessageView().SetSelected(nil) + view.input.Focus() } func (view *RoomView) GetStatus() string { @@ -281,18 +301,33 @@ func (view *RoomView) Draw(screen mauview.Screen) { } func (view *RoomView) ClearAllContext() { - view.MessageView().SetSelected(nil) view.SetEditing(nil) + view.StopSelecting() view.replying = nil - view.selecting = false - view.selectContent = "" + view.input.Focus() } func (view *RoomView) OnKeyEvent(event mauview.KeyEvent) bool { msgView := view.MessageView() + if view.selecting { + switch event.Key() { + case tcell.KeyEscape: + view.ClearAllContext() + case tcell.KeyUp: + view.SelectPrevious() + case tcell.KeyDown: + view.SelectNext() + case tcell.KeyEnter: + view.OnSelect(msgView.selected) + default: + return false + } + return true + } switch event.Key() { case tcell.KeyEscape: view.ClearAllContext() + return true case tcell.KeyPgUp: if msgView.IsAtTop() { go view.parent.LoadHistory(view.Room.ID) @@ -430,8 +465,8 @@ func (view *RoomView) SetEditing(evt *event.Event) { view.input.SetCursorOffset(-1) } -func (view *RoomView) findMessageToEdit(forward bool) *event.Event { - currentFound := view.editing == nil +func (view *RoomView) findMessage(current *event.Event, ownMessage, forward bool) *messages.UIMessage { + currentFound := current == nil self := view.parent.matrix.Client().UserID msgs := view.MessageView().messages for i := 0; i < len(msgs); i++ { @@ -440,13 +475,15 @@ func (view *RoomView) findMessageToEdit(forward bool) *event.Event { index = len(msgs) - i - 1 } evt := msgs[index] - if evt.EventID == "" || evt.EventID == evt.TxnID { + if evt.EventID == "" || evt.EventID == evt.TxnID || evt.IsService { continue } else if currentFound { - if evt.SenderID == self && evt.Event.Type == mautrix.EventMessage { - return evt.Event + if ownMessage && evt.SenderID == self && evt.Event.Type == mautrix.EventMessage { + return evt + } else if !ownMessage { + return evt } - } else if evt.EventID == view.editing.ID { + } else if evt.EventID == current.ID { currentFound = true } } @@ -457,17 +494,38 @@ func (view *RoomView) EditNext() { if view.editing == nil { return } - foundEvent := view.findMessageToEdit(true) - view.SetEditing(foundEvent) + foundMsg := view.findMessage(view.editing, true, true) + view.SetEditing(foundMsg.GetEvent()) } func (view *RoomView) EditPrevious() { if view.replying != nil { return } - foundEvent := view.findMessageToEdit(false) - if foundEvent != nil { - view.SetEditing(foundEvent) + foundMsg := view.findMessage(view.editing, true, false) + if foundMsg != nil { + view.SetEditing(foundMsg.GetEvent()) + } +} + +func (view *RoomView) SelectNext() { + msgView := view.MessageView() + if msgView.selected == nil { + return + } + foundMsg := view.findMessage(msgView.selected.GetEvent(), true, true) + if foundMsg != nil { + msgView.SetSelected(foundMsg) + // TODO scroll selected message into view + } +} + +func (view *RoomView) SelectPrevious() { + msgView := view.MessageView() + foundMsg := view.findMessage(msgView.selected.GetEvent(), true, false) + if foundMsg != nil { + msgView.SetSelected(foundMsg) + // TODO scroll selected message into view } } @@ -524,12 +582,12 @@ func (view *RoomView) InputSubmit(text string) { func (view *RoomView) SendReaction(eventID string, reaction string) { defer debug.Recover() - debug.Print("Reacting to", eventID, "in", view.Room.ID, "with", reaction) + debug.Print("Reacting to", eventID, "in", view.Room.ID, "with", reaction) eventID, err := view.parent.matrix.SendEvent(&event.Event{ - Event: &mautrix.Event{ - Type: mautrix.EventReaction, - RoomID: view.Room.ID, - Content: mautrix.Content{ + Event: &mautrix.Event{ + Type: mautrix.EventReaction, + RoomID: view.Room.ID, + Content: mautrix.Content{ RelatesTo: &mautrix.RelatesTo{ Type: mautrix.RelAnnotation, EventID: eventID, -- cgit v1.2.3