tangled
alpha
login
or
join now
diffdown.com
/
diffdown-app
0
fork
atom
Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol
diffdown.com
0
fork
atom
overview
issues
10
pulls
pipelines
feat: add collaboration hub with room management
John Luther
3 weeks ago
cd3a87ca
d2324d9b
+97
2 changed files
expand all
collapse all
unified
split
internal
collaboration
client.go
hub.go
+15
internal/collaboration/client.go
reviewed
···
1
1
+
package collaboration
2
2
+
3
3
+
import (
4
4
+
"github.com/gorilla/websocket"
5
5
+
)
6
6
+
7
7
+
type Client struct {
8
8
+
hub *Hub
9
9
+
conn *websocket.Conn
10
10
+
send chan []byte
11
11
+
DID string
12
12
+
Name string
13
13
+
Color string
14
14
+
roomKey string
15
15
+
}
+82
internal/collaboration/hub.go
reviewed
···
1
1
+
package collaboration
2
2
+
3
3
+
import (
4
4
+
"sync"
5
5
+
)
6
6
+
7
7
+
type Hub struct {
8
8
+
rooms map[string]*Room
9
9
+
mu sync.RWMutex
10
10
+
}
11
11
+
12
12
+
type Room struct {
13
13
+
documentRKey string
14
14
+
clients map[*Client]bool
15
15
+
broadcast chan []byte
16
16
+
register chan *Client
17
17
+
unregister chan *Client
18
18
+
mu sync.RWMutex
19
19
+
}
20
20
+
21
21
+
func NewHub() *Hub {
22
22
+
return &Hub{
23
23
+
rooms: make(map[string]*Room),
24
24
+
}
25
25
+
}
26
26
+
27
27
+
func (h *Hub) GetOrCreateRoom(rkey string) *Room {
28
28
+
h.mu.Lock()
29
29
+
defer h.mu.Unlock()
30
30
+
if room, exists := h.rooms[rkey]; exists {
31
31
+
return room
32
32
+
}
33
33
+
room := &Room{
34
34
+
documentRKey: rkey,
35
35
+
clients: make(map[*Client]bool),
36
36
+
broadcast: make(chan []byte, 256),
37
37
+
register: make(chan *Client),
38
38
+
unregister: make(chan *Client),
39
39
+
}
40
40
+
h.rooms[rkey] = room
41
41
+
go room.run()
42
42
+
return room
43
43
+
}
44
44
+
45
45
+
func (r *Room) run() {
46
46
+
for {
47
47
+
select {
48
48
+
case client := <-r.register:
49
49
+
r.mu.Lock()
50
50
+
r.clients[client] = true
51
51
+
r.mu.Unlock()
52
52
+
r.broadcastPresence()
53
53
+
case client := <-r.unregister:
54
54
+
r.mu.Lock()
55
55
+
if _, ok := r.clients[client]; ok {
56
56
+
delete(r.clients, client)
57
57
+
close(client.send)
58
58
+
}
59
59
+
r.mu.Unlock()
60
60
+
r.broadcastPresence()
61
61
+
case message := <-r.broadcast:
62
62
+
r.mu.RLock()
63
63
+
for client := range r.clients {
64
64
+
select {
65
65
+
case client.send <- message:
66
66
+
default:
67
67
+
close(client.send)
68
68
+
delete(r.clients, client)
69
69
+
}
70
70
+
}
71
71
+
r.mu.RUnlock()
72
72
+
}
73
73
+
}
74
74
+
}
75
75
+
76
76
+
func (r *Room) Broadcast(message []byte) {
77
77
+
r.broadcast <- message
78
78
+
}
79
79
+
80
80
+
func (r *Room) broadcastPresence() {
81
81
+
// Implementation in Task 2.2
82
82
+
}