commit 058532e
Hubert Hirtz
·
2021-09-01 10:37:37 +0000 UTC
parent 1feb31d
Fetch missed messages on reconnect just one step closer to proper CHATHISTORY support!! :=D ^v^
4 files changed,
+97,
-52
M
app.go
+78,
-10
1@@ -24,6 +24,42 @@ const (
2 ircEvent
3 )
4
5+type bound struct {
6+ first time.Time
7+ last time.Time
8+
9+ firstMessage string
10+ lastMessage string
11+}
12+
13+// Compare returns 0 if line is within bounds, -1 if before, 1 if after.
14+func (b *bound) Compare(line *ui.Line) int {
15+ if line.At.Before(b.first) {
16+ return -1
17+ }
18+ if line.At.After(b.last) {
19+ return 1
20+ }
21+ if line.At.Equal(b.first) && line.Body.String() != b.firstMessage {
22+ return -1
23+ }
24+ if line.At.Equal(b.last) && line.Body.String() != b.lastMessage {
25+ return -1
26+ }
27+ return 0
28+}
29+
30+// Update updates the bounds to include the given line.
31+func (b *bound) Update(line *ui.Line) {
32+ if line.At.Before(b.first) {
33+ b.first = line.At
34+ b.firstMessage = line.Body.String()
35+ } else if line.At.After(b.last) {
36+ b.last = line.At
37+ b.lastMessage = line.Body.String()
38+ }
39+}
40+
41 type event struct {
42 src source
43 content interface{}
44@@ -38,13 +74,15 @@ type App struct {
45 cfg Config
46 highlights []string
47
48- lastQuery string
49+ lastQuery string
50+ messageBounds map[string]bound
51 }
52
53 func NewApp(cfg Config) (app *App, err error) {
54 app = &App{
55- cfg: cfg,
56- events: make(chan event, eventChanSize),
57+ cfg: cfg,
58+ events: make(chan event, eventChanSize),
59+ messageBounds: map[string]bound{},
60 }
61
62 if cfg.Highlights != nil {
63@@ -521,10 +559,17 @@ func (app *App) handleIRCEvent(ev interface{}) {
64 })
65 }
66 case irc.SelfJoinEvent:
67- i := app.win.AddBuffer(ev.Channel)
68- app.s.NewHistoryRequest(ev.Channel).
69- WithLimit(200).
70- Before(msg.TimeOrNow())
71+ i, added := app.win.AddBuffer(ev.Channel)
72+ bounds, ok := app.messageBounds[ev.Channel]
73+ if added || !ok {
74+ app.s.NewHistoryRequest(ev.Channel).
75+ WithLimit(200).
76+ Before(msg.TimeOrNow())
77+ } else {
78+ app.s.NewHistoryRequest(ev.Channel).
79+ WithLimit(200).
80+ After(bounds.last)
81+ }
82 if ev.Requested {
83 app.win.JumpBufferIndex(i)
84 }
85@@ -604,16 +649,39 @@ func (app *App) handleIRCEvent(ev interface{}) {
86 if !app.s.IsChannel(msg.Params[0]) && !app.s.IsMe(ev.User) {
87 app.lastQuery = msg.Prefix.Name
88 }
89+ bounds := app.messageBounds[ev.Target]
90+ bounds.Update(&line)
91+ app.messageBounds[ev.Target] = bounds
92 case irc.HistoryEvent:
93- var lines []ui.Line
94+ var linesBefore []ui.Line
95+ var linesAfter []ui.Line
96+ bounds, hasBounds := app.messageBounds[ev.Target]
97 for _, m := range ev.Messages {
98 switch ev := m.(type) {
99 case irc.MessageEvent:
100 _, line, _ := app.formatMessage(ev)
101- lines = append(lines, line)
102+ if hasBounds {
103+ c := bounds.Compare(&line)
104+ if c < 0 {
105+ linesBefore = append(linesBefore, line)
106+ } else if c > 0 {
107+ linesAfter = append(linesAfter, line)
108+ }
109+ } else {
110+ linesAfter = append(linesAfter, line)
111+ }
112 }
113 }
114- app.win.AddLines(ev.Target, lines)
115+ app.win.AddLines(ev.Target, linesBefore, linesAfter)
116+ if len(linesBefore) != 0 {
117+ bounds.Update(&linesBefore[0])
118+ bounds.Update(&linesBefore[len(linesBefore)-1])
119+ }
120+ if len(linesAfter) != 0 {
121+ bounds.Update(&linesAfter[0])
122+ bounds.Update(&linesAfter[len(linesAfter)-1])
123+ }
124+ app.messageBounds[ev.Target] = bounds
125 case irc.ErrorEvent:
126 if isBlackListed(msg.Command) {
127 break
+6,
-0
1@@ -429,6 +429,12 @@ func (r *HistoryRequest) doRequest() {
2 r.s.out <- NewMessage("CHATHISTORY", args...)
3 }
4
5+func (r *HistoryRequest) After(t time.Time) {
6+ r.command = "AFTER"
7+ r.bounds = []string{formatTimestamp(t)}
8+ r.doRequest()
9+}
10+
11 func (r *HistoryRequest) Before(t time.Time) {
12 r.command = "BEFORE"
13 r.bounds = []string{formatTimestamp(t)}
+10,
-39
1@@ -235,16 +235,16 @@ func (bs *BufferList) Previous() {
2 bs.list[bs.current].unread = false
3 }
4
5-func (bs *BufferList) Add(title string) int {
6+func (bs *BufferList) Add(title string) (i int, added bool) {
7 lTitle := strings.ToLower(title)
8 for i, b := range bs.list {
9 if strings.ToLower(b.title) == lTitle {
10- return i
11+ return i, false
12 }
13 }
14
15 bs.list = append(bs.list, buffer{title: title})
16- return len(bs.list) - 1
17+ return len(bs.list) - 1, true
18 }
19
20 func (bs *BufferList) Remove(title string) (ok bool) {
21@@ -299,49 +299,20 @@ func (bs *BufferList) AddLine(title string, notify NotifyType, line Line) {
22 }
23 }
24
25-// "lines" needs to be sorted by their "At" field.
26-func (bs *BufferList) AddLines(title string, lines []Line) {
27+func (bs *BufferList) AddLines(title string, before, after []Line) {
28 idx := bs.idx(title)
29 if idx < 0 {
30 return
31 }
32
33 b := &bs.list[idx]
34- limit := len(lines)
35-
36- if 0 < len(b.lines) {
37- // Compute "limit", the index first line of "lines" that should
38- // not be added to the buffer.
39- firstLineTime := b.lines[0].At.Unix()
40- firstLineBody := b.lines[0].Body
41- for i, l := range lines {
42- historyLineTime := l.At.Unix()
43- if historyLineTime < firstLineTime {
44- // This line is behind the first line of the
45- // buffer.
46- continue
47- }
48- if historyLineTime > firstLineTime {
49- // This line happened after the first line of
50- // the buffer.
51- limit = i
52- break
53- }
54- if l.Body.string == firstLineBody.string {
55- // This line happened at the same millisecond
56- // as the first line of the buffer, and has the
57- // same contents. Heuristic: it's the same
58- // message.
59- limit = i
60- break
61- }
62- }
63+
64+ if len(before) != 0 {
65+ b.lines = append(before, b.lines...)
66 }
67- for i := 0; i < limit; i++ {
68- lines[i].computeSplitPoints()
69+ if len(after) != 0 {
70+ b.lines = append(b.lines, after...)
71 }
72-
73- b.lines = append(lines[:limit], b.lines...)
74 }
75
76 func (bs *BufferList) Current() (title string) {
77@@ -353,7 +324,7 @@ func (bs *BufferList) CurrentOldestTime() (t *time.Time) {
78 if 0 < len(ls) {
79 t = &ls[0].At
80 }
81- return
82+ return t
83 }
84
85 func (bs *BufferList) ScrollUp(n int) {
M
ui/ui.go
+3,
-3
1@@ -148,7 +148,7 @@ func (ui *UI) IsAtTop() bool {
2 return ui.bs.IsAtTop()
3 }
4
5-func (ui *UI) AddBuffer(title string) int {
6+func (ui *UI) AddBuffer(title string) (i int, added bool) {
7 return ui.bs.Add(title)
8 }
9
10@@ -161,8 +161,8 @@ func (ui *UI) AddLine(buffer string, notify NotifyType, line Line) {
11 ui.bs.AddLine(buffer, notify, line)
12 }
13
14-func (ui *UI) AddLines(buffer string, lines []Line) {
15- ui.bs.AddLines(buffer, lines)
16+func (ui *UI) AddLines(buffer string, before, after []Line) {
17+ ui.bs.AddLines(buffer, before, after)
18 }
19
20 func (ui *UI) JumpBuffer(sub string) bool {