summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordelthas <delthas@dille.cc>2022-02-10 16:09:42 +0100
committerdelthas <delthas@dille.cc>2022-02-11 12:18:45 +0100
commit6f083ad92d97333330904649323a146c2f9cbe10 (patch)
tree78cc7d218375dc07c15b7904a78f6511d38e25e9
parentAdd support for the soju.im/read capability and READ command (diff)
Fix event collapsing
-rw-r--r--app.go164
-rw-r--r--ui/buffers.go2
2 files changed, 93 insertions, 73 deletions
diff --git a/app.go b/app.go
index 9fd9b1a..086ba0c 100644
--- a/app.go
+++ b/app.go
@@ -990,7 +990,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
- Data: []interface{}{ev},
+ Data: []irc.Event{ev},
}
case irc.UserJoinEvent:
var body ui.StyledStringBuilder
@@ -1005,7 +1005,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
- Data: []interface{}{ev},
+ Data: []irc.Event{ev},
}
case irc.UserPartEvent:
var body ui.StyledStringBuilder
@@ -1020,7 +1020,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
- Data: []interface{}{ev},
+ Data: []irc.Event{ev},
}
case irc.UserQuitEvent:
var body ui.StyledStringBuilder
@@ -1035,7 +1035,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
- Data: []interface{}{ev},
+ Data: []irc.Event{ev},
}
case irc.TopicChangeEvent:
topic := ui.IRCString(ev.Topic).String()
@@ -1048,13 +1048,15 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
}
case irc.ModeChangeEvent:
body := fmt.Sprintf("[%s]", ev.Mode)
+ // simple mode event: <+/-><mode> <nick>
+ mergeable := len(strings.Split(ev.Mode, " ")) == 2
return ui.Line{
At: ev.Time,
Head: "--",
HeadColor: tcell.ColorGray,
Body: ui.Styled(body, tcell.StyleDefault.Foreground(tcell.ColorGray)),
- Mergeable: true,
- Data: []interface{}{ev},
+ Mergeable: mergeable,
+ Data: []irc.Event{ev},
}
default:
return ui.Line{}
@@ -1139,86 +1141,104 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
}
func (app *App) mergeLine(former *ui.Line, addition ui.Line) {
- partQuitUser := func(ev interface{}) string {
- if ev, ok := ev.(irc.UserQuitEvent); ok {
- return ev.User
- }
- if ev, ok := ev.(irc.UserPartEvent); ok {
- return ev.User
- }
- panic("unreachable")
+ events := append(former.Data.([]irc.Event), addition.Data.([]irc.Event)...)
+ type flow struct {
+ hide bool
+ state int // -1: newly offline; 1: newly online
}
+ flows := make(map[string]*flow)
+
+ eventFlows := make([]*flow, len(events))
- changed := false
-Outer:
- for _, addedEvent := range addition.Data {
- switch addedEvent := addedEvent.(type) {
+ for i, ev := range events {
+ switch ev := ev.(type) {
case irc.UserNickEvent:
- for i := len(former.Data) - 1; i >= 0; i-- {
- switch ev := former.Data[i].(type) {
- case irc.UserNickEvent:
- if ev.User == addedEvent.FormerNick && ev.FormerNick == addedEvent.User {
- former.Data = append(former.Data[:i], former.Data[i+1:]...)
- changed = true
- continue Outer
- }
- }
+ userCf := strings.ToLower(ev.User)
+ f, ok := flows[strings.ToLower(ev.FormerNick)]
+ if ok {
+ flows[userCf] = f
+ delete(flows, strings.ToLower(ev.FormerNick))
+ eventFlows[i] = f
+ } else {
+ f = &flow{}
+ flows[userCf] = f
+ eventFlows[i] = f
}
case irc.UserJoinEvent:
- for i := len(former.Data) - 1; i >= 0; i-- {
- switch ev := former.Data[i].(type) {
- case irc.UserPartEvent, irc.UserQuitEvent:
- if partQuitUser(ev) == addedEvent.User {
- former.Data = append(former.Data[:i], former.Data[i+1:]...)
- changed = true
- continue Outer
- }
+ userCf := strings.ToLower(ev.User)
+ f, ok := flows[userCf]
+ if ok {
+ if f.state == -1 {
+ f.hide = true
+ delete(flows, userCf)
+ }
+ } else {
+ f = &flow{
+ state: 1,
+ }
+ flows[userCf] = f
+ eventFlows[i] = f
+ }
+ case irc.UserPartEvent:
+ userCf := strings.ToLower(ev.User)
+ f, ok := flows[userCf]
+ if ok {
+ if f.state == 1 {
+ f.hide = true
+ delete(flows, userCf)
}
+ } else {
+ f = &flow{
+ state: -1,
+ }
+ flows[userCf] = f
+ eventFlows[i] = f
}
- case irc.UserQuitEvent, irc.UserPartEvent:
- user := partQuitUser(addedEvent)
- var toRemove []int
- for i := len(former.Data) - 1; i >= 0; i-- {
- switch ev := former.Data[i].(type) {
- case irc.UserNickEvent:
- if ev.User == user {
- user = ev.FormerNick
- toRemove = append(toRemove, i)
- }
- case irc.UserJoinEvent:
- if ev.User == user {
- for _, i := range append(toRemove, i) {
- former.Data = append(former.Data[:i], former.Data[i+1:]...)
- }
- changed = true
- continue Outer
- }
+ case irc.UserQuitEvent:
+ userCf := strings.ToLower(ev.User)
+ f, ok := flows[userCf]
+ if ok {
+ if f.state == 1 {
+ f.hide = true
+ delete(flows, userCf)
+ }
+ } else {
+ f = &flow{
+ state: -1,
}
+ flows[userCf] = f
+ eventFlows[i] = f
+ }
+ case irc.ModeChangeEvent:
+ userCf := strings.ToLower(strings.Split(ev.Mode, " ")[1])
+ f, ok := flows[userCf]
+ if ok {
+ eventFlows[i] = f
+ } else {
+ f = &flow{}
+ flows[userCf] = f
+ eventFlows[i] = f
}
}
- former.Data = append(former.Data, addedEvent)
}
- if changed {
- if len(former.Data) == 0 {
- former.Body = ui.PlainString("")
- return
+
+ newBody := new(ui.StyledStringBuilder)
+ newBody.Grow(128)
+ first := true
+ for i, ev := range events {
+ if f := eventFlows[i]; f == nil || f.hide {
+ continue
}
- var body ui.StyledStringBuilder
- body.Grow(len(former.Body.String()))
- body.WriteStyledString(app.formatEvent(former.Data[0]).Body)
- for _, ev := range former.Data[1:] {
- body.WriteString(" ")
- body.WriteStyledString(app.formatEvent(ev).Body)
+ l := app.formatEvent(ev)
+ if first {
+ first = false
+ } else {
+ newBody.WriteString(" ")
}
- former.Body = body.StyledString()
- } else {
- var newBody ui.StyledStringBuilder
- newBody.Grow(len(former.Body.String()) + 2 + len(addition.Body.String()))
- newBody.WriteStyledString(former.Body)
- newBody.WriteString(" ")
- newBody.WriteStyledString(addition.Body)
- former.Body = newBody.StyledString()
+ newBody.WriteStyledString(l.Body)
}
+ former.Body = newBody.StyledString()
+ former.Data = events
}
// updatePrompt changes the prompt text according to the application context.
diff --git a/ui/buffers.go b/ui/buffers.go
index 4c40e19..6222fbe 100644
--- a/ui/buffers.go
+++ b/ui/buffers.go
@@ -33,7 +33,7 @@ type Line struct {
HeadColor tcell.Color
Highlight bool
Mergeable bool
- Data []interface{}
+ Data interface{}
splitPoints []point
width int