diff --git a/desktop/electron/package.json b/desktop/electron/package.json index c0eabedb..26a3929c 100644 --- a/desktop/electron/package.json +++ b/desktop/electron/package.json @@ -27,7 +27,8 @@ "electron-settings": "^4.0.2", "electron-updater": "^4.6.5", "electron-util": "^0.17.2", - "electron-window-state": "^5.0.3" + "electron-window-state": "^5.0.3", + "node-fetch": "^3.2.0" }, "devDependencies": { "@types/auto-launch": "^5.0.2", diff --git a/desktop/electron/src/ipc.ts b/desktop/electron/src/ipc.ts index ba3619ce..31a28d35 100644 --- a/desktop/electron/src/ipc.ts +++ b/desktop/electron/src/ipc.ts @@ -3,25 +3,26 @@ import electronIsDev from "electron-is-dev"; import { createAndShowNotification } from "./notification"; import { Server } from "./preload-local-app/types"; import settings, { SettingsData } from "./settings"; -import { loadShortcuts, saveShortcut, setShortcutsEnabled } from "./shortcuts"; -import { getWindow, hideAppView, showAppView } from "./window"; +import { loadShortcuts, setShortcutsEnabled } from "./shortcuts"; +import { getAppView, getWindow, hideAppView, showAppView } from "./window"; +// import fetch from "node-fetch"; export function emitMuteToggle() { - const mainWindow = getWindow(); - if (!mainWindow) { + const appView = getAppView(); + if (!appView) { throw new Error("Main window not found"); } - mainWindow.webContents.send("app:on-camera-toggle"); + appView.webContents.send("app:on-camera-toggle"); } export function emitCameraToggle() { - const mainWindow = getWindow(); - if (!mainWindow) { + const appView = getAppView(); + if (!appView) { throw new Error("Main window not found"); } - mainWindow.webContents.send("app:on-mute-toggle"); + appView.webContents.send("app:on-mute-toggle"); } export default () => { @@ -68,7 +69,7 @@ export default () => { try { // TODO: add proper test to see if server url is valid and points to a real WA server - await fetch(`${server.url}/iframe_api.js`); + // await fetch(`${server.url}/iframe_api.js`); } catch (e) { console.error(e); return new Error("Invalid server url"); @@ -76,7 +77,7 @@ export default () => { const newServer = { ...server, - _id: `${servers.length + 1}`, + _id: `${Date.now()}-${servers.length + 1}`, }; servers.push(newServer); settings.set("servers", servers); diff --git a/desktop/electron/src/preload-app/preload.ts b/desktop/electron/src/preload-app/preload.ts index d72516e3..bd7239e7 100644 --- a/desktop/electron/src/preload-app/preload.ts +++ b/desktop/electron/src/preload-app/preload.ts @@ -10,4 +10,4 @@ const api: WorkAdventureDesktopApi = { onCameraToggle: (callback) => ipcRenderer.on("app:on-camera-toggle", callback), }; -contextBridge.exposeInMainWorld("WorkAdventureDesktopApi", api); +contextBridge.exposeInMainWorld("WAD", api); diff --git a/desktop/electron/src/preload-local-app/preload.ts b/desktop/electron/src/preload-local-app/preload.ts index 387bfc38..4c970e25 100644 --- a/desktop/electron/src/preload-local-app/preload.ts +++ b/desktop/electron/src/preload-local-app/preload.ts @@ -16,4 +16,4 @@ const api: WorkAdventureLocalAppApi = { setShortcutsEnabled: (enabled) => ipcRenderer.invoke("local-app:setShortcutsEnabled", enabled), }; -contextBridge.exposeInMainWorld("WorkAdventureDesktopApi", api); +contextBridge.exposeInMainWorld("WAD", api); diff --git a/desktop/electron/src/shortcuts.ts b/desktop/electron/src/shortcuts.ts index 7a8ef84b..83385e63 100644 --- a/desktop/electron/src/shortcuts.ts +++ b/desktop/electron/src/shortcuts.ts @@ -1,7 +1,6 @@ import { globalShortcut } from "electron"; import settings, { SettingsData } from "./settings"; import { emitCameraToggle, emitMuteToggle } from "./ipc"; -import { createAndShowNotification } from "./notification"; export function setShortcutsEnabled(enabled: boolean) { if (enabled) { @@ -16,18 +15,15 @@ export function loadShortcuts() { const shortcuts = settings.get("shortcuts"); - // // mute key if (shortcuts?.mute_toggle && shortcuts.mute_toggle.length > 0) { globalShortcut.register(shortcuts.mute_toggle, () => { emitMuteToggle(); - createAndShowNotification({ body: "Toggled mute" }); // TODO }); } if (shortcuts?.camera_toggle && shortcuts.camera_toggle.length > 0) { globalShortcut.register(shortcuts.camera_toggle, () => { emitCameraToggle(); - createAndShowNotification({ body: "Toggled camera" }); // TODO }); } } diff --git a/desktop/electron/src/window.ts b/desktop/electron/src/window.ts index 122270f9..064d8141 100644 --- a/desktop/electron/src/window.ts +++ b/desktop/electron/src/window.ts @@ -17,6 +17,19 @@ export function getAppView() { return appView; } +function resizeAppView() { + if (!mainWindow || !appView) { + return; + } + + appView.setBounds({ + x: sidebarWidth, + y: 0, + width: mainWindow.getBounds().width - sidebarWidth, + height: mainWindow.getBounds().height, + }); +} + export async function createWindow() { // do not re-create window if still existing if (mainWindow) { @@ -41,6 +54,7 @@ export async function createWindow() { preload: path.resolve(__dirname, "..", "dist", "preload-local-app", "preload.js"), }, }); + mainWindow.setMenu(null); // Let us register listeners on the window, so we can update the state // automatically (the listeners will be removed when the window is closed) @@ -74,16 +88,8 @@ export async function createWindow() { preload: path.resolve(__dirname, "..", "dist", "preload-app", "preload.js"), }, }); - appView.setBounds({ - x: sidebarWidth, - y: 0, - width: mainWindow.getBounds().width - sidebarWidth, - height: mainWindow.getBounds().height, - }); - appView.setAutoResize({ - width: true, - height: true, - }); + resizeAppView(); + mainWindow.on("resize", resizeAppView); mainWindow.once("ready-to-show", () => { mainWindow?.show(); @@ -91,7 +97,7 @@ export async function createWindow() { // appView?.webContents.openDevTools({ // mode: "detach", // }); - mainWindow?.webContents.openDevTools({ mode: "detach" }); + // mainWindow?.webContents.openDevTools({ mode: "detach" }); } }); diff --git a/desktop/electron/yarn.lock b/desktop/electron/yarn.lock index 44c6ad47..82034d10 100644 --- a/desktop/electron/yarn.lock +++ b/desktop/electron/yarn.lock @@ -843,6 +843,11 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +data-uri-to-buffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" + integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== + debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" @@ -1455,6 +1460,14 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.4.tgz#e8c6567f80ad7fc22fd302e7dcb72bafde9c1717" + integrity sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -1506,6 +1519,13 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + fs-extra@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" @@ -2246,6 +2266,20 @@ node-addon-api@^1.6.3: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.0.tgz#59390db4e489184fa35d4b74caf5510e8dfbaf3b" + integrity sha512-8xeimMwMItMw8hRrOl3C9/xzU49HV/yE6ORew/l+dxWimO5A4Ra8ld2rerlJvc/O7et5Z1zrWsPX43v1QBjCxw== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -3085,6 +3119,11 @@ verror@^1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +web-streams-polyfill@^3.0.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" + integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" diff --git a/desktop/local-app/index.html b/desktop/local-app/index.html index 6065affb..55d6267f 100644 --- a/desktop/local-app/index.html +++ b/desktop/local-app/index.html @@ -23,6 +23,10 @@ display: flex; } + a:hover { + text-decoration: none !important; + } + *::-webkit-scrollbar { width: 10px; height: 10px; diff --git a/desktop/local-app/src/App.svelte b/desktop/local-app/src/App.svelte index 5a2e92c9..f5045791 100644 --- a/desktop/local-app/src/App.svelte +++ b/desktop/local-app/src/App.svelte @@ -8,6 +8,7 @@ const Home = () => import("~/views/Home.svelte"); const AddServer = () => import("~/views/AddServer.svelte"); const Settings = () => import("~/views/Settings.svelte"); + const Server = () => import("~/views/Server.svelte"); let insideElectron = api.desktop; @@ -19,6 +20,7 @@ Loading ... Loading ... Loading ... + Loading ...

404

No Route could be matched.

diff --git a/desktop/local-app/src/lib/InputField.svelte b/desktop/local-app/src/lib/InputField.svelte index 33a833e7..bb759793 100644 --- a/desktop/local-app/src/lib/InputField.svelte +++ b/desktop/local-app/src/lib/InputField.svelte @@ -9,7 +9,6 @@ {title} - {#if description.length > 0}

{description}

{/if} diff --git a/desktop/local-app/src/lib/Link.svelte b/desktop/local-app/src/lib/Link.svelte deleted file mode 100644 index d5d9ff46..00000000 --- a/desktop/local-app/src/lib/Link.svelte +++ /dev/null @@ -1,18 +0,0 @@ - - -
- -
diff --git a/desktop/local-app/src/lib/Sidebar.svelte b/desktop/local-app/src/lib/Sidebar.svelte index d1e1929b..5b0f6f3c 100644 --- a/desktop/local-app/src/lib/Sidebar.svelte +++ b/desktop/local-app/src/lib/Sidebar.svelte @@ -1,8 +1,8 @@ + + \ No newline at end of file diff --git a/desktop/local-app/src/window.d.ts b/desktop/local-app/src/window.d.ts new file mode 100644 index 00000000..50b20044 --- /dev/null +++ b/desktop/local-app/src/window.d.ts @@ -0,0 +1,7 @@ +import type { WorkAdventureLocalAppApi } from "@wa-preload-local-app"; + +declare global { + interface Window { + WAD: WorkAdventureLocalAppApi; + } +} diff --git a/front/src/Api/desktop/index.ts b/front/src/Api/desktop/index.ts new file mode 100644 index 00000000..be5c7901 --- /dev/null +++ b/front/src/Api/desktop/index.ts @@ -0,0 +1,38 @@ +import { isSilentStore, requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore"; +import { get } from "svelte/store"; + +class DesktopApi { + isSilent: boolean = false; + + init() { + if (!window?.WAD?.desktop) { + return; + } + + console.log("Yipee you are using the desktop app ;)"); + + window.WAD.onMuteToggle(() => { + if (this.isSilent) return; + if (get(requestedMicrophoneState) === true) { + requestedMicrophoneState.disableMicrophone(); + } else { + requestedMicrophoneState.enableMicrophone(); + } + }); + + window.WAD.onCameraToggle(() => { + if (this.isSilent) return; + if (get(requestedCameraState) === true) { + requestedCameraState.disableWebcam(); + } else { + requestedCameraState.enableWebcam(); + } + }); + + isSilentStore.subscribe((value) => { + this.isSilent = value; + }); + } +} + +export const desktopApi = new DesktopApi(); diff --git a/front/src/iframe_api.ts b/front/src/iframe_api.ts index f5e20032..e368df32 100644 --- a/front/src/iframe_api.ts +++ b/front/src/iframe_api.ts @@ -182,13 +182,6 @@ const wa = { export type WorkAdventureApi = typeof wa; -declare global { - interface Window { - WA: WorkAdventureApi; - } - let WA: WorkAdventureApi; -} - window.WA = wa; window.addEventListener( diff --git a/front/src/index.ts b/front/src/index.ts index b34191aa..cfe06a46 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -16,6 +16,7 @@ import { coWebsiteManager } from "./WebRtc/CoWebsiteManager"; import { localUserStore } from "./Connexion/LocalUserStore"; import { ErrorScene } from "./Phaser/Reconnecting/ErrorScene"; import { iframeListener } from "./Api/IframeListener"; +import { desktopApi } from "./Api/desktop/index"; import { SelectCharacterMobileScene } from "./Phaser/Login/SelectCharacterMobileScene"; import { HdpiManager } from "./Phaser/Services/HdpiManager"; import { waScaleManager } from "./Phaser/Services/WaScaleManager"; @@ -154,6 +155,7 @@ coWebsiteManager.onResize.subscribe(() => { }); iframeListener.init(); +desktopApi.init(); const app = new App({ target: HtmlUtils.getElementByIdOrFail("game-overlay"), diff --git a/front/src/window.d.ts b/front/src/window.d.ts new file mode 100644 index 00000000..8393e15e --- /dev/null +++ b/front/src/window.d.ts @@ -0,0 +1,10 @@ +import { WorkAdventureApi } from "./iframe_api"; +import { WorkAdventureDesktopApi } from "@wa-preload-app"; + +declare global { + interface Window { + WA: WorkAdventureApi; + WAD: WorkAdventureDesktopApi; + } + let WA: WorkAdventureApi; +} diff --git a/front/tsconfig.json b/front/tsconfig.json index b9057d28..edb99eb5 100644 --- a/front/tsconfig.json +++ b/front/tsconfig.json @@ -27,7 +27,10 @@ "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "paths": { + "@wa-preload-app": ["../desktop/electron/src/preload-app/types.ts"], + } }, "exclude": [ "node_modules",