// Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 package eventbus import ( "encoding/json" "fmt" "log" "os" "sync" "time" ) const ( WSEvent_ElectronNewWindow = "electron:newwindow" WSEvent_ElectronCloseWindow = "electron:closewindow" WSEvent_Rpc = "rpc" ) type WSEventType struct { EventType string `json:"eventtype"` ORef string `json:"oref,omitempty"` Data any `json:"data"` } type WindowWatchData struct { WindowWSCh chan any TabId string } var globalLock = &sync.Mutex{} var wsMap = make(map[string]*WindowWatchData) // websocketid => WindowWatchData func RegisterWSChannel(connId string, tabId string, ch chan any) { globalLock.Lock() defer globalLock.Unlock() wsMap[connId] = &WindowWatchData{ WindowWSCh: ch, TabId: tabId, } } func UnregisterWSChannel(connId string) { globalLock.Lock() defer globalLock.Unlock() delete(wsMap, connId) } func getWindowWatchesForWindowId(windowId string) []*WindowWatchData { globalLock.Lock() defer globalLock.Unlock() var watches []*WindowWatchData for _, wdata := range wsMap { if wdata.TabId == windowId { watches = append(watches, wdata) } } return watches } // TODO fix busy wait -- but we need to wait until a new window connects back with a websocket // returns true if the window is connected func BusyWaitForWindowId(windowId string, timeout time.Duration) bool { endTime := time.Now().Add(timeout) for { if len(getWindowWatchesForWindowId(windowId)) > 0 { return true } if time.Now().After(endTime) { return false } time.Sleep(20 * time.Millisecond) } } func SendEventToElectron(event WSEventType) { barr, err := json.Marshal(event) if err != nil { log.Printf("cannot marshal electron message: %v\n", err) return } // send to electron log.Printf("sending event to electron: %q\n", event.EventType) fmt.Fprintf(os.Stderr, "\nWAVESRV-EVENT:%s\n", string(barr)) }