commit ca71c08
delthas
·
2025-04-20 12:06:28 +0000 UTC
parent 9baf688
Support METADATA (pin/mute) for user buffers Also, fix not monitoring users again after a reconnect in some cases. See: https://codeberg.org/emersion/soju/pulls/54
6 files changed,
+78,
-73
M
app.go
+38,
-33
1@@ -793,13 +793,8 @@ func (app *App) handleMouseEvent(ev vaxis.Mouse) {
2 members := s.Names(target)
3 if i < len(members) {
4 buffer := members[i].Name.Name
5- i, added := app.win.AddBuffer(netID, "", buffer)
6+ i, _ := app.addUserBuffer(netID, buffer, time.Time{})
7 app.win.JumpBufferIndex(i)
8- if added {
9- s.MonitorAdd(buffer)
10- s.ReadGet(buffer)
11- s.NewHistoryRequest(buffer).WithLimit(500).Latest()
12- }
13 }
14 }
15 }
16@@ -980,13 +975,8 @@ func (app *App) handleNickEvent(ev *events.EventClickNick) {
17 if s == nil {
18 return
19 }
20- i, added := app.win.AddBuffer(ev.NetID, "", ev.Nick)
21+ i, _ := app.addUserBuffer(ev.NetID, ev.Nick, time.Time{})
22 app.win.JumpBufferIndex(i)
23- if added {
24- s.MonitorAdd(ev.Nick)
25- s.ReadGet(ev.Nick)
26- s.NewHistoryRequest(ev.Nick).WithLimit(500).Latest()
27- }
28 }
29
30 func (app *App) handleChannelEvent(ev *events.EventClickChannel) {
31@@ -1391,6 +1381,8 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
32 }
33 case irc.SelfJoinEvent:
34 i, added := app.win.AddBuffer(netID, "", ev.Channel)
35+ i = app.win.SetMuted(netID, ev.Channel, s.MutedGet(ev.Channel))
36+ i = app.win.SetPinned(netID, ev.Channel, s.PinnedGet(ev.Channel))
37 if !ev.Read.IsZero() {
38 app.win.SetRead(netID, ev.Channel, ev.Read)
39 }
40@@ -1418,8 +1410,6 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
41 topic := ui.IRCString(ev.Topic).ParseURLs()
42 app.win.SetTopic(netID, ev.Channel, topic)
43 }
44- app.win.SetPinned(netID, ev.Channel, ev.Pinned)
45- app.win.SetMuted(netID, ev.Channel, ev.Muted)
46
47 // Restore last buffer
48 if netID == app.lastNetID && ev.Channel == app.lastBuffer {
49@@ -1496,20 +1486,11 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
50 break
51 }
52 if buffer != "" && !s.IsChannel(buffer) {
53- if _, added := app.win.AddBuffer(netID, "", buffer); added {
54- app.monitor[netID][buffer] = struct{}{}
55- s.MonitorAdd(buffer)
56- s.ReadGet(buffer)
57- if t, ok := msg.Time(); ok {
58- s.NewHistoryRequest(buffer).
59- WithLimit(500).
60- Before(t)
61- } else {
62- s.NewHistoryRequest(buffer).
63- WithLimit(500).
64- Latest()
65- }
66+ t, ok := msg.Time()
67+ if !ok {
68+ t = time.Time{}
69 }
70+ app.addUserBuffer(netID, buffer, t)
71 }
72 app.win.AddLine(netID, buffer, line)
73 if line.Notify == ui.NotifyHighlight {
74@@ -1545,15 +1526,10 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
75 if s.IsChannel(target.name) {
76 continue
77 }
78- s.MonitorAdd(target.name)
79- s.ReadGet(target.name)
80- app.win.AddBuffer(netID, "", target.name)
81 // CHATHISTORY BEFORE excludes its bound, so add 1ms
82 // (precision of the time tag) to include that last message.
83 target.last = target.last.Add(1 * time.Millisecond)
84- s.NewHistoryRequest(target.name).
85- WithLimit(500).
86- Before(target.last)
87+ app.addUserBuffer(netID, target.name, target.last)
88 }
89 case irc.HistoryEvent:
90 var linesBefore []ui.Line
91@@ -1620,6 +1596,9 @@ func (app *App) handleIRCEvent(netID string, ev interface{}) {
92 case irc.MetadataChangeEvent:
93 app.win.SetPinned(netID, ev.Target, ev.Pinned)
94 app.win.SetMuted(netID, ev.Target, ev.Muted)
95+ if ev.Pinned && !s.IsChannel(ev.Target) {
96+ app.addUserBuffer(netID, ev.Target, time.Time{})
97+ }
98 case irc.BouncerNetworkEvent:
99 if !ev.Delete {
100 _, added := app.win.AddBuffer(ev.ID, ev.Name, "")
101@@ -2333,6 +2312,32 @@ func (app *App) printTopic(netID, buffer string) (ok bool) {
102 return true
103 }
104
105+func (app *App) addUserBuffer(netID, buffer string, t time.Time) (i int, added bool) {
106+ i, added = app.win.AddBuffer(netID, "", buffer)
107+ if !added {
108+ return
109+ }
110+ s := app.sessions[netID]
111+ if s == nil {
112+ return
113+ }
114+ i = app.win.SetMuted(netID, buffer, s.MutedGet(buffer))
115+ i = app.win.SetPinned(netID, buffer, s.PinnedGet(buffer))
116+ app.monitor[netID][buffer] = struct{}{}
117+ s.MonitorAdd(buffer)
118+ s.ReadGet(buffer)
119+ if !t.IsZero() {
120+ s.NewHistoryRequest(buffer).
121+ WithLimit(500).
122+ Before(t)
123+ } else {
124+ s.NewHistoryRequest(buffer).
125+ WithLimit(500).
126+ Latest()
127+ }
128+ return
129+}
130+
131 func keyMatches(k vaxis.Key, r rune, mods vaxis.ModifierMask) bool {
132 m := k.Modifiers
133 m &^= vaxis.ModCapsLock
+2,
-11
1@@ -655,18 +655,13 @@ func commandDoQuery(app *App, args []string) (err error) {
2 if s.IsChannel(target) {
3 return fmt.Errorf("cannot query a channel, use JOIN instead")
4 }
5- i, added := app.win.AddBuffer(netID, "", target)
6+ i, _ := app.addUserBuffer(netID, target, time.Time{})
7 app.win.JumpBufferIndex(i)
8 if len(args) > 1 {
9 if err := commandSendMessage(app, target, args[1]); err != nil {
10 return err
11 }
12 }
13- if added {
14- s.MonitorAdd(target)
15- s.ReadGet(target)
16- s.NewHistoryRequest(target).WithLimit(200).Latest()
17- }
18 return nil
19 }
20
21@@ -1041,12 +1036,8 @@ func commandSendMessage(app *App, target string, content string) error {
22 Time: time.Now(),
23 })
24 if buffer != "" && !s.IsChannel(target) {
25- app.monitor[netID][buffer] = struct{}{}
26- s.MonitorAdd(buffer)
27- s.ReadGet(buffer)
28- app.win.AddBuffer(netID, "", buffer)
29+ app.addUserBuffer(netID, buffer, time.Time{})
30 }
31-
32 app.win.AddLine(netID, buffer, line)
33 }
34 return nil
+0,
-2
1@@ -32,8 +32,6 @@ type SelfJoinEvent struct {
2 Requested bool // whether we recently requested to join that channel
3 Topic string
4 Read time.Time
5- Pinned bool
6- Muted bool
7 }
8
9 type UserJoinEvent struct {
+26,
-19
1@@ -104,12 +104,15 @@ type Channel struct {
2 TopicWho *Prefix // the name of the last user who set the topic.
3 TopicTime time.Time // the last time the topic has been changed.
4 Read time.Time // the time until which messages were read.
5- Pinned bool
6- Muted bool
7
8 complete bool // whether this structure is fully initialized.
9 }
10
11+type Metadata struct {
12+ Pinned bool
13+ Muted bool
14+}
15+
16 // SessionParams defines how to connect to an IRC server.
17 type SessionParams struct {
18 Nickname string
19@@ -156,6 +159,7 @@ type Session struct {
20
21 users map[string]*User // known users.
22 channels map[string]Channel // joined channels.
23+ metadata map[string]Metadata // known target metadata.
24 chBatches map[string]HistoryEvent // channel history batches being processed.
25 chReqs map[string]struct{} // set of targets for which history is currently requested.
26 targetsBatchID string // ID of the channel history targets batch being processed.
27@@ -193,6 +197,7 @@ func NewSession(out chan<- Message, params SessionParams) *Session {
28 prefixModes: "ov",
29 users: map[string]*User{},
30 channels: map[string]Channel{},
31+ metadata: map[string]Metadata{},
32 chBatches: map[string]HistoryEvent{},
33 chReqs: map[string]struct{}{},
34 monitors: map[string]struct{}{},
35@@ -568,6 +573,10 @@ func (s *Session) ReadSet(target string, timestamp time.Time) {
36 }
37 }
38
39+func (s *Session) MutedGet(target string) bool {
40+ return s.metadata[s.Casemap(target)].Muted
41+}
42+
43 func (s *Session) MutedSet(target string, muted bool) (ok bool) {
44 var v string
45 if muted {
46@@ -582,6 +591,10 @@ func (s *Session) MutedSet(target string, muted bool) (ok bool) {
47 return
48 }
49
50+func (s *Session) PinnedGet(target string) bool {
51+ return s.metadata[s.Casemap(target)].Pinned
52+}
53+
54 func (s *Session) PinnedSet(target string, pinned bool) (ok bool) {
55 var v string
56 if pinned {
57@@ -1185,8 +1198,6 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
58 Channel: c.Name,
59 Topic: c.Topic,
60 Read: c.Read,
61- Pinned: c.Pinned,
62- Muted: c.Muted,
63 }
64 if stamp, ok := s.pendingChannels[channelCf]; ok && time.Since(stamp) < 5*time.Second {
65 ev.Requested = true
66@@ -1526,25 +1537,21 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
67 if err := msg.ParseParams(&target, &key, nil, &value); err != nil {
68 return nil, err
69 }
70- channelCf := s.Casemap(target)
71- c, ok := s.channels[channelCf]
72- if !ok {
73- return nil, nil
74- }
75+ targetCf := s.Casemap(target)
76+ m := s.metadata[targetCf]
77 switch key {
78 case "soju.im/pinned":
79- c.Pinned = value == "1"
80+ m.Pinned = value == "1"
81 case "soju.im/muted":
82- c.Muted = value == "1"
83- }
84- s.channels[channelCf] = c
85- if c.complete {
86- return MetadataChangeEvent{
87- Target: target,
88- Pinned: c.Pinned,
89- Muted: c.Muted,
90- }, nil
91+ m.Muted = value == "1"
92+ }
93+ s.metadata[targetCf] = m
94+ ev := MetadataChangeEvent{
95+ Target: target,
96+ Pinned: m.Pinned,
97+ Muted: m.Muted,
98 }
99+ return ev, nil
100 case "BOUNCER":
101 if len(msg.Params) < 3 {
102 break
+8,
-4
1@@ -607,13 +607,15 @@ func (bs *BufferList) GetPinned(netID, title string) bool {
2 return b.pinned
3 }
4
5-func (bs *BufferList) SetPinned(netID, title string, pinned bool) {
6+func (bs *BufferList) SetPinned(netID, title string, pinned bool) int {
7 _, b := bs.at(netID, title)
8 if b == nil {
9- return
10+ return -1
11 }
12 b.pinned = pinned
13 bs.reorder()
14+ i, _ := bs.at(netID, title)
15+ return i
16 }
17
18 func (bs *BufferList) GetMuted(netID, title string) bool {
19@@ -624,13 +626,15 @@ func (bs *BufferList) GetMuted(netID, title string) bool {
20 return b.muted
21 }
22
23-func (bs *BufferList) SetMuted(netID, title string, muted bool) {
24+func (bs *BufferList) SetMuted(netID, title string, muted bool) int {
25 _, b := bs.at(netID, title)
26 if b == nil {
27- return
28+ return -1
29 }
30 b.muted = muted
31 bs.reorder()
32+ i, _ := bs.at(netID, title)
33+ return i
34 }
35
36 func (bs *BufferList) clearRead(i int) {
M
ui/ui.go
+4,
-4
1@@ -554,16 +554,16 @@ func (ui *UI) GetPinned(netID, buffer string) bool {
2 return ui.bs.GetPinned(netID, buffer)
3 }
4
5-func (ui *UI) SetPinned(netID, buffer string, pinned bool) {
6- ui.bs.SetPinned(netID, buffer, pinned)
7+func (ui *UI) SetPinned(netID, buffer string, pinned bool) int {
8+ return ui.bs.SetPinned(netID, buffer, pinned)
9 }
10
11 func (ui *UI) GetMuted(netID, buffer string) bool {
12 return ui.bs.GetMuted(netID, buffer)
13 }
14
15-func (ui *UI) SetMuted(netID, buffer string, muted bool) {
16- ui.bs.SetMuted(netID, buffer, muted)
17+func (ui *UI) SetMuted(netID, buffer string, muted bool) int {
18+ return ui.bs.SetMuted(netID, buffer, muted)
19 }
20
21 func (ui *UI) SetRead(netID, buffer string, timestamp time.Time) {