aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTulir Asokan <tulir@maunium.net>2018-03-26 17:22:47 +0300
committerTulir Asokan <tulir@maunium.net>2018-03-26 17:22:47 +0300
commitb31d96881432ebb1d4918ae970fabfd6362e1186 (patch)
tree565340e18ce1f9107f52285215a53765b4afaf38
parent6095638fbb0a39fa240a135cf47e54ce5681ee9d (diff)
Show notifications and highlights in room list. Fixes #8
-rw-r--r--interface/ui.go3
-rw-r--r--matrix/matrix.go25
-rw-r--r--matrix/rooms/room.go17
-rw-r--r--ui/view-main.go43
-rw-r--r--ui/widget/message-view.go12
-rw-r--r--ui/widget/room-list.go34
-rw-r--r--ui/widget/util.go16
7 files changed, 109 insertions, 41 deletions
diff --git a/interface/ui.go b/interface/ui.go
index 43e214b..c0ddf53 100644
--- a/interface/ui.go
+++ b/interface/ui.go
@@ -18,6 +18,8 @@ package ifc
import (
"maunium.net/go/gomatrix"
+ "maunium.net/go/gomuks/matrix/pushrules"
+ "maunium.net/go/gomuks/matrix/rooms"
"maunium.net/go/gomuks/ui/types"
"maunium.net/go/gomuks/ui/widget"
"maunium.net/go/tview"
@@ -51,6 +53,7 @@ type MainView interface {
AddServiceMessage(roomID *widget.RoomView, message string)
ProcessMessageEvent(roomView *widget.RoomView, evt *gomatrix.Event) *types.Message
ProcessMembershipEvent(roomView *widget.RoomView, evt *gomatrix.Event) *types.Message
+ NotifyMessage(room *rooms.Room, message *types.Message, should pushrules.PushActionArrayShould)
}
type LoginView interface {
diff --git a/matrix/matrix.go b/matrix/matrix.go
index b72db7d..d706b95 100644
--- a/matrix/matrix.go
+++ b/matrix/matrix.go
@@ -22,13 +22,11 @@ import (
"strings"
"time"
- "github.com/gdamore/tcell"
"maunium.net/go/gomatrix"
"maunium.net/go/gomuks/config"
"maunium.net/go/gomuks/interface"
"maunium.net/go/gomuks/matrix/pushrules"
"maunium.net/go/gomuks/matrix/rooms"
- "maunium.net/go/gomuks/notification"
"maunium.net/go/gomuks/ui/debug"
"maunium.net/go/gomuks/ui/widget"
)
@@ -214,33 +212,18 @@ func (c *Container) Start() {
}
}
-// NotifyMessage sends a desktop notification of the message with the given details.
-func (c *Container) NotifyMessage(room *rooms.Room, sender, text string, critical bool) {
- if room.GetTitle() != sender {
- sender = fmt.Sprintf("%s (%s)", sender, room.GetTitle())
- }
- notification.Send(sender, text, critical)
-}
-
// HandleMessage is the event handler for the m.room.message timeline event.
func (c *Container) HandleMessage(evt *gomatrix.Event) {
- roomView := c.ui.MainView().GetRoom(evt.RoomID)
+ mainView := c.ui.MainView()
+ roomView := mainView.GetRoom(evt.RoomID)
if roomView == nil {
return
}
- message := c.ui.MainView().ProcessMessageEvent(roomView, evt)
+ message := mainView.ProcessMessageEvent(roomView, evt)
if message != nil {
pushRules := c.PushRules().GetActions(roomView.Room, evt).Should()
- if (pushRules.Notify || !pushRules.NotifySpecified) && evt.Sender != c.config.Session.UserID {
- c.NotifyMessage(roomView.Room, message.Sender, message.Text, pushRules.Highlight)
- }
- if pushRules.Highlight {
- message.TextColor = tcell.ColorYellow
- }
- if pushRules.PlaySound {
- // TODO play sound
- }
+ mainView.NotifyMessage(roomView.Room, message, pushRules)
roomView.AddMessage(message, widget.AppendMessage)
c.ui.Render()
}
diff --git a/matrix/rooms/room.go b/matrix/rooms/room.go
index c24b6db..7dd2af4 100644
--- a/matrix/rooms/room.go
+++ b/matrix/rooms/room.go
@@ -32,6 +32,16 @@ type Room struct {
PrevBatch string
// The MXID of the user whose session this room was created for.
SessionUserID string
+
+ // The number of unread messages that were notified about.
+ UnreadMessages int
+ // Whether or not any of the unread messages were highlights.
+ Highlighted bool
+ // Whether or not the room contains any new messages.
+ // This can be true even when UnreadMessages is zero if there's
+ // a notificationless message like bot notices.
+ HasNewMessages bool
+
// MXID -> Member cache calculated from membership events.
memberCache map[string]*Member
// The first non-SessionUserID member in the room. Calculated at
@@ -65,6 +75,13 @@ func (room *Room) UnlockHistory() {
}
}
+// MarkRead clears the new message statuses on this room.
+func (room *Room) MarkRead() {
+ room.UnreadMessages = 0
+ room.Highlighted = false
+ room.HasNewMessages = false
+}
+
// UpdateState updates the room's current state with the given Event. This will clobber events based
// on the type/state_key combination.
func (room *Room) UpdateState(event *gomatrix.Event) {
diff --git a/ui/view-main.go b/ui/view-main.go
index 94d09ab..a037ea0 100644
--- a/ui/view-main.go
+++ b/ui/view-main.go
@@ -28,6 +28,9 @@ import (
"maunium.net/go/gomatrix"
"maunium.net/go/gomuks/config"
"maunium.net/go/gomuks/interface"
+ "maunium.net/go/gomuks/matrix/pushrules"
+ "maunium.net/go/gomuks/matrix/rooms"
+ "maunium.net/go/gomuks/notification"
"maunium.net/go/gomuks/ui/debug"
"maunium.net/go/gomuks/ui/types"
"maunium.net/go/gomuks/ui/widget"
@@ -239,6 +242,10 @@ func (view *MainView) MouseEventHandler(roomView *widget.RoomView, event *tcell.
msgView.AddScrollOffset(-WheelScrollOffsetDiff)
view.parent.Render()
+
+ if msgView.ScrollOffset == 0 {
+ roomView.Room.MarkRead()
+ }
default:
debug.Print("Mouse event received:", event.Buttons(), event.Modifiers(), x, y)
return event
@@ -263,7 +270,11 @@ func (view *MainView) SwitchRoom(roomIndex int) {
}
view.currentRoomIndex = roomIndex % len(view.roomIDs)
view.roomView.SwitchToPage(view.CurrentRoomID())
- view.roomList.SetSelected(view.rooms[view.CurrentRoomID()].Room)
+ roomView := view.rooms[view.CurrentRoomID()]
+ if roomView.MessageView().ScrollOffset == 0 {
+ roomView.Room.MarkRead()
+ }
+ view.roomList.SetSelected(roomView.Room)
view.gmx.App().SetFocus(view)
view.parent.Render()
}
@@ -367,6 +378,36 @@ func (view *MainView) SetTyping(room string, users []string) {
}
}
+func sendNotification(room *rooms.Room, sender, text string, critical bool) {
+ if room.GetTitle() != sender {
+ sender = fmt.Sprintf("%s (%s)", sender, room.GetTitle())
+ }
+ notification.Send(sender, text, critical)
+}
+
+func (view *MainView) NotifyMessage(room *rooms.Room, message *types.Message, should pushrules.PushActionArrayShould) {
+ isCurrent := room.ID == view.CurrentRoomID()
+ if !isCurrent {
+ room.HasNewMessages = true
+ }
+ shouldNotify := (should.Notify || !should.NotifySpecified) && message.Sender != view.config.Session.UserID
+ if shouldNotify {
+ sendNotification(room, message.Sender, message.Text, should.Highlight)
+ if !isCurrent {
+ room.UnreadMessages++
+ }
+ }
+ if should.Highlight {
+ message.TextColor = tcell.ColorYellow
+ if !isCurrent {
+ room.Highlighted = true
+ }
+ }
+ if should.PlaySound {
+ // TODO play sound
+ }
+}
+
func (view *MainView) AddServiceMessage(roomView *widget.RoomView, text string) {
message := roomView.NewMessage("", "*", "gomuks.service", text, time.Now())
message.TextColor = tcell.ColorGray
diff --git a/ui/widget/message-view.go b/ui/widget/message-view.go
index 332af94..e48dddf 100644
--- a/ui/widget/message-view.go
+++ b/ui/widget/message-view.go
@@ -276,11 +276,11 @@ func getScrollbarStyle(scrollbarHere, isTop, isBottom bool) (char rune, style tc
func (view *MessageView) Draw(screen tcell.Screen) {
view.Box.Draw(screen)
- x, y, width, height := view.GetInnerRect()
+ x, y, _, height := view.GetInnerRect()
view.recalculateBuffers()
if len(view.textBuffer) == 0 {
- writeLine(screen, tview.AlignLeft, "It's quite empty in here.", x, y+height, width, tcell.ColorDefault)
+ writeLineSimple(screen, "It's quite empty in here.", x, y+height)
return
}
@@ -294,7 +294,7 @@ func (view *MessageView) Draw(screen tcell.Screen) {
if view.LoadingMessages {
message = "Loading more messages..."
}
- writeLine(screen, tview.AlignLeft, message, messageX, y, width, tcell.ColorGreen)
+ writeLineSimpleColor(screen, message, messageX, y, tcell.ColorGreen)
}
if len(view.textBuffer) != len(view.metaBuffer) {
@@ -339,16 +339,16 @@ func (view *MessageView) Draw(screen tcell.Screen) {
text, meta := view.textBuffer[index], view.metaBuffer[index]
if meta != prevMeta {
if len(meta.GetTimestamp()) > 0 {
- writeLine(screen, tview.AlignLeft, meta.GetTimestamp(), x, y+line, width, meta.GetTimestampColor())
+ writeLineSimpleColor(screen, meta.GetTimestamp(), x, y+line, meta.GetTimestampColor())
}
if prevMeta == nil || meta.GetSender() != prevMeta.GetSender() {
- writeLine(
+ writeLineColor(
screen, tview.AlignRight, meta.GetSender(),
usernameX, y+line, view.widestSender,
meta.GetSenderColor())
}
prevMeta = meta
}
- writeLine(screen, tview.AlignLeft, text, messageX, y+line, width, meta.GetTextColor())
+ writeLineSimpleColor(screen, text, messageX, y+line, meta.GetTextColor())
}
}
diff --git a/ui/widget/room-list.go b/ui/widget/room-list.go
index b908510..d2fb543 100644
--- a/ui/widget/room-list.go
+++ b/ui/widget/room-list.go
@@ -17,6 +17,9 @@
package widget
import (
+ "fmt"
+ "strconv"
+
"github.com/gdamore/tcell"
"maunium.net/go/gomuks/matrix/rooms"
"maunium.net/go/tview"
@@ -104,22 +107,31 @@ func (list *RoomList) Draw(screen tcell.Screen) {
text := item.GetTitle()
- writeLine(screen, tview.AlignLeft, text, x, y, width, list.mainTextColor)
+ lineWidth := width
- // Background color of selected text.
+ style := tcell.StyleDefault.Foreground(list.mainTextColor)
if item == list.selected {
- textWidth := tview.StringWidth(text)
- for bx := 0; bx < textWidth && bx < width; bx++ {
- m, c, style, _ := screen.GetContent(x+bx, y)
- fg, _, _ := style.Decompose()
- if fg == list.mainTextColor {
- fg = list.selectedTextColor
- }
- style = style.Background(list.selectedBackgroundColor).Foreground(fg)
- screen.SetContent(x+bx, y, m, c, style)
+ style = style.Foreground(list.selectedTextColor).Background(list.selectedBackgroundColor)
+ }
+ if item.HasNewMessages {
+ style = style.Bold(true)
+ }
+
+ if item.UnreadMessages > 0 {
+ unreadMessageCount := "99+"
+ if item.UnreadMessages < 100 {
+ unreadMessageCount = strconv.Itoa(item.UnreadMessages)
+ }
+ if item.Highlighted {
+ unreadMessageCount += "!"
}
+ unreadMessageCount = fmt.Sprintf("(%s)", unreadMessageCount)
+ writeLine(screen, tview.AlignRight, unreadMessageCount, x+lineWidth-6, y, 6, style)
+ lineWidth -= len(unreadMessageCount) + 1
}
+ writeLine(screen, tview.AlignLeft, text, x, y, lineWidth, style)
+
y++
if y >= bottomLimit {
break
diff --git a/ui/widget/util.go b/ui/widget/util.go
index 5bde263..0888210 100644
--- a/ui/widget/util.go
+++ b/ui/widget/util.go
@@ -22,7 +22,19 @@ import (
"maunium.net/go/tview"
)
-func writeLine(screen tcell.Screen, align int, line string, x, y, maxWidth int, color tcell.Color) {
+func writeLineSimple(screen tcell.Screen, line string, x, y int) {
+ writeLine(screen, tview.AlignLeft, line, x, y, 1<<30, tcell.StyleDefault)
+}
+
+func writeLineSimpleColor(screen tcell.Screen, line string, x, y int, color tcell.Color) {
+ writeLine(screen, tview.AlignLeft, line, x, y, 1<<30, tcell.StyleDefault.Foreground(color))
+}
+
+func writeLineColor(screen tcell.Screen, align int, line string, x, y, maxWidth int, color tcell.Color) {
+ writeLine(screen, align, line, x, y, maxWidth, tcell.StyleDefault.Foreground(color))
+}
+
+func writeLine(screen tcell.Screen, align int, line string, x, y, maxWidth int, style tcell.Style) {
offsetX := 0
if align == tview.AlignRight {
offsetX = maxWidth - runewidth.StringWidth(line)
@@ -37,7 +49,7 @@ func writeLine(screen tcell.Screen, align int, line string, x, y, maxWidth int,
}
for localOffset := 0; localOffset < chWidth; localOffset++ {
- screen.SetContent(x+offsetX+localOffset, y, ch, nil, tcell.StyleDefault.Foreground(color))
+ screen.SetContent(x+offsetX+localOffset, y, ch, nil, style)
}
offsetX += chWidth
if offsetX > maxWidth {