add sessions cursors.

This commit is contained in:
Miroslav Šedivý 2021-10-24 01:09:41 +02:00
parent 318b833b30
commit 0b5e064cab
7 changed files with 97 additions and 29 deletions

View File

@ -15,14 +15,12 @@ import (
func New(config *config.Session) *SessionManagerCtx { func New(config *config.Session) *SessionManagerCtx {
manager := &SessionManagerCtx{ manager := &SessionManagerCtx{
logger: log.With().Str("module", "session").Logger(), logger: log.With().Str("module", "session").Logger(),
config: config, config: config,
host: nil, tokens: make(map[string]string),
hostMu: sync.Mutex{}, sessions: make(map[string]*SessionCtx),
tokens: make(map[string]string), cursors: make(map[types.Session]types.Cursor),
sessions: make(map[string]*SessionCtx), emmiter: events.New(),
sessionsMu: sync.Mutex{},
emmiter: events.New(),
} }
// create API session // create API session
@ -48,13 +46,19 @@ func New(config *config.Session) *SessionManagerCtx {
} }
type SessionManagerCtx struct { type SessionManagerCtx struct {
logger zerolog.Logger logger zerolog.Logger
config *config.Session config *config.Session
host types.Session
hostMu sync.Mutex
tokens map[string]string tokens map[string]string
sessions map[string]*SessionCtx sessions map[string]*SessionCtx
sessionsMu sync.Mutex sessionsMu sync.Mutex
host types.Session
hostMu sync.Mutex
cursors map[types.Session]types.Cursor
cursorsMu sync.Mutex
emmiter events.EventEmmiter emmiter events.EventEmmiter
apiSession *SessionCtx apiSession *SessionCtx
} }
@ -193,6 +197,32 @@ func (manager *SessionManagerCtx) ClearHost() {
manager.SetHost(nil) manager.SetHost(nil)
} }
// ---
// cursors
// ---
func (manager *SessionManagerCtx) SetCursor(x, y int, session types.Session) {
manager.cursorsMu.Lock()
defer manager.cursorsMu.Unlock()
pos, ok := manager.cursors[session]
if ok {
pos.X, pos.Y = x, y
} else {
manager.cursors[session] = types.Cursor{X: x, Y: y}
}
}
func (manager *SessionManagerCtx) PopCursors() map[types.Session]types.Cursor {
manager.cursorsMu.Lock()
defer manager.cursorsMu.Unlock()
cursors := manager.cursors
manager.cursors = make(map[types.Session]types.Cursor)
return cursors
}
// --- // ---
// broadcasts // broadcasts
// --- // ---

View File

@ -16,10 +16,6 @@ type SessionCtx struct {
profile types.MemberProfile profile types.MemberProfile
state types.SessionState state types.SessionState
positionX int
positionY int
positionMu sync.Mutex
websocketPeer types.WebSocketPeer websocketPeer types.WebSocketPeer
websocketMu sync.Mutex websocketMu sync.Mutex
@ -57,16 +53,8 @@ func (session *SessionCtx) IsHost() bool {
return session.manager.GetHost() == session return session.manager.GetHost() == session
} }
// --- func (session *SessionCtx) SetCursor(x, y int) {
// cursor position session.manager.SetCursor(x, y, session)
// ---
func (session *SessionCtx) SetPosition(x, y int) {
session.positionMu.Lock()
defer session.positionMu.Unlock()
session.positionX = x
session.positionY = y
} }
// --- // ---

View File

@ -21,6 +21,7 @@ const (
SESSION_DELETED = "session/deleted" SESSION_DELETED = "session/deleted"
SESSION_PROFILE = "session/profile" SESSION_PROFILE = "session/profile"
SESSION_STATE = "session/state" SESSION_STATE = "session/state"
SESSION_CURSORS = "session/cursors"
) )
const ( const (

View File

@ -87,6 +87,12 @@ type SessionData struct {
State types.SessionState `json:"state"` State types.SessionState `json:"state"`
} }
type SessionCursor struct {
ID string `json:"id"`
X uint16 `json:"x"`
Y uint16 `json:"y"`
}
///////////////////////////// /////////////////////////////
// Control // Control
///////////////////////////// /////////////////////////////

View File

@ -12,6 +12,11 @@ var (
ErrSessionLoginDisabled = errors.New("session login disabled") ErrSessionLoginDisabled = errors.New("session login disabled")
) )
type Cursor struct {
X int
Y int
}
type SessionState struct { type SessionState struct {
IsConnected bool `json:"is_connected"` IsConnected bool `json:"is_connected"`
IsWatching bool `json:"is_watching"` IsWatching bool `json:"is_watching"`
@ -23,8 +28,8 @@ type Session interface {
State() SessionState State() SessionState
IsHost() bool IsHost() bool
// cursor position // cursor
SetPosition(x, y int) SetCursor(x, y int)
// websocket // websocket
SetWebSocketPeer(websocketPeer WebSocketPeer) SetWebSocketPeer(websocketPeer WebSocketPeer)
@ -50,6 +55,9 @@ type SessionManager interface {
GetHost() Session GetHost() Session
ClearHost() ClearHost()
SetCursor(x, y int, session Session)
PopCursors() map[Session]Cursor
Broadcast(event string, payload interface{}, exclude interface{}) Broadcast(event string, payload interface{}, exclude interface{})
AdminBroadcast(event string, payload interface{}, exclude interface{}) AdminBroadcast(event string, payload interface{}, exclude interface{})

View File

@ -52,7 +52,7 @@ func (manager *WebRTCManagerCtx) handle(data []byte, session types.Session) erro
// handle inactive cursor movement // handle inactive cursor movement
if session.Profile().CanHost { if session.Profile().CanHost {
session.SetPosition(x, y) session.SetCursor(x, y)
} }
return nil return nil

View File

@ -132,6 +132,41 @@ func (manager *WebSocketManagerCtx) Start() {
manager.fileChooserDialogEvents() manager.fileChooserDialogEvents()
manager.wg.Add(1)
go func() {
defer manager.wg.Done()
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-manager.shutdown:
return
case <-ticker.C:
cursorsMap := manager.sessions.PopCursors()
if len(cursorsMap) == 0 {
continue
}
cursors := []message.SessionCursor{}
for session, cursor := range cursorsMap {
cursors = append(
cursors,
message.SessionCursor{
ID: session.ID(),
X: uint16(cursor.X),
Y: uint16(cursor.Y),
},
)
}
// TODO: Send to subscribers only.
manager.sessions.AdminBroadcast(event.SESSION_CURSORS, cursors, nil)
}
}
}()
manager.logger.Info().Msg("websocket starting") manager.logger.Info().Msg("websocket starting")
} }