1
0
Fork 0
mirror of https://gitlab.com/futo-org/fcast.git synced 2025-06-24 21:25:23 +00:00

Changed connection detection on window re-create

This commit is contained in:
Michael Hollister 2025-01-08 15:30:39 -06:00
parent bff3440a8e
commit 9a7924ebce
7 changed files with 32 additions and 45 deletions

View file

@ -70,6 +70,7 @@ export class TcpListenerService {
heartbeatRetries += 1; heartbeatRetries += 1;
session.send(Opcode.Ping); session.send(Opcode.Ping);
this.emitter.emit('ping', { id: connectionId });
} catch (e) { } catch (e) {
Main.logger.warn(`Error while pinging sender device ${socket.remoteAddress}:${socket.remotePort}.`, e); Main.logger.warn(`Error while pinging sender device ${socket.remoteAddress}:${socket.remotePort}.`, e);
socket.destroy(); socket.destroy();

View file

@ -68,6 +68,7 @@ export class WebSocketListenerService {
heartbeatRetries += 1; heartbeatRetries += 1;
session.send(Opcode.Ping); session.send(Opcode.Ping);
this.emitter.emit('ping', { id: connectionId });
} catch (e) { } catch (e) {
Main.logger.warn(`Error while pinging sender device ${socket.remoteAddress}:${socket.remotePort}.`, e); Main.logger.warn(`Error while pinging sender device ${socket.remoteAddress}:${socket.remotePort}.`, e);
socket.destroy(); socket.destroy();

View file

@ -18,20 +18,15 @@ if (TARGET === 'electron') {
// @ts-ignore // @ts-ignore
const electronAPI = __non_webpack_require__('electron'); const electronAPI = __non_webpack_require__('electron');
// Since event is sent async during window startup, could fire off before or after renderer.js is loaded
electronAPI.ipcRenderer.on('startup-storage-clear', () => {
localStorage.clear();
});
electronAPI.ipcRenderer.on("device-info", (_event, value: any) => { electronAPI.ipcRenderer.on("device-info", (_event, value: any) => {
preloadData.deviceInfo = value; preloadData.deviceInfo = value;
}) })
electronAPI.contextBridge.exposeInMainWorld('targetAPI', { electronAPI.contextBridge.exposeInMainWorld('targetAPI', {
onStartupStorageClear: (callback: any) => electronAPI.ipcRenderer.on('startup-storage-clear', callback),
onDeviceInfo: (callback: any) => electronAPI.ipcRenderer.on("device-info", callback), onDeviceInfo: (callback: any) => electronAPI.ipcRenderer.on("device-info", callback),
onConnect: (callback: any) => electronAPI.ipcRenderer.on("connect", callback), onConnect: (callback: any) => electronAPI.ipcRenderer.on("connect", callback),
onDisconnect: (callback: any) => electronAPI.ipcRenderer.on("disconnect", callback), onDisconnect: (callback: any) => electronAPI.ipcRenderer.on("disconnect", callback),
onPing: (callback: any) => electronAPI.ipcRenderer.on("ping", callback),
getDeviceInfo: () => preloadData.deviceInfo, getDeviceInfo: () => preloadData.deviceInfo,
}); });
@ -39,17 +34,17 @@ if (TARGET === 'electron') {
} else if (TARGET === 'webOS') { } else if (TARGET === 'webOS') {
try { try {
preloadData = { preloadData = {
onStartupStorageClearCb: () => { localStorage.clear(); },
onDeviceInfoCb: () => { console.log('Main: Callback not set while fetching device info'); }, onDeviceInfoCb: () => { console.log('Main: Callback not set while fetching device info'); },
onConnectCb: (_, value: any) => { console.log('Main: Callback not set while calling onConnect'); }, onConnectCb: (_, value: any) => { console.log('Main: Callback not set while calling onConnect'); },
onDisconnectCb: (_, value: any) => { console.log('Main: Callback not set while calling onDisconnect'); }, onDisconnectCb: (_, value: any) => { console.log('Main: Callback not set while calling onDisconnect'); },
onPingCb: (_, value: any) => { console.log('Main: Callback not set while calling onPing'); },
}; };
window.targetAPI = { window.targetAPI = {
onStartupStorageClear: (callback: () => void) => preloadData.onStartupStorageClearCb = callback,
onDeviceInfo: (callback: () => void) => preloadData.onDeviceInfoCb = callback, onDeviceInfo: (callback: () => void) => preloadData.onDeviceInfoCb = callback,
onConnect: (callback: (_, value: any) => void) => preloadData.onConnectCb = callback, onConnect: (callback: (_, value: any) => void) => preloadData.onConnectCb = callback,
onDisconnect: (callback: (_, value: any) => void) => preloadData.onDisconnectCb = callback, onDisconnect: (callback: (_, value: any) => void) => preloadData.onDisconnectCb = callback,
onPing: (callback: (_, value: any) => void) => preloadData.onPingCb = callback,
getDeviceInfo: () => preloadData.deviceInfo, getDeviceInfo: () => preloadData.deviceInfo,
}; };
} }

View file

@ -6,22 +6,19 @@ import { toast, ToastIcon } from '../components/Toast';
const connectionStatusText = document.getElementById("connection-status-text"); const connectionStatusText = document.getElementById("connection-status-text");
const connectionStatusSpinner = document.getElementById("connection-spinner"); const connectionStatusSpinner = document.getElementById("connection-spinner");
const connectionStatusCheck = document.getElementById("connection-check"); const connectionStatusCheck = document.getElementById("connection-check");
let connections = JSON.parse(localStorage.getItem('connections')) ?? []; let connections = [];
if (connections.length > 0) {
connections.forEach(connection => {
onConnect(connection);
});
}
window.targetAPI.onStartupStorageClear((_event, value: any) => { // Window might be re-created while devices are still connected
localStorage.clear(); window.targetAPI.onPing((_event, value: any) => {
localStorage.setItem('connections', JSON.stringify(connections)); if (connections.length === 0) {
connections.push(value.id);
onConnect(value.id);
}
}); });
window.targetAPI.onDeviceInfo(renderIPsAndQRCode); window.targetAPI.onDeviceInfo(renderIPsAndQRCode);
window.targetAPI.onConnect((_event, value: any) => { window.targetAPI.onConnect((_event, value: any) => {
connections.push(value.id); connections.push(value.id);
localStorage.setItem('connections', JSON.stringify(connections));
onConnect(value); onConnect(value);
}); });
window.targetAPI.onDisconnect((_event, value: any) => { window.targetAPI.onDisconnect((_event, value: any) => {
@ -29,7 +26,6 @@ window.targetAPI.onDisconnect((_event, value: any) => {
const index = connections.indexOf(value.id); const index = connections.indexOf(value.id);
if (index != -1) { if (index != -1) {
connections.splice(index, 1); connections.splice(index, 1);
localStorage.setItem('connections', JSON.stringify(connections));
} }
if (connections.length === 0) { if (connections.length === 0) {

View file

@ -25,7 +25,6 @@ export class Main {
static discoveryService: DiscoveryService; static discoveryService: DiscoveryService;
static tray: Tray; static tray: Tray;
static logger: log4js.Logger; static logger: log4js.Logger;
private static startupStorageClear = true;
private static toggleMainWindow() { private static toggleMainWindow() {
if (Main.mainWindow) { if (Main.mainWindow) {
@ -194,6 +193,7 @@ export class Main {
l.emitter.on('connect', (message) => Main.mainWindow?.webContents?.send('connect', message)); l.emitter.on('connect', (message) => Main.mainWindow?.webContents?.send('connect', message));
l.emitter.on('disconnect', (message) => Main.mainWindow?.webContents?.send('disconnect', message)); l.emitter.on('disconnect', (message) => Main.mainWindow?.webContents?.send('disconnect', message));
l.emitter.on('ping', (message) => Main.mainWindow?.webContents?.send('ping', message));
l.start(); l.start();
ipcMain.on('send-playback-error', (event: IpcMainEvent, value: PlaybackErrorMessage) => { ipcMain.on('send-playback-error', (event: IpcMainEvent, value: PlaybackErrorMessage) => {
@ -298,11 +298,6 @@ export class Main {
} }
}); });
if (Main.startupStorageClear) {
Main.mainWindow.webContents.send('startup-storage-clear');
Main.startupStorageClear = false;
}
Main.mainWindow.loadFile(path.join(__dirname, 'main/index.html')); Main.mainWindow.loadFile(path.join(__dirname, 'main/index.html'));
Main.mainWindow.on('closed', () => { Main.mainWindow.on('closed', () => {
Main.mainWindow = null; Main.mainWindow = null;

View file

@ -49,21 +49,6 @@ export class Main {
const voidCb = (message: any) => { message.respond({ returnValue: true, value: {} }); }; const voidCb = (message: any) => { message.respond({ returnValue: true, value: {} }); };
const objectCb = (message: any, value: any) => { message.respond({ returnValue: true, value: value }); }; const objectCb = (message: any, value: any) => { message.respond({ returnValue: true, value: value }); };
let startupStorageClearClosureCb = null;
service.register("startup-storage-clear", (message: any) => {
if (message.isSubscription) {
startupStorageClearClosureCb = voidCb.bind(this, message);
Main.emitter.on('startup-storage-clear', startupStorageClearClosureCb);
}
message.respond({ returnValue: true, value: { subscribed: true }});
},
(message: any) => {
Main.logger.info('Canceled startup-storage-clear service subscriber');
Main.emitter.off('startup-storage-clear', startupStorageClearClosureCb);
message.respond({ returnValue: true, value: message.payload });
});
let toastClosureCb = null; let toastClosureCb = null;
service.register("toast", (message: any) => { service.register("toast", (message: any) => {
if (message.isSubscription) { if (message.isSubscription) {
@ -118,6 +103,21 @@ export class Main {
message.respond({ returnValue: true, value: message.payload }); message.respond({ returnValue: true, value: message.payload });
}); });
let pingClosureCb = null;
service.register("ping", (message: any) => {
if (message.isSubscription) {
pingClosureCb = objectCb.bind(this, message);
Main.emitter.on('ping', pingClosureCb);
}
message.respond({ returnValue: true, value: { subscribed: true }});
},
(message: any) => {
Main.logger.info('Canceled ping service subscriber');
Main.emitter.off('ping', pingClosureCb);
message.respond({ returnValue: true, value: message.payload });
});
Main.discoveryService = new DiscoveryService(); Main.discoveryService = new DiscoveryService();
Main.discoveryService.start(); Main.discoveryService.start();
@ -272,6 +272,7 @@ export class Main {
l.emitter.on('connect', (message) => Main.emitter.emit('connect', message)); l.emitter.on('connect', (message) => Main.emitter.emit('connect', message));
l.emitter.on('disconnect', (message) => Main.emitter.emit('disconnect', message)); l.emitter.on('disconnect', (message) => Main.emitter.emit('disconnect', message));
l.emitter.on('ping', (message) => Main.emitter.emit('ping', message));
l.start(); l.start();
}); });
@ -303,8 +304,6 @@ export class Main {
message.respond({ returnValue: true, value: { success: true } }); message.respond({ returnValue: true, value: { success: true } });
}); });
this.emitter.emit('startup-storage-clear');
} }
catch (err) { catch (err) {
Main.logger.error("Error initializing service:", err); Main.logger.error("Error initializing service:", err);

View file

@ -15,7 +15,6 @@ enum RemoteKeyCode {
} }
try { try {
const startupStorageClearService = registerService('startup-storage-clear', () => { preloadData.onStartupStorageClearCb(); });
const toastService = registerService('toast', (message: any) => { toast(message.value.message, message.value.icon, message.value.duration); }); const toastService = registerService('toast', (message: any) => { toast(message.value.message, message.value.icon, message.value.duration); });
const getDeviceInfoService = registerService('getDeviceInfo', (message: any) => { const getDeviceInfoService = registerService('getDeviceInfo', (message: any) => {
console.log(`Main: getDeviceInfo ${JSON.stringify(message)}`); console.log(`Main: getDeviceInfo ${JSON.stringify(message)}`);
@ -24,14 +23,15 @@ try {
}, false); }, false);
const onConnectService = registerService('connect', (message: any) => { preloadData.onConnectCb(null, message.value); }); const onConnectService = registerService('connect', (message: any) => { preloadData.onConnectCb(null, message.value); });
const onDisconnectService = registerService('disconnect', (message: any) => { preloadData.onDisconnectCb(null, message.value); }); const onDisconnectService = registerService('disconnect', (message: any) => { preloadData.onDisconnectCb(null, message.value); });
const onPingService = registerService('ping', (message: any) => { preloadData.onPingCb(null, message.value); });
const playService = registerService('play', (message: any) => { const playService = registerService('play', (message: any) => {
if (message.value !== undefined && message.value.playData !== undefined) { if (message.value !== undefined && message.value.playData !== undefined) {
console.log(`Main: Playing ${JSON.stringify(message)}`); console.log(`Main: Playing ${JSON.stringify(message)}`);
getDeviceInfoService.cancel(); getDeviceInfoService.cancel();
startupStorageClearService.cancel();
toastService.cancel(); toastService.cancel();
onConnectService.cancel(); onConnectService.cancel();
onDisconnectService.cancel(); onDisconnectService.cancel();
onPingService.cancel();
playService.cancel(); playService.cancel();
// WebOS 22 and earlier does not work well using the history API, // WebOS 22 and earlier does not work well using the history API,
@ -49,11 +49,11 @@ try {
const lastTimestamp = localStorage.getItem('lastTimestamp'); const lastTimestamp = localStorage.getItem('lastTimestamp');
if (params.playData !== undefined && params.timestamp != lastTimestamp) { if (params.playData !== undefined && params.timestamp != lastTimestamp) {
localStorage.setItem('lastTimestamp', params.timestamp); localStorage.setItem('lastTimestamp', params.timestamp);
startupStorageClearService?.cancel();
toastService?.cancel(); toastService?.cancel();
getDeviceInfoService?.cancel(); getDeviceInfoService?.cancel();
onConnectService?.cancel(); onConnectService?.cancel();
onDisconnectService?.cancel(); onDisconnectService?.cancel();
onPingService?.cancel();
playService?.cancel(); playService?.cancel();
// WebOS 22 and earlier does not work well using the history API, // WebOS 22 and earlier does not work well using the history API,