commit 6f083ad

delthas  ·  2022-02-10 15:09:42 +0000 UTC
parent b46a755
Fix event collapsing
2 files changed,  +93, -73
M app.go
M app.go
+92, -72
  1@@ -990,7 +990,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
  2 			HeadColor: tcell.ColorGray,
  3 			Body:      body.StyledString(),
  4 			Mergeable: true,
  5-			Data:      []interface{}{ev},
  6+			Data:      []irc.Event{ev},
  7 		}
  8 	case irc.UserJoinEvent:
  9 		var body ui.StyledStringBuilder
 10@@ -1005,7 +1005,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 11 			HeadColor: tcell.ColorGray,
 12 			Body:      body.StyledString(),
 13 			Mergeable: true,
 14-			Data:      []interface{}{ev},
 15+			Data:      []irc.Event{ev},
 16 		}
 17 	case irc.UserPartEvent:
 18 		var body ui.StyledStringBuilder
 19@@ -1020,7 +1020,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 20 			HeadColor: tcell.ColorGray,
 21 			Body:      body.StyledString(),
 22 			Mergeable: true,
 23-			Data:      []interface{}{ev},
 24+			Data:      []irc.Event{ev},
 25 		}
 26 	case irc.UserQuitEvent:
 27 		var body ui.StyledStringBuilder
 28@@ -1035,7 +1035,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 29 			HeadColor: tcell.ColorGray,
 30 			Body:      body.StyledString(),
 31 			Mergeable: true,
 32-			Data:      []interface{}{ev},
 33+			Data:      []irc.Event{ev},
 34 		}
 35 	case irc.TopicChangeEvent:
 36 		topic := ui.IRCString(ev.Topic).String()
 37@@ -1048,13 +1048,15 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 38 		}
 39 	case irc.ModeChangeEvent:
 40 		body := fmt.Sprintf("[%s]", ev.Mode)
 41+		// simple mode event: <+/-><mode> <nick>
 42+		mergeable := len(strings.Split(ev.Mode, " ")) == 2
 43 		return ui.Line{
 44 			At:        ev.Time,
 45 			Head:      "--",
 46 			HeadColor: tcell.ColorGray,
 47 			Body:      ui.Styled(body, tcell.StyleDefault.Foreground(tcell.ColorGray)),
 48-			Mergeable: true,
 49-			Data:      []interface{}{ev},
 50+			Mergeable: mergeable,
 51+			Data:      []irc.Event{ev},
 52 		}
 53 	default:
 54 		return ui.Line{}
 55@@ -1139,86 +1141,104 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
 56 }
 57 
 58 func (app *App) mergeLine(former *ui.Line, addition ui.Line) {
 59-	partQuitUser := func(ev interface{}) string {
 60-		if ev, ok := ev.(irc.UserQuitEvent); ok {
 61-			return ev.User
 62-		}
 63-		if ev, ok := ev.(irc.UserPartEvent); ok {
 64-			return ev.User
 65-		}
 66-		panic("unreachable")
 67+	events := append(former.Data.([]irc.Event), addition.Data.([]irc.Event)...)
 68+	type flow struct {
 69+		hide  bool
 70+		state int // -1: newly offline; 1: newly online
 71 	}
 72+	flows := make(map[string]*flow)
 73+
 74+	eventFlows := make([]*flow, len(events))
 75 
 76-	changed := false
 77-Outer:
 78-	for _, addedEvent := range addition.Data {
 79-		switch addedEvent := addedEvent.(type) {
 80+	for i, ev := range events {
 81+		switch ev := ev.(type) {
 82 		case irc.UserNickEvent:
 83-			for i := len(former.Data) - 1; i >= 0; i-- {
 84-				switch ev := former.Data[i].(type) {
 85-				case irc.UserNickEvent:
 86-					if ev.User == addedEvent.FormerNick && ev.FormerNick == addedEvent.User {
 87-						former.Data = append(former.Data[:i], former.Data[i+1:]...)
 88-						changed = true
 89-						continue Outer
 90-					}
 91-				}
 92+			userCf := strings.ToLower(ev.User)
 93+			f, ok := flows[strings.ToLower(ev.FormerNick)]
 94+			if ok {
 95+				flows[userCf] = f
 96+				delete(flows, strings.ToLower(ev.FormerNick))
 97+				eventFlows[i] = f
 98+			} else {
 99+				f = &flow{}
100+				flows[userCf] = f
101+				eventFlows[i] = f
102 			}
103 		case irc.UserJoinEvent:
104-			for i := len(former.Data) - 1; i >= 0; i-- {
105-				switch ev := former.Data[i].(type) {
106-				case irc.UserPartEvent, irc.UserQuitEvent:
107-					if partQuitUser(ev) == addedEvent.User {
108-						former.Data = append(former.Data[:i], former.Data[i+1:]...)
109-						changed = true
110-						continue Outer
111-					}
112+			userCf := strings.ToLower(ev.User)
113+			f, ok := flows[userCf]
114+			if ok {
115+				if f.state == -1 {
116+					f.hide = true
117+					delete(flows, userCf)
118+				}
119+			} else {
120+				f = &flow{
121+					state: 1,
122+				}
123+				flows[userCf] = f
124+				eventFlows[i] = f
125+			}
126+		case irc.UserPartEvent:
127+			userCf := strings.ToLower(ev.User)
128+			f, ok := flows[userCf]
129+			if ok {
130+				if f.state == 1 {
131+					f.hide = true
132+					delete(flows, userCf)
133 				}
134+			} else {
135+				f = &flow{
136+					state: -1,
137+				}
138+				flows[userCf] = f
139+				eventFlows[i] = f
140 			}
141-		case irc.UserQuitEvent, irc.UserPartEvent:
142-			user := partQuitUser(addedEvent)
143-			var toRemove []int
144-			for i := len(former.Data) - 1; i >= 0; i-- {
145-				switch ev := former.Data[i].(type) {
146-				case irc.UserNickEvent:
147-					if ev.User == user {
148-						user = ev.FormerNick
149-						toRemove = append(toRemove, i)
150-					}
151-				case irc.UserJoinEvent:
152-					if ev.User == user {
153-						for _, i := range append(toRemove, i) {
154-							former.Data = append(former.Data[:i], former.Data[i+1:]...)
155-						}
156-						changed = true
157-						continue Outer
158-					}
159+		case irc.UserQuitEvent:
160+			userCf := strings.ToLower(ev.User)
161+			f, ok := flows[userCf]
162+			if ok {
163+				if f.state == 1 {
164+					f.hide = true
165+					delete(flows, userCf)
166+				}
167+			} else {
168+				f = &flow{
169+					state: -1,
170 				}
171+				flows[userCf] = f
172+				eventFlows[i] = f
173+			}
174+		case irc.ModeChangeEvent:
175+			userCf := strings.ToLower(strings.Split(ev.Mode, " ")[1])
176+			f, ok := flows[userCf]
177+			if ok {
178+				eventFlows[i] = f
179+			} else {
180+				f = &flow{}
181+				flows[userCf] = f
182+				eventFlows[i] = f
183 			}
184 		}
185-		former.Data = append(former.Data, addedEvent)
186 	}
187-	if changed {
188-		if len(former.Data) == 0 {
189-			former.Body = ui.PlainString("")
190-			return
191+
192+	newBody := new(ui.StyledStringBuilder)
193+	newBody.Grow(128)
194+	first := true
195+	for i, ev := range events {
196+		if f := eventFlows[i]; f == nil || f.hide {
197+			continue
198 		}
199-		var body ui.StyledStringBuilder
200-		body.Grow(len(former.Body.String()))
201-		body.WriteStyledString(app.formatEvent(former.Data[0]).Body)
202-		for _, ev := range former.Data[1:] {
203-			body.WriteString("  ")
204-			body.WriteStyledString(app.formatEvent(ev).Body)
205+		l := app.formatEvent(ev)
206+		if first {
207+			first = false
208+		} else {
209+			newBody.WriteString("  ")
210 		}
211-		former.Body = body.StyledString()
212-	} else {
213-		var newBody ui.StyledStringBuilder
214-		newBody.Grow(len(former.Body.String()) + 2 + len(addition.Body.String()))
215-		newBody.WriteStyledString(former.Body)
216-		newBody.WriteString("  ")
217-		newBody.WriteStyledString(addition.Body)
218-		former.Body = newBody.StyledString()
219+		newBody.WriteStyledString(l.Body)
220 	}
221+	former.Body = newBody.StyledString()
222+	former.Data = events
223 }
224 
225 // updatePrompt changes the prompt text according to the application context.
+1, -1
1@@ -33,7 +33,7 @@ type Line struct {
2 	HeadColor tcell.Color
3 	Highlight bool
4 	Mergeable bool
5-	Data      []interface{}
6+	Data      interface{}
7 
8 	splitPoints []point
9 	width       int