commit e4a2fe2
delthas
·
2022-10-18 15:27:20 +0000 UTC
parent faefde5
Clear highlights from MARKREAD when only NotifyNone lines are left Previously, we did not clear buffers highlight statuses on MARKREAD if there was any unread line after it. This meant that if we received a plain message, than a join message, and some other device sent us a read marker for the plain message, we would still highlight the buffer. But we should not: a join message should not highlight the buffer. This is a recurrent use case because some clients do not display join mesasges and therefore do not send read markers for it. This updates the logic to actually store the notify level (in the line) and uses it to reset the highlight status when only NotifyNone messages (or no messages) are left.
5 files changed,
+58,
-47
M
app.go
+24,
-19
1@@ -626,10 +626,11 @@ func (app *App) handleKeyEvent(ev *tcell.EventKey) {
2 input := app.win.InputEnter()
3 err := app.handleInput(buffer, input)
4 if err != nil {
5- app.win.AddLine(netID, buffer, ui.NotifyUnread, ui.Line{
6+ app.win.AddLine(netID, buffer, ui.Line{
7 At: time.Now(),
8 Head: "!!",
9 HeadColor: tcell.ColorRed,
10+ Notify: ui.NotifyUnread,
11 Body: ui.PlainSprintf("%q: %s", input, err),
12 })
13 }
14@@ -715,9 +716,10 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
15 // Mutate IRC state
16 ev, err := s.HandleMessage(msg)
17 if err != nil {
18- app.win.AddLine(netID, "", ui.NotifyUnread, ui.Line{
19+ app.win.AddLine(netID, "", ui.Line{
20 Head: "!!",
21 HeadColor: tcell.ColorRed,
22+ Notify: ui.NotifyUnread,
23 Body: ui.PlainSprintf("Received corrupt message %q: %s", msg.String(), err),
24 })
25 return
26@@ -742,7 +744,7 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
27 if s.Nick() != app.cfg.Nick {
28 body = fmt.Sprintf("Connected to the server as %s", s.Nick())
29 }
30- app.win.AddLine(netID, "", ui.NotifyNone, ui.Line{
31+ app.win.AddLine(netID, "", ui.Line{
32 At: msg.TimeOrNow(),
33 Head: "--",
34 Body: ui.PlainString(body),
35@@ -770,7 +772,7 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
36 case irc.UserNickEvent:
37 line := app.formatEvent(ev)
38 for _, c := range s.ChannelsSharedWith(ev.User) {
39- app.win.AddLine(netID, c, ui.NotifyNone, line)
40+ app.win.AddLine(netID, c, line)
41 }
42 case irc.SelfJoinEvent:
43 i, added := app.win.AddBuffer(netID, "", ev.Channel)
44@@ -801,26 +803,26 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
45 }
46 case irc.UserJoinEvent:
47 line := app.formatEvent(ev)
48- app.win.AddLine(netID, ev.Channel, ui.NotifyNone, line)
49+ app.win.AddLine(netID, ev.Channel, line)
50 case irc.SelfPartEvent:
51 app.win.RemoveBuffer(netID, ev.Channel)
52 delete(app.messageBounds, boundKey{netID, ev.Channel})
53 case irc.UserPartEvent:
54 line := app.formatEvent(ev)
55- app.win.AddLine(netID, ev.Channel, ui.NotifyNone, line)
56+ app.win.AddLine(netID, ev.Channel, line)
57 case irc.UserQuitEvent:
58 line := app.formatEvent(ev)
59 for _, c := range ev.Channels {
60- app.win.AddLine(netID, c, ui.NotifyNone, line)
61+ app.win.AddLine(netID, c, line)
62 }
63 case irc.TopicChangeEvent:
64 line := app.formatEvent(ev)
65- app.win.AddLine(netID, ev.Channel, ui.NotifyUnread, line)
66+ app.win.AddLine(netID, ev.Channel, line)
67 topic := ui.IRCString(ev.Topic).String()
68 app.win.SetTopic(netID, ev.Channel, topic)
69 case irc.ModeChangeEvent:
70 line := app.formatEvent(ev)
71- app.win.AddLine(netID, ev.Channel, ui.NotifyNone, line)
72+ app.win.AddLine(netID, ev.Channel, line)
73 case irc.InviteEvent:
74 var buffer string
75 var notify ui.NotifyType
76@@ -838,16 +840,17 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
77 notify = ui.NotifyUnread
78 body = fmt.Sprintf("%s invited %s to join this channel", ev.Inviter, ev.Invitee)
79 }
80- app.win.AddLine(netID, buffer, notify, ui.Line{
81+ app.win.AddLine(netID, buffer, ui.Line{
82 At: msg.TimeOrNow(),
83 Head: "--",
84 HeadColor: tcell.ColorGray,
85+ Notify: notify,
86 Body: ui.Styled(body, tcell.StyleDefault.Foreground(tcell.ColorGray)),
87 Highlight: notify == ui.NotifyHighlight,
88 Readable: true,
89 })
90 case irc.MessageEvent:
91- buffer, line, notification := app.formatMessage(s, ev)
92+ buffer, line := app.formatMessage(s, ev)
93 if line.IsZero() {
94 break
95 }
96@@ -861,8 +864,8 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
97 Before(msg.TimeOrNow())
98 }
99 }
100- app.win.AddLine(netID, buffer, notification, line)
101- if notification == ui.NotifyHighlight {
102+ app.win.AddLine(netID, buffer, line)
103+ if line.Notify == ui.NotifyHighlight {
104 app.notifyHighlight(buffer, ev.User, line.Body.String())
105 }
106 if !s.IsChannel(msg.Params[0]) && !s.IsMe(ev.User) {
107@@ -910,7 +913,7 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
108 var line ui.Line
109 switch ev := m.(type) {
110 case irc.MessageEvent:
111- _, line, _ = app.formatMessage(s, ev)
112+ _, line = app.formatMessage(s, ev)
113 default:
114 line = app.formatEvent(ev)
115 }
116@@ -944,7 +947,7 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
117 app.win.OpenOverlay()
118 lines := make([]ui.Line, 0, len(ev.Messages))
119 for _, m := range ev.Messages {
120- _, line, _ := app.formatMessage(s, m)
121+ _, line := app.formatMessage(s, m)
122 if line.IsZero() {
123 continue
124 }
125@@ -1229,6 +1232,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
126 At: ev.Time,
127 Head: "--",
128 HeadColor: tcell.ColorGray,
129+ Notify: ui.NotifyUnread,
130 Body: ui.Styled(body, tcell.StyleDefault.Foreground(tcell.ColorGray)),
131 Readable: true,
132 }
133@@ -1254,9 +1258,8 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
134 //
135 // It computes three things:
136 // - which buffer the message must be added to,
137-// - the UI line,
138-// - what kind of notification senpai should send.
139-func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer string, line ui.Line, notification ui.NotifyType) {
140+// - the UI line.
141+func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer string, line ui.Line) {
142 isFromSelf := s.IsMe(ev.User)
143 isToSelf := s.IsMe(ev.Target)
144 isHighlight := ev.TargetIsChannel && app.isHighlight(s, ev.Content)
145@@ -1292,6 +1295,7 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
146 buffer = ev.Target
147 }
148
149+ var notification ui.NotifyType
150 hlLine := ev.TargetIsChannel && isHighlight && !isFromSelf
151 if isFromSelf {
152 notification = ui.NotifyNone
153@@ -1332,6 +1336,7 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
154 At: ev.Time,
155 Head: head,
156 HeadColor: headColor,
157+ Notify: notification,
158 Body: body.StyledString(),
159 Highlight: hlLine,
160 Readable: true,
161@@ -1477,7 +1482,7 @@ func (app *App) printTopic(netID, buffer string) (ok bool) {
162 } else {
163 body = fmt.Sprintf("Topic (by %s, %s): %s", who, at.Local().Format("Mon Jan 2 15:04:05"), topic)
164 }
165- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
166+ app.win.AddLine(netID, buffer, ui.Line{
167 At: time.Now(),
168 Head: "--",
169 HeadColor: tcell.ColorGray,
+15,
-15
1@@ -198,7 +198,7 @@ func noCommand(app *App, content string) error {
2
3 s.PrivMsg(buffer, content)
4 if !s.HasCapability("echo-message") {
5- buffer, line, _ := app.formatMessage(s, irc.MessageEvent{
6+ buffer, line := app.formatMessage(s, irc.MessageEvent{
7 User: s.Nick(),
8 Target: buffer,
9 TargetIsChannel: s.IsChannel(buffer),
10@@ -206,7 +206,7 @@ func noCommand(app *App, content string) error {
11 Content: content,
12 Time: time.Now(),
13 })
14- app.win.AddLine(netID, buffer, ui.NotifyNone, line)
15+ app.win.AddLine(netID, buffer, line)
16 }
17
18 return nil
19@@ -239,15 +239,15 @@ func commandDoHelp(app *App, args []string) (err error) {
20 sb.SetStyle(tcell.StyleDefault)
21 sb.WriteByte(' ')
22 sb.WriteString(cmd.Usage)
23- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
24+ app.win.AddLine(netID, buffer, ui.Line{
25 At: t,
26 Body: sb.StyledString(),
27 })
28- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
29+ app.win.AddLine(netID, buffer, ui.Line{
30 At: t,
31 Body: ui.PlainSprintf(" %s", cmd.Desc),
32 })
33- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
34+ app.win.AddLine(netID, buffer, ui.Line{
35 At: t,
36 })
37 }
38@@ -261,7 +261,7 @@ func commandDoHelp(app *App, args []string) (err error) {
39 }
40
41 if len(args) == 0 {
42- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
43+ app.win.AddLine(netID, buffer, ui.Line{
44 At: t,
45 Head: "--",
46 Body: ui.PlainString("Available commands:"),
47@@ -274,7 +274,7 @@ func commandDoHelp(app *App, args []string) (err error) {
48 addLineCommands(cmdNames)
49 } else {
50 search := strings.ToUpper(args[0])
51- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
52+ app.win.AddLine(netID, buffer, ui.Line{
53 At: t,
54 Head: "--",
55 Body: ui.PlainSprintf("Commands that match \"%s\":", search),
56@@ -288,7 +288,7 @@ func commandDoHelp(app *App, args []string) (err error) {
57 cmdNames = append(cmdNames, cmdName)
58 }
59 if len(cmdNames) == 0 {
60- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
61+ app.win.AddLine(netID, buffer, ui.Line{
62 At: t,
63 Body: ui.PlainSprintf(" no command matches %q", args[0]),
64 })
65@@ -326,7 +326,7 @@ func commandDoMe(app *App, args []string) (err error) {
66 content := fmt.Sprintf("\x01ACTION %s\x01", args[0])
67 s.PrivMsg(buffer, content)
68 if !s.HasCapability("echo-message") {
69- buffer, line, _ := app.formatMessage(s, irc.MessageEvent{
70+ buffer, line := app.formatMessage(s, irc.MessageEvent{
71 User: s.Nick(),
72 Target: buffer,
73 TargetIsChannel: s.IsChannel(buffer),
74@@ -334,7 +334,7 @@ func commandDoMe(app *App, args []string) (err error) {
75 Content: content,
76 Time: time.Now(),
77 })
78- app.win.AddLine(netID, buffer, ui.NotifyNone, line)
79+ app.win.AddLine(netID, buffer, line)
80 }
81 return nil
82 }
83@@ -368,7 +368,7 @@ func commandDoNames(app *App, args []string) (err error) {
84 }
85 body := sb.StyledString()
86 // TODO remove last space
87- app.win.AddLine(netID, buffer, ui.NotifyNone, ui.Line{
88+ app.win.AddLine(netID, buffer, ui.Line{
89 At: time.Now(),
90 Head: "--",
91 HeadColor: tcell.ColorGray,
92@@ -491,7 +491,7 @@ func commandDoR(app *App, args []string) (err error) {
93 }
94 s.PrivMsg(app.lastQuery, args[0])
95 if !s.HasCapability("echo-message") {
96- buffer, line, _ := app.formatMessage(s, irc.MessageEvent{
97+ buffer, line := app.formatMessage(s, irc.MessageEvent{
98 User: s.Nick(),
99 Target: app.lastQuery,
100 TargetIsChannel: s.IsChannel(app.lastQuery),
101@@ -499,7 +499,7 @@ func commandDoR(app *App, args []string) (err error) {
102 Content: args[0],
103 Time: time.Now(),
104 })
105- app.win.AddLine(app.lastQueryNet, buffer, ui.NotifyNone, line)
106+ app.win.AddLine(app.lastQueryNet, buffer, line)
107 }
108 return nil
109 }
110@@ -696,7 +696,7 @@ func commandSendMessage(app *App, target string, content string) error {
111 }
112 s.PrivMsg(target, content)
113 if !s.HasCapability("echo-message") {
114- buffer, line, _ := app.formatMessage(s, irc.MessageEvent{
115+ buffer, line := app.formatMessage(s, irc.MessageEvent{
116 User: s.Nick(),
117 Target: target,
118 TargetIsChannel: s.IsChannel(target),
119@@ -711,7 +711,7 @@ func commandSendMessage(app *App, target string, content string) error {
120 app.win.AddBuffer(netID, "", buffer)
121 }
122
123- app.win.AddLine(netID, buffer, ui.NotifyNone, line)
124+ app.win.AddLine(netID, buffer, line)
125 }
126 return nil
127 }
+14,
-8
1@@ -33,6 +33,7 @@ type Line struct {
2 Head string
3 Body StyledString
4 HeadColor tcell.Color
5+ Notify NotifyType
6 Highlight bool
7 Readable bool
8 Mergeable bool
9@@ -366,7 +367,7 @@ func (bs *BufferList) mergeLine(former *Line, addition Line) (keepLine bool) {
10 return true
11 }
12
13-func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line) {
14+func (bs *BufferList) AddLine(netID, title string, line Line) {
15 _, b := bs.at(netID, title)
16 if b == nil {
17 return
18@@ -394,10 +395,10 @@ func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line)
19 }
20 }
21
22- if notify != NotifyNone && b != current {
23+ if line.Notify != NotifyNone && b != current {
24 b.unread = true
25 }
26- if notify == NotifyHighlight && b != current {
27+ if line.Notify == NotifyHighlight && b != current {
28 b.highlights++
29 }
30 }
31@@ -443,16 +444,21 @@ func (bs *BufferList) SetRead(netID, title string, timestamp time.Time) {
32 if b == nil {
33 return
34 }
35+ clearRead := true
36 for i := len(b.lines) - 1; i >= 0; i-- {
37 line := &b.lines[i]
38- if line.Readable {
39- if !line.At.After(timestamp) {
40- b.highlights = 0
41- b.unread = false
42- }
43+ if !line.At.After(timestamp) {
44+ break
45+ }
46+ if line.Readable && line.Notify != NotifyNone {
47+ clearRead = false
48 break
49 }
50 }
51+ if clearRead {
52+ b.highlights = 0
53+ b.unread = false
54+ }
55 if b.read.Before(timestamp) {
56 b.read = timestamp
57 }
M
ui/ui.go
+2,
-2
1@@ -270,8 +270,8 @@ func (ui *UI) RemoveNetworkBuffers(netID string) {
2 ui.memberOffset = 0
3 }
4
5-func (ui *UI) AddLine(netID, buffer string, notify NotifyType, line Line) {
6- ui.bs.AddLine(netID, buffer, notify, line)
7+func (ui *UI) AddLine(netID, buffer string, line Line) {
8+ ui.bs.AddLine(netID, buffer, line)
9 }
10
11 func (ui *UI) AddLines(netID, buffer string, before, after []Line) {
+3,
-3
1@@ -11,7 +11,7 @@ const welcomeMessage = "senpai dev build. Enter /help for a list of commands."
2
3 func (app *App) initWindow() {
4 app.win.AddBuffer("", "(home)", "")
5- app.win.AddLine("", "", ui.NotifyNone, ui.Line{
6+ app.win.AddLine("", "", ui.Line{
7 Head: "--",
8 Body: ui.PlainString(welcomeMessage),
9 At: time.Now(),
10@@ -39,9 +39,9 @@ func (app *App) queueStatusLine(netID string, line ui.Line) {
11 func (app *App) addStatusLine(netID string, line ui.Line) {
12 currentNetID, buffer := app.win.CurrentBuffer()
13 if currentNetID == netID && buffer != "" {
14- app.win.AddLine(netID, buffer, ui.NotifyNone, line)
15+ app.win.AddLine(netID, buffer, line)
16 }
17- app.win.AddLine(netID, "", ui.NotifyNone, line)
18+ app.win.AddLine(netID, "", line)
19 }
20
21 func (app *App) setStatus() {