diff options
-rw-r--r-- | app.go | 88 | ||||
-rw-r--r-- | irc/session.go | 6 | ||||
-rw-r--r-- | ui/buffers.go | 49 | ||||
-rw-r--r-- | ui/ui.go | 6 |
4 files changed, 97 insertions, 52 deletions
@@ -24,6 +24,42 @@ const ( ircEvent ) +type bound struct { + first time.Time + last time.Time + + firstMessage string + lastMessage string +} + +// Compare returns 0 if line is within bounds, -1 if before, 1 if after. +func (b *bound) Compare(line *ui.Line) int { + if line.At.Before(b.first) { + return -1 + } + if line.At.After(b.last) { + return 1 + } + if line.At.Equal(b.first) && line.Body.String() != b.firstMessage { + return -1 + } + if line.At.Equal(b.last) && line.Body.String() != b.lastMessage { + return -1 + } + return 0 +} + +// Update updates the bounds to include the given line. +func (b *bound) Update(line *ui.Line) { + if line.At.Before(b.first) { + b.first = line.At + b.firstMessage = line.Body.String() + } else if line.At.After(b.last) { + b.last = line.At + b.lastMessage = line.Body.String() + } +} + type event struct { src source content interface{} @@ -38,13 +74,15 @@ type App struct { cfg Config highlights []string - lastQuery string + lastQuery string + messageBounds map[string]bound } func NewApp(cfg Config) (app *App, err error) { app = &App{ - cfg: cfg, - events: make(chan event, eventChanSize), + cfg: cfg, + events: make(chan event, eventChanSize), + messageBounds: map[string]bound{}, } if cfg.Highlights != nil { @@ -521,10 +559,17 @@ func (app *App) handleIRCEvent(ev interface{}) { }) } case irc.SelfJoinEvent: - i := app.win.AddBuffer(ev.Channel) - app.s.NewHistoryRequest(ev.Channel). - WithLimit(200). - Before(msg.TimeOrNow()) + i, added := app.win.AddBuffer(ev.Channel) + bounds, ok := app.messageBounds[ev.Channel] + if added || !ok { + app.s.NewHistoryRequest(ev.Channel). + WithLimit(200). + Before(msg.TimeOrNow()) + } else { + app.s.NewHistoryRequest(ev.Channel). + WithLimit(200). + After(bounds.last) + } if ev.Requested { app.win.JumpBufferIndex(i) } @@ -604,16 +649,39 @@ func (app *App) handleIRCEvent(ev interface{}) { if !app.s.IsChannel(msg.Params[0]) && !app.s.IsMe(ev.User) { app.lastQuery = msg.Prefix.Name } + bounds := app.messageBounds[ev.Target] + bounds.Update(&line) + app.messageBounds[ev.Target] = bounds case irc.HistoryEvent: - var lines []ui.Line + var linesBefore []ui.Line + var linesAfter []ui.Line + bounds, hasBounds := app.messageBounds[ev.Target] for _, m := range ev.Messages { switch ev := m.(type) { case irc.MessageEvent: _, line, _ := app.formatMessage(ev) - lines = append(lines, line) + if hasBounds { + c := bounds.Compare(&line) + if c < 0 { + linesBefore = append(linesBefore, line) + } else if c > 0 { + linesAfter = append(linesAfter, line) + } + } else { + linesAfter = append(linesAfter, line) + } } } - app.win.AddLines(ev.Target, lines) + app.win.AddLines(ev.Target, linesBefore, linesAfter) + if len(linesBefore) != 0 { + bounds.Update(&linesBefore[0]) + bounds.Update(&linesBefore[len(linesBefore)-1]) + } + if len(linesAfter) != 0 { + bounds.Update(&linesAfter[0]) + bounds.Update(&linesAfter[len(linesAfter)-1]) + } + app.messageBounds[ev.Target] = bounds case irc.ErrorEvent: if isBlackListed(msg.Command) { break diff --git a/irc/session.go b/irc/session.go index d08fb22..9f00dee 100644 --- a/irc/session.go +++ b/irc/session.go @@ -429,6 +429,12 @@ func (r *HistoryRequest) doRequest() { r.s.out <- NewMessage("CHATHISTORY", args...) } +func (r *HistoryRequest) After(t time.Time) { + r.command = "AFTER" + r.bounds = []string{formatTimestamp(t)} + r.doRequest() +} + func (r *HistoryRequest) Before(t time.Time) { r.command = "BEFORE" r.bounds = []string{formatTimestamp(t)} diff --git a/ui/buffers.go b/ui/buffers.go index 91d46cd..681918c 100644 --- a/ui/buffers.go +++ b/ui/buffers.go @@ -235,16 +235,16 @@ func (bs *BufferList) Previous() { bs.list[bs.current].unread = false } -func (bs *BufferList) Add(title string) int { +func (bs *BufferList) Add(title string) (i int, added bool) { lTitle := strings.ToLower(title) for i, b := range bs.list { if strings.ToLower(b.title) == lTitle { - return i + return i, false } } bs.list = append(bs.list, buffer{title: title}) - return len(bs.list) - 1 + return len(bs.list) - 1, true } func (bs *BufferList) Remove(title string) (ok bool) { @@ -299,49 +299,20 @@ func (bs *BufferList) AddLine(title string, notify NotifyType, line Line) { } } -// "lines" needs to be sorted by their "At" field. -func (bs *BufferList) AddLines(title string, lines []Line) { +func (bs *BufferList) AddLines(title string, before, after []Line) { idx := bs.idx(title) if idx < 0 { return } b := &bs.list[idx] - limit := len(lines) - - if 0 < len(b.lines) { - // Compute "limit", the index first line of "lines" that should - // not be added to the buffer. - firstLineTime := b.lines[0].At.Unix() - firstLineBody := b.lines[0].Body - for i, l := range lines { - historyLineTime := l.At.Unix() - if historyLineTime < firstLineTime { - // This line is behind the first line of the - // buffer. - continue - } - if historyLineTime > firstLineTime { - // This line happened after the first line of - // the buffer. - limit = i - break - } - if l.Body.string == firstLineBody.string { - // This line happened at the same millisecond - // as the first line of the buffer, and has the - // same contents. Heuristic: it's the same - // message. - limit = i - break - } - } + + if len(before) != 0 { + b.lines = append(before, b.lines...) } - for i := 0; i < limit; i++ { - lines[i].computeSplitPoints() + if len(after) != 0 { + b.lines = append(b.lines, after...) } - - b.lines = append(lines[:limit], b.lines...) } func (bs *BufferList) Current() (title string) { @@ -353,7 +324,7 @@ func (bs *BufferList) CurrentOldestTime() (t *time.Time) { if 0 < len(ls) { t = &ls[0].At } - return + return t } func (bs *BufferList) ScrollUp(n int) { @@ -148,7 +148,7 @@ func (ui *UI) IsAtTop() bool { return ui.bs.IsAtTop() } -func (ui *UI) AddBuffer(title string) int { +func (ui *UI) AddBuffer(title string) (i int, added bool) { return ui.bs.Add(title) } @@ -161,8 +161,8 @@ func (ui *UI) AddLine(buffer string, notify NotifyType, line Line) { ui.bs.AddLine(buffer, notify, line) } -func (ui *UI) AddLines(buffer string, lines []Line) { - ui.bs.AddLines(buffer, lines) +func (ui *UI) AddLines(buffer string, before, after []Line) { + ui.bs.AddLines(buffer, before, after) } func (ui *UI) JumpBuffer(sub string) bool { |