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}