Enable screensharing in desktop app (#2042)
* enable screensharing in desktop app * add source picker * update dependencies * improve source picker * improve source picker * update thumbnails * decrease thumbnail size * revert unnecessary changes in screen sharing store * fix types and eslint * fix prettier * remove unused import
This commit is contained in:
@@ -31,13 +31,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/auto-launch": "^5.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
||||
"@typescript-eslint/parser": "^2.26.0",
|
||||
"electron": "^17.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.18.0",
|
||||
"@typescript-eslint/parser": "^5.18.0",
|
||||
"electron": "^18.0.3",
|
||||
"electron-builder": "^22.14.13",
|
||||
"eslint": "^6.8.0",
|
||||
"prettier": "^2.5.1",
|
||||
"tsup": "^5.11.13",
|
||||
"typescript": "^3.8.3"
|
||||
"eslint": "^8.12.0",
|
||||
"prettier": "^2.6.2",
|
||||
"tsup": "^5.12.4",
|
||||
"typescript": "^4.6.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { setLogLevel } from "./log";
|
||||
import "./serve"; // prepare custom url scheme
|
||||
import { loadShortcuts } from "./shortcuts";
|
||||
|
||||
function init() {
|
||||
async function init() {
|
||||
const appLock = app.requestSingleInstanceLock();
|
||||
|
||||
if (!appLock) {
|
||||
@@ -21,7 +21,7 @@ function init() {
|
||||
|
||||
app.on("second-instance", () => {
|
||||
// re-create window if closed
|
||||
createWindow();
|
||||
void createWindow();
|
||||
|
||||
const mainWindow = getWindow();
|
||||
|
||||
@@ -36,15 +36,15 @@ function init() {
|
||||
});
|
||||
|
||||
// This method will be called when Electron has finished loading
|
||||
app.whenReady().then(async () => {
|
||||
await app.whenReady().then(async () => {
|
||||
await settings.init();
|
||||
|
||||
setLogLevel(settings.get("log_level") || "info");
|
||||
|
||||
autoUpdater.init();
|
||||
await autoUpdater.init();
|
||||
|
||||
// enable auto launch
|
||||
updateAutoLaunch();
|
||||
await updateAutoLaunch();
|
||||
|
||||
// load ipc handler
|
||||
ipc();
|
||||
@@ -72,7 +72,7 @@ function init() {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
void createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -38,32 +38,35 @@ export async function manualRequestUpdateCheck() {
|
||||
isManualRequestedUpdate = false;
|
||||
}
|
||||
|
||||
function init() {
|
||||
async function init() {
|
||||
autoUpdater.logger = log;
|
||||
|
||||
autoUpdater.on("update-downloaded", ({ releaseNotes, releaseName }) => {
|
||||
(async () => {
|
||||
const dialogOpts = {
|
||||
type: "question",
|
||||
buttons: ["Install and Restart", "Install Later"],
|
||||
defaultId: 0,
|
||||
title: "WorkAdventure - Update",
|
||||
message: process.platform === "win32" ? releaseNotes : releaseName,
|
||||
detail: "A new version has been downloaded. Restart the application to apply the updates.",
|
||||
};
|
||||
autoUpdater.on(
|
||||
"update-downloaded",
|
||||
({ releaseNotes, releaseName }: { releaseNotes: string; releaseName: string }) => {
|
||||
void (async () => {
|
||||
const dialogOpts = {
|
||||
type: "question",
|
||||
buttons: ["Install and Restart", "Install Later"],
|
||||
defaultId: 0,
|
||||
title: "WorkAdventure - Update",
|
||||
message: process.platform === "win32" ? releaseNotes : releaseName,
|
||||
detail: "A new version has been downloaded. Restart the application to apply the updates.",
|
||||
};
|
||||
|
||||
const { response } = await dialog.showMessageBox(dialogOpts);
|
||||
if (response === 0) {
|
||||
await sleep(1000);
|
||||
const { response } = await dialog.showMessageBox(dialogOpts);
|
||||
if (response === 0) {
|
||||
await sleep(1000);
|
||||
|
||||
autoUpdater.quitAndInstall();
|
||||
autoUpdater.quitAndInstall();
|
||||
|
||||
// Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app.
|
||||
// app.confirmedExitPrompt = true;
|
||||
app.quit();
|
||||
}
|
||||
})();
|
||||
});
|
||||
// Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app.
|
||||
// app.confirmedExitPrompt = true;
|
||||
app.quit();
|
||||
}
|
||||
})();
|
||||
}
|
||||
);
|
||||
|
||||
if (process.platform === "linux" && !process.env.APPIMAGE) {
|
||||
autoUpdater.autoDownload = false;
|
||||
@@ -85,7 +88,7 @@ function init() {
|
||||
}
|
||||
});
|
||||
|
||||
checkForUpdates();
|
||||
await checkForUpdates();
|
||||
|
||||
// run update check every hour again
|
||||
setInterval(() => checkForUpdates, 1000 * 60 * 1);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ipcMain, app } from "electron";
|
||||
import { ipcMain, app, desktopCapturer } from "electron";
|
||||
import electronIsDev from "electron-is-dev";
|
||||
import { createAndShowNotification } from "./notification";
|
||||
import { Server } from "./preload-local-app/types";
|
||||
@@ -30,10 +30,18 @@ export default () => {
|
||||
ipcMain.handle("get-version", () => (electronIsDev ? "dev" : app.getVersion()));
|
||||
|
||||
// app ipc
|
||||
ipcMain.on("app:notify", (event, txt) => {
|
||||
ipcMain.on("app:notify", (event, txt: string) => {
|
||||
createAndShowNotification({ body: txt });
|
||||
});
|
||||
|
||||
ipcMain.handle("app:getDesktopCapturerSources", async (event, options: Electron.SourcesOptions) => {
|
||||
return (await desktopCapturer.getSources(options)).map((source) => ({
|
||||
id: source.id,
|
||||
name: source.name,
|
||||
thumbnailURL: source.thumbnail.toDataURL(),
|
||||
}));
|
||||
});
|
||||
|
||||
// local-app ipc
|
||||
ipcMain.handle("local-app:showLocalApp", () => {
|
||||
hideAppView();
|
||||
@@ -43,7 +51,7 @@ export default () => {
|
||||
return settings.get("servers");
|
||||
});
|
||||
|
||||
ipcMain.handle("local-app:selectServer", (event, serverId: string) => {
|
||||
ipcMain.handle("local-app:selectServer", async (event, serverId: string) => {
|
||||
const servers = settings.get("servers") || [];
|
||||
const selectedServer = servers.find((s) => s._id === serverId);
|
||||
|
||||
@@ -51,7 +59,7 @@ export default () => {
|
||||
return new Error("Server not found");
|
||||
}
|
||||
|
||||
showAppView(selectedServer.url);
|
||||
await showAppView(selectedServer.url);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ function onError(e: Error) {
|
||||
function onRejection(reason: Error) {
|
||||
if (reason instanceof Error) {
|
||||
let _reason = reason;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const errPrototype = Object.getPrototypeOf(reason);
|
||||
const nameProperty = Object.getOwnPropertyDescriptor(errPrototype, "name");
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@ import app from "./app";
|
||||
import log from "./log";
|
||||
|
||||
log.init();
|
||||
app.init();
|
||||
void app.init();
|
||||
|
||||
@@ -8,6 +8,7 @@ const api: WorkAdventureDesktopApi = {
|
||||
notify: (txt) => ipcRenderer.send("app:notify", txt),
|
||||
onMuteToggle: (callback) => ipcRenderer.on("app:on-mute-toggle", callback),
|
||||
onCameraToggle: (callback) => ipcRenderer.on("app:on-camera-toggle", callback),
|
||||
getDesktopCapturerSources: (options) => ipcRenderer.invoke("app:getDesktopCapturerSources", options),
|
||||
};
|
||||
|
||||
contextBridge.exposeInMainWorld("WAD", api);
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
// copy of Electron.SourcesOptions to avoid Electron dependency in front
|
||||
export interface SourcesOptions {
|
||||
types: string[];
|
||||
thumbnailSize?: { height: number; width: number };
|
||||
}
|
||||
|
||||
export interface DesktopCapturerSource {
|
||||
id: string;
|
||||
name: string;
|
||||
thumbnailURL: string;
|
||||
}
|
||||
|
||||
export type WorkAdventureDesktopApi = {
|
||||
desktop: boolean;
|
||||
isDevelopment: () => Promise<boolean>;
|
||||
@@ -5,4 +17,5 @@ export type WorkAdventureDesktopApi = {
|
||||
notify: (txt: string) => void;
|
||||
onMuteToggle: (callback: () => void) => void;
|
||||
onCameraToggle: (callback: () => void) => void;
|
||||
getDesktopCapturerSources: (options: SourcesOptions) => Promise<DesktopCapturerSource[]>;
|
||||
};
|
||||
|
||||
@@ -36,14 +36,14 @@ export function createTray() {
|
||||
},
|
||||
{
|
||||
label: "Check for updates",
|
||||
async click() {
|
||||
await autoUpdater.manualRequestUpdateCheck();
|
||||
click() {
|
||||
void autoUpdater.manualRequestUpdateCheck();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Open Logs",
|
||||
click() {
|
||||
log.openLog();
|
||||
void log.openLog();
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -115,7 +115,7 @@ export async function createWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
export function showAppView(url?: string) {
|
||||
export async function showAppView(url?: string) {
|
||||
if (!appView) {
|
||||
throw new Error("App view not found");
|
||||
}
|
||||
@@ -130,7 +130,7 @@ export function showAppView(url?: string) {
|
||||
mainWindow.addBrowserView(appView);
|
||||
|
||||
if (url && url !== appViewUrl) {
|
||||
appView.webContents.loadURL(url);
|
||||
await appView.webContents.loadURL(url);
|
||||
appViewUrl = url;
|
||||
}
|
||||
|
||||
|
||||
+374
-585
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user