commit 7116500
Hugo Osvaldo Barrera
·
2023-07-03 17:32:03 +0000 UTC
parent f1ca0dc
Show an "unread" indicator bar When switching to a channel, show a ruler at the last unread position. Keep the previous "last read" ruler for the focused buffer, since the "last read" timestamp is updated as soon as the buffer is focused (which would result in the ruler always rendering at the bottom). Also add a special case in `SetRead` for when the "last read" timestamp is received from the server _after_ the buffer was focused. This happens basically for the buffer that was focused at start-up. Fixes: https://todo.sr.ht/~taiite/senpai/76 Co-authored-by: delthas <delthas@dille.cc>
1 files changed,
+70,
-12
+70,
-12
1@@ -28,6 +28,14 @@ const (
2 NotifyHighlight
3 )
4
5+type optional int
6+
7+const (
8+ optionalUnset optional = iota
9+ optionalFalse
10+ optionalTrue
11+)
12+
13 type Line struct {
14 At time.Time
15 Head string
16@@ -189,6 +197,17 @@ type buffer struct {
17 read time.Time
18 openedOnce bool
19
20+ // This is the "last read" timestamp when the buffer was last focused.
21+ // If the "last read" timestamp changes while the buffer is focused,
22+ // the ruler should not move.
23+ unreadRuler time.Time
24+ // Whether to draw the unread bar for the current buffer.
25+ // The goal is to draw the unread bar iff there was at least one unread
26+ // message when the buffer was opened.
27+ // The unreadSkip value starts off as optionalUnset, then gets set to
28+ // either optionalFalse or optionalTrue when a message is received.
29+ unreadSkip optional
30+
31 lines []Line
32 topic string
33
34@@ -256,8 +275,21 @@ func (bs *BufferList) To(i int) bool {
35 if len(bs.list) <= bs.current {
36 bs.current = len(bs.list) - 1
37 }
38- bs.list[bs.current].highlights = 0
39- bs.list[bs.current].unread = false
40+ b := bs.list[bs.current]
41+ b.highlights = 0
42+ b.unread = false
43+ b.unreadRuler = b.read
44+ if len(b.lines) > 0 {
45+ l := b.lines[len(b.lines)-1]
46+ if !l.At.After(b.unreadRuler) {
47+ b.unreadSkip = optionalTrue
48+ } else {
49+ b.unreadSkip = optionalFalse
50+ }
51+ } else {
52+ b.unreadSkip = optionalUnset
53+ }
54+ bs.list[bs.current] = b
55 return true
56 }
57 return false
58@@ -268,19 +300,13 @@ func (bs *BufferList) ShowBufferNumbers(enabled bool) {
59 }
60
61 func (bs *BufferList) Next() {
62- bs.overlay = nil
63- bs.current = (bs.current + 1) % len(bs.list)
64- b := bs.cur()
65- b.highlights = 0
66- b.unread = false
67+ c := (bs.current + 1) % len(bs.list)
68+ bs.To(c)
69 }
70
71 func (bs *BufferList) Previous() {
72- bs.overlay = nil
73- bs.current = (bs.current - 1 + len(bs.list)) % len(bs.list)
74- b := bs.cur()
75- b.highlights = 0
76- b.unread = false
77+ c := (bs.current - 1 + len(bs.list)) % len(bs.list)
78+ bs.To(c)
79 }
80
81 func (bs *BufferList) NextUnread() {
82@@ -421,6 +447,13 @@ func (bs *BufferList) AddLine(netID, title string, line Line) {
83 if line.Notify == NotifyHighlight && b != current {
84 b.highlights++
85 }
86+ if b == current && b.unreadSkip == optionalUnset && len(b.lines) > 0 {
87+ if b.unreadRuler.IsZero() || !b.lines[len(b.lines)-1].At.After(b.unreadRuler) {
88+ b.unreadSkip = optionalTrue
89+ } else {
90+ b.unreadSkip = optionalFalse
91+ }
92+ }
93 }
94
95 func (bs *BufferList) AddLines(netID, title string, before, after []Line) {
96@@ -459,6 +492,13 @@ func (bs *BufferList) AddLines(netID, title string, before, after []Line) {
97 }
98 }
99 b.lines = lines
100+ if b == bs.cur() && b.unreadSkip == optionalUnset && len(b.lines) > 0 {
101+ if b.unreadRuler.IsZero() || !b.lines[len(b.lines)-1].At.After(b.unreadRuler) {
102+ b.unreadSkip = optionalTrue
103+ } else {
104+ b.unreadSkip = optionalFalse
105+ }
106+ }
107 }
108
109 func (bs *BufferList) SetTopic(netID, title string, topic string) {
110@@ -491,6 +531,10 @@ func (bs *BufferList) SetRead(netID, title string, timestamp time.Time) {
111 }
112 if b.read.Before(timestamp) {
113 b.read = timestamp
114+ // For buffers that were focused _before_ we receive any "last read" date.
115+ if b.unreadRuler.IsZero() {
116+ b.unreadRuler = b.read
117+ }
118 }
119 }
120
121@@ -783,6 +827,7 @@ func (bs *BufferList) DrawTimeline(screen tcell.Screen, x0, y0, nickColWidth int
122 }
123
124 yi := b.scrollAmt + y0 + bs.tlHeight
125+ rulerDrawn := b.unreadSkip != optionalFalse || b.unreadRuler.IsZero() || b.title == ""
126 for i := len(b.lines) - 1; 0 <= i; i-- {
127 if yi < y0 {
128 break
129@@ -792,6 +837,19 @@ func (bs *BufferList) DrawTimeline(screen tcell.Screen, x0, y0, nickColWidth int
130
131 line := &b.lines[i]
132 nls := line.NewLines(bs.textWidth)
133+
134+ if !rulerDrawn {
135+ isRead := !line.At.After(b.unreadRuler)
136+ if isRead && yi > y0 {
137+ yi--
138+ st := tcell.StyleDefault.Foreground(tcell.ColorRed)
139+ for x := x0; x < x0+bs.tlInnerWidth+nickColWidth+9; x++ {
140+ screen.SetContent(x, yi, 0x254C, nil, st)
141+ }
142+ rulerDrawn = true
143+ }
144+ }
145+
146 yi -= len(nls) + 1
147 if y0+bs.tlHeight <= yi {
148 continue