diff options
author | delthas <delthas@dille.cc> | 2022-02-10 16:09:42 +0100 |
---|---|---|
committer | delthas <delthas@dille.cc> | 2022-02-11 12:18:45 +0100 |
commit | 6f083ad92d97333330904649323a146c2f9cbe10 (patch) | |
tree | 78cc7d218375dc07c15b7904a78f6511d38e25e9 | |
parent | Add support for the soju.im/read capability and READ command (diff) |
Fix event collapsing
-rw-r--r-- | app.go | 164 | ||||
-rw-r--r-- | ui/buffers.go | 2 |
2 files changed, 93 insertions, 73 deletions
@@ -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 |