awareness.go
1package ygo
2
3import "encoding/json"
4
5// UserInfo represents the user information in awareness state.
6// This is the standard Yjs awareness "user" field structure.
7type UserInfo struct {
8 Name string `json:"name"`
9 Color string `json:"color"`
10}
11
12// AwarenessState represents the local client's awareness state.
13// It provides type-safe methods for setting common fields.
14type AwarenessState struct {
15 user UserInfo
16 cursor map[string]any
17 custom map[string]any
18}
19
20// NewAwarenessState creates a new awareness state.
21func NewAwarenessState() *AwarenessState {
22 return &AwarenessState{}
23}
24
25// SetUserInfo sets the user information (name and color).
26func (s *AwarenessState) SetUserInfo(name, color string) *AwarenessState {
27 s.user = UserInfo{Name: name, Color: color}
28 return s
29}
30
31// SetCursor sets cursor position for editor bindings.
32func (s *AwarenessState) SetCursor(anchor, head uint32, more map[string]any) *AwarenessState {
33 s.cursor = map[string]any{
34 "anchor": anchor,
35 "head": head,
36 }
37 for k, v := range more {
38 s.cursor[k] = v
39 }
40 return s
41}
42
43// SetCustom sets a custom awareness field.
44func (s *AwarenessState) SetCustom(key string, value any) *AwarenessState {
45 if s.custom == nil {
46 s.custom = make(map[string]any)
47 }
48 s.custom[key] = value
49 return s
50}
51
52// UserInfo returns the user information.
53func (s *AwarenessState) UserInfo() (UserInfo, bool) {
54 if s.user.Name == "" {
55 return UserInfo{}, false
56 }
57 return s.user, true
58}
59
60// MarshalJSON implements json.Marshaler for the awareness protocol wire format.
61func (s *AwarenessState) MarshalJSON() ([]byte, error) {
62 m := make(map[string]any)
63
64 if s.user.Name != "" {
65 m["user"] = s.user
66 }
67 if s.cursor != nil {
68 m["cursor"] = s.cursor
69 }
70 for k, v := range s.custom {
71 m[k] = v
72 }
73
74 return json.Marshal(m)
75}