summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app.go88
-rw-r--r--irc/session.go6
-rw-r--r--ui/buffers.go49
-rw-r--r--ui/ui.go6
4 files changed, 97 insertions, 52 deletions
diff --git a/app.go b/app.go
index 3d6d3a2..ca2cc6f 100644
--- a/app.go
+++ b/app.go
@@ -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) {
diff --git a/ui/ui.go b/ui/ui.go
index 39f936c..8fb6227 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -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 {