Skip to content

Commit affe468

Browse files
committed
Added: multidevices support
1 parent 6a67482 commit affe468

7 files changed

Lines changed: 741 additions & 52 deletions

File tree

internal/app/app.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ func (a *App) enableWebClientOverride() error {
288288
return nil
289289
}
290290

291-
// Get current backend name
292-
currentBackend := a.lifecycle.GetCurrentBackend()
293-
if currentBackend == "webclient" {
294-
log.Println("WebClient override: already using webclient backend")
291+
// Check if all devices already use webclient — no override needed
292+
if a.lifecycle.AllDevicesUseBackend("webclient") {
293+
log.Println("WebClient override: all devices already using webclient backend")
295294
return nil
296295
}
297296

297+
currentBackend := a.lifecycle.GetCurrentBackend()
298298
log.Println("========================================")
299299
log.Printf("Enabling webclient override (current backend: %s)", currentBackend)
300300

@@ -451,6 +451,13 @@ func (a *App) ReloadConfig() error {
451451
log.Println("New config validated successfully")
452452
log.Printf("Loaded config: %s (%s) with %d widgets", newCfg.GameName, newCfg.GameDisplayName, len(newCfg.Widgets))
453453

454+
// Reset webclient override state — the reloaded config defines its own backends
455+
if a.webclientOverrideActive {
456+
log.Println("Resetting webclient override state for config reload")
457+
a.webclientOverrideActive = false
458+
a.webclientOverrideOriginal = ""
459+
}
460+
454461
log.Println("Stopping current instance...")
455462
a.lifecycle.Stop()
456463

@@ -503,6 +510,13 @@ func (a *App) SwitchProfile(path string) error {
503510
profileName = "Unknown"
504511
}
505512

513+
// Reset webclient override state — the new profile defines its own backends
514+
if a.webclientOverrideActive {
515+
log.Println("Resetting webclient override state for profile switch")
516+
a.webclientOverrideActive = false
517+
a.webclientOverrideOriginal = ""
518+
}
519+
506520
// Stop compositor first to free the display
507521
log.Println("Stopping current instance...")
508522
a.lifecycle.Stop()

internal/app/lifecycle.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,23 @@ func (m *LifecycleManager) GetCurrentBackend() string {
269269
return ""
270270
}
271271

272+
// AllDevicesUseBackend returns true if every device is using the given backend name.
273+
// Returns false if there are no devices.
274+
func (m *LifecycleManager) AllDevicesUseBackend(name string) bool {
275+
m.mu.Lock()
276+
defer m.mu.Unlock()
277+
278+
if len(m.devices) == 0 {
279+
return false
280+
}
281+
for _, dev := range m.devices {
282+
if dev.GetCurrentBackend() != name {
283+
return false
284+
}
285+
}
286+
return true
287+
}
288+
272289
// ShowWebClientModeMessage displays "WEB CLIENT" on all devices
273290
func (m *LifecycleManager) ShowWebClientModeMessage() {
274291
m.mu.Lock()

internal/webeditor/embed/js/api.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,23 +160,44 @@ const API = {
160160

161161
/**
162162
* Get preview availability and configuration
163+
* @param {string} [deviceId] - Optional device ID for multi-device preview
163164
* @returns {Promise<Object>} Preview info with available, width, height, target_fps
164165
*/
165-
async getPreviewInfo() {
166-
const response = await fetch('/api/preview');
166+
async getPreviewInfo(deviceId) {
167+
const url = deviceId
168+
? `/api/preview?device=${encodeURIComponent(deviceId)}`
169+
: '/api/preview';
170+
const response = await fetch(url);
167171
if (!response.ok) {
168172
throw new Error(`Failed to get preview info: ${response.statusText}`);
169173
}
170174
return response.json();
171175
},
172176

177+
/**
178+
* Get list of preview devices
179+
* @returns {Promise<Object>} Device list with devices array
180+
*/
181+
async getPreviewDevices() {
182+
const response = await fetch('/api/preview/devices');
183+
if (!response.ok) {
184+
throw new Error(`Failed to get preview devices: ${response.statusText}`);
185+
}
186+
return response.json();
187+
},
188+
173189
/**
174190
* Create a WebSocket connection for live preview
191+
* @param {string} [deviceId] - Optional device ID for multi-device preview
175192
* @returns {WebSocket} WebSocket connection
176193
*/
177-
createPreviewWebSocket() {
194+
createPreviewWebSocket(deviceId) {
178195
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
179-
return new WebSocket(`${protocol}//${window.location.host}/api/preview/ws`);
196+
let url = `${protocol}//${window.location.host}/api/preview/ws`;
197+
if (deviceId) {
198+
url += `?device=${encodeURIComponent(deviceId)}`;
199+
}
200+
return new WebSocket(url);
180201
},
181202

182203
/**

0 commit comments

Comments
 (0)