feat(tray): desktop tray icon companion with Theta logo, color-coded status, and home LAN detection (#10)

- tray_icons.go / cmd/theta-agent-tray: Renders iconic Theta 42 logo in status colors:
    - 🔴 Red: Not connected to directory
    - 🟡 Yellow: Connected to directory, but not on home LAN
    - 🟢 Green: Connected to directory on home LAN
    - 🔵 Blue: Connected to directory with active WireGuard tunnel
- home_detect.go: Compares agent public IP with home site public IP
- tray_server.go / tray_ipc.go: Unix socket IPC daemon server (/run/theta/tray.sock or /tmp/theta-tray.sock)
- cmd/theta-agent-tray: Desktop GUI binary with system tray menu (Auto-connect toggle, Connect/Disconnect VPN)
- Auto-detects DISPLAY / WAYLAND_DISPLAY environment variables
This commit is contained in:
2026-08-08 23:16:20 -04:00
committed by GitHub
parent 34f6f685fc
commit c676c658ed
20 changed files with 470 additions and 5 deletions
+11
View File
@@ -6,9 +6,14 @@ import (
"os"
"os/signal"
"strings"
"sync/atomic"
"syscall"
)
// wsConnected is flipped atomically by connectWebSocket as the connection
// comes up and drops, so StartHomeMonitor can read it without a mutex.
var wsConnected atomic.Bool
func main() {
if len(os.Args) > 1 && handleCLI(os.Args[1:]) {
return
@@ -39,9 +44,15 @@ func main() {
// Initialize system executor
exec := &SystemExecutor{}
// Tray IPC server — desktop tray connects here for status updates.
go globalTrayServer.Start()
// WebSocket connection to SSO Manager
go connectWebSocket(cm, exec)
// Home detection + tray status push (polls public IP every 60s).
go StartHomeMonitor(cfg, func() bool { return wsConnected.Load() })
// Block until signal is received
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)