improve local-app
This commit is contained in:
parent
6b208ceb0c
commit
ac18aab773
@ -17,6 +17,8 @@
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
|
||||
"@tsconfig/svelte": "^2.0.1",
|
||||
"prettier": "^2.5.1",
|
||||
"prettier-plugin-svelte": "^2.6.0",
|
||||
"rollup-plugin-svelte-svg": "^1.0.0-beta.6",
|
||||
"svelte": "^3.44.0",
|
||||
"svelte-check": "^2.2.7",
|
||||
"svelte-navigator": "^3.1.5",
|
||||
@ -26,5 +28,10 @@
|
||||
"vite": "^2.8.0",
|
||||
"vite-plugin-windicss": "^1.7.1",
|
||||
"windicss": "^3.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@16bits/nes.css": "^2.3.2",
|
||||
"@fontsource/press-start-2p": "^4.5.2",
|
||||
"hotkeys-js": "^3.8.7"
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { Router, Route } from "svelte-navigator";
|
||||
|
||||
import Sidebar from "./lib/Sidebar.svelte";
|
||||
import Sidebar from "~/lib/Sidebar.svelte";
|
||||
|
||||
import LazyRoute from "./lib/LazyRoute.svelte";
|
||||
import LazyRoute from "~/lib/LazyRoute.svelte";
|
||||
|
||||
const Home = () => import("./views/Home.svelte");
|
||||
const AddServer = () => import("./views/AddServer.svelte");
|
||||
const Home = () => import("~/views/Home.svelte");
|
||||
const AddServer = () => import("~/views/AddServer.svelte");
|
||||
const Settings = () => import("~/views/Settings.svelte");
|
||||
|
||||
let insideElectron = window?.WorkAdventureDesktopApi?.desktop;
|
||||
</script>
|
||||
@ -17,6 +18,7 @@
|
||||
<main class="flex flex-grow">
|
||||
<LazyRoute path="/" component={Home} delayMs={500}>Loading ...</LazyRoute>
|
||||
<LazyRoute path="/server/add" component={AddServer} delayMs={500}>Loading ...</LazyRoute>
|
||||
<LazyRoute path="/settings" component={Settings} delayMs={500}>Loading ...</LazyRoute>
|
||||
<Route>
|
||||
<h3>404</h3>
|
||||
<p>No Route could be matched.</p>
|
||||
@ -28,9 +30,12 @@
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
@import "@fontsource/press-start-2p/index.css";
|
||||
@import "@16bits/nes.css/css/nes.min.css";
|
||||
|
||||
:root {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
|
||||
"Helvetica Neue", sans-serif;
|
||||
font-family: "Press Start 2P", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell,
|
||||
"Open Sans", "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
main {
|
||||
|
3
desktop/local-app/src/assets/nes.icons/README.md
Normal file
3
desktop/local-app/src/assets/nes.icons/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# NES.icons
|
||||
|
||||
Source: https://github.com/nostalgic-css/NES.icons/
|
103
desktop/local-app/src/assets/nes.icons/cog.svg
Normal file
103
desktop/local-app/src/assets/nes.icons/cog.svg
Normal file
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="7" y="0" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="0" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="1" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="1" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="1" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="1" width="1" height="1" fill="#000000" />
|
||||
<rect x="1" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="5" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="6" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="9" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="10" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="14" y="2" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="4" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="5" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="6" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="9" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="10" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="11" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="3" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="4" width="1" height="1" fill="#000000" />
|
||||
<rect x="4" y="4" width="1" height="1" fill="#000000" />
|
||||
<rect x="11" y="4" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="4" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="5" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="5" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="5" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="5" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="6" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="6" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="6" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="6" width="1" height="1" fill="#000000" />
|
||||
<rect x="0" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="1" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="14" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="15" y="7" width="1" height="1" fill="#000000" />
|
||||
<rect x="0" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="1" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="14" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="15" y="8" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="9" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="9" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="9" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="9" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="10" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="10" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="10" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="10" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="11" width="1" height="1" fill="#000000" />
|
||||
<rect x="4" y="11" width="1" height="1" fill="#000000" />
|
||||
<rect x="11" y="11" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="11" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="4" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="5" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="6" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="9" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="10" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="11" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="12" width="1" height="1" fill="#000000" />
|
||||
<rect x="1" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="3" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="5" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="6" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="9" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="10" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="12" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="14" y="13" width="1" height="1" fill="#000000" />
|
||||
<rect x="2" y="14" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="14" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="14" width="1" height="1" fill="#000000" />
|
||||
<rect x="13" y="14" width="1" height="1" fill="#000000" />
|
||||
<rect x="7" y="15" width="1" height="1" fill="#000000" />
|
||||
<rect x="8" y="15" width="1" height="1" fill="#000000" />
|
||||
</svg>
|
After Width: | Height: | Size: 5.8 KiB |
16
desktop/local-app/src/lib/InputField.svelte
Normal file
16
desktop/local-app/src/lib/InputField.svelte
Normal file
@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
export let title: string;
|
||||
export let id: string;
|
||||
export let description: string = "";
|
||||
</script>
|
||||
|
||||
<div class="mb-6">
|
||||
<label class="block text-gray-200 text-lg font-bold mb-1" for={id}>
|
||||
{title}
|
||||
</label>
|
||||
<slot />
|
||||
<!-- <input class="shadow appearance-none border border-red-500 rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" id="password" type="password" placeholder="******************"> -->
|
||||
{#if description.length > 0}
|
||||
<p class="text-gray-200 text-xs mt-1 italic">{description}</p>
|
||||
{/if}
|
||||
</div>
|
178
desktop/local-app/src/lib/KeyRecord.svelte
Normal file
178
desktop/local-app/src/lib/KeyRecord.svelte
Normal file
@ -0,0 +1,178 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
export let id: string;
|
||||
export let value: string = "";
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: string;
|
||||
}>();
|
||||
|
||||
// https://www.electronjs.org/de/docs/latest/api/accelerator
|
||||
function keyCodeToElectron(key: string): string {
|
||||
if (key.match(/^Key[A-Z]/)) {
|
||||
return key.replace(/^Key/, "").toLocaleUpperCase();
|
||||
}
|
||||
|
||||
if (key.match(/^Digit[0-9]/)) {
|
||||
return key.replace(/^Digit/, "").toLowerCase();
|
||||
}
|
||||
|
||||
if (key.match(/^Numpad[0-9]/)) {
|
||||
return key.replace(/^Numpad/, "num").toLowerCase();
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
// Modifiers
|
||||
case "ControlLeft":
|
||||
return "CmdOrCtrl";
|
||||
case "ControlRight":
|
||||
return "CmdOrCtrl";
|
||||
case "AltLeft":
|
||||
return "Alt";
|
||||
case "AltRight":
|
||||
return "AltGr";
|
||||
case "ScrollLock":
|
||||
return "Scrolllock";
|
||||
case "ShiftLeft":
|
||||
return "Shift";
|
||||
case "ShiftRight":
|
||||
return "Shift";
|
||||
// Specialchars
|
||||
case "Period":
|
||||
return ".";
|
||||
case "Comma":
|
||||
return ",";
|
||||
case "Slash":
|
||||
return "/";
|
||||
case "Backslash":
|
||||
return "\\";
|
||||
case "Minus":
|
||||
return "-";
|
||||
case "Equal":
|
||||
return "=";
|
||||
case "BracketLeft":
|
||||
return "[";
|
||||
case "BracketRight":
|
||||
return "]";
|
||||
case "Quote":
|
||||
return "'";
|
||||
case "Semicolon":
|
||||
return ";";
|
||||
case "IntlBackslash":
|
||||
return "\\";
|
||||
case "Backquote":
|
||||
return "`";
|
||||
// Numpad
|
||||
case "NumpadDecimal":
|
||||
return "numdec";
|
||||
case "NumpadAdd":
|
||||
return "numadd";
|
||||
case "NumpadSubtract":
|
||||
return "numsub";
|
||||
case "NumpadMultiply":
|
||||
return "nummult";
|
||||
case "NumpadDivide":
|
||||
return "numdiv";
|
||||
default:
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
let shortCut: string[] = [];
|
||||
let recording = false;
|
||||
let recordingTimeout: NodeJS.Timeout;
|
||||
let keyInputTimeout: NodeJS.Timeout;
|
||||
|
||||
function camelPad(str: string) {
|
||||
return (
|
||||
str
|
||||
// Look for long acronyms and filter out the last letter
|
||||
.replace(/([A-Z]+)([A-Z][a-z])/g, " $1 $2")
|
||||
// Look for lower-case letters followed by upper-case letters
|
||||
.replace(/([a-z\d])([A-Z])/g, "$1 $2")
|
||||
// Look for lower-case letters followed by numbers
|
||||
// .replace(/([a-zA-Z])(\d)/g, "$1 $2")
|
||||
.replace(/^./, (str) => str.toUpperCase())
|
||||
// Remove any white space left around the word
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
||||
function resetRecording() {
|
||||
recording = false;
|
||||
shortCut = [];
|
||||
value = "";
|
||||
}
|
||||
|
||||
function stopRecording() {
|
||||
clearTimeout(recordingTimeout);
|
||||
recording = false;
|
||||
value = shortCut.map(keyCodeToElectron).join(" + ");
|
||||
dispatch("change", value);
|
||||
}
|
||||
|
||||
function startRecording() {
|
||||
if (recording) {
|
||||
return;
|
||||
}
|
||||
|
||||
recording = true;
|
||||
value = "";
|
||||
shortCut = [];
|
||||
|
||||
recordingTimeout = setTimeout(() => {
|
||||
stopRecording();
|
||||
}, 1000 * 5);
|
||||
}
|
||||
|
||||
function keyUp(event: KeyboardEvent) {
|
||||
if (!recording) {
|
||||
return;
|
||||
}
|
||||
|
||||
shortCut = [...shortCut, event.code];
|
||||
|
||||
if (!keyInputTimeout) {
|
||||
keyInputTimeout = setTimeout(() => {
|
||||
stopRecording();
|
||||
keyInputTimeout = undefined;
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={`flex items-center w-full h-8 border-1 rounded-md overflow-hidden text-gray-200 text-xs appearance-none focus:outline-none ${
|
||||
recording ? "border-red-500" : "border-gray-400"
|
||||
}`}
|
||||
on:keyup={keyUp}
|
||||
on:click={startRecording}
|
||||
tabindex="0"
|
||||
>
|
||||
<input
|
||||
{id}
|
||||
type="text"
|
||||
class="flex-grow h-full border-none mx-2 bg-transparent appearance-none focus:outline-none"
|
||||
disabled
|
||||
{value}
|
||||
/>
|
||||
{#if value.length > 0}
|
||||
<span
|
||||
class="flex items-center justify-center w-4 h-4 p-2 mr-1 rounded-full cursor-pointer bg-gray-500 hover:bg-gray-400"
|
||||
on:click|stopPropagation={resetRecording}>x</span
|
||||
>
|
||||
{/if}
|
||||
<div
|
||||
class={`flex h-6 items-center px-2 m-0.5 rounded-sm w-28 justify-center cursor-pointer ${
|
||||
recording ? "bg-red-500" : "hover:bg-gray-400"
|
||||
}`}
|
||||
on:click={recording ? stopRecording : startRecording}
|
||||
>
|
||||
{#if recording}
|
||||
<span>recording</span>
|
||||
{:else}
|
||||
<span>record</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
@ -21,7 +21,7 @@
|
||||
showFallback = true;
|
||||
}, delayMs);
|
||||
}
|
||||
component().then(module => {
|
||||
component().then((module) => {
|
||||
loadedComponent = module.default;
|
||||
});
|
||||
return () => clearTimeout(timeout);
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { Route } from "svelte-navigator";
|
||||
import Lazy from "./Lazy.svelte";
|
||||
import Lazy from "~/lib/Lazy.svelte";
|
||||
|
||||
export let component;
|
||||
export let delayMs = null;
|
||||
|
@ -1,18 +1,17 @@
|
||||
<script>
|
||||
import { navigate } from "svelte-navigator";
|
||||
|
||||
let to = '/';
|
||||
let clazz = '';
|
||||
let to = "/";
|
||||
let clazz = "";
|
||||
|
||||
export { clazz as class, to };
|
||||
|
||||
|
||||
async function click() {
|
||||
await window?.WorkAdventureDesktopApi?.showLocalApp();
|
||||
navigate(to);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div on:click="{ click }" class="{`${clazz}`}">
|
||||
<div on:click={click} class={`${clazz}`}>
|
||||
<slot />
|
||||
</div>
|
@ -1,16 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import Link from "./Link.svelte";
|
||||
import { servers, selectedServer, selectServer, loadServers } from "../store";
|
||||
|
||||
import Link from "~/lib/Link.svelte";
|
||||
import { servers, selectedServer, selectServer, loadServers, Server } from "../store";
|
||||
import CogIcon from "~/assets/nes.icons/cog.svg";
|
||||
|
||||
let isDevelopment = false;
|
||||
|
||||
function getServerColor(i: number) {
|
||||
const serverColors = ['bg-red-400', 'bg-yellow-500', 'bg-green-500', 'bg-blue-500', 'bg-indigo-500', 'bg-purple-500'];
|
||||
const serverColors = [
|
||||
"bg-red-400",
|
||||
"bg-yellow-500",
|
||||
"bg-green-500",
|
||||
"bg-blue-500",
|
||||
"bg-indigo-500",
|
||||
"bg-purple-500",
|
||||
];
|
||||
|
||||
return serverColors[i % serverColors.length];
|
||||
}
|
||||
|
||||
selectedServer.subscribe((e) => {
|
||||
console.log("selected server changed", e);
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
await loadServers();
|
||||
isDevelopment = await window?.WorkAdventureDesktopApi?.isDevelopment();
|
||||
@ -20,29 +33,37 @@
|
||||
<aside class="flex flex-col bg-gray-700 items-center">
|
||||
<div class="flex flex-col mt-4 space-y-4 overflow-y-auto pb-4">
|
||||
{#each $servers as server, i}
|
||||
<div class="flex flex-col items-center justify-center text-gray-400">
|
||||
<div class="flex flex-col items-center justify-center ">
|
||||
<div
|
||||
class={`w-12 h-12 rounded-lg flex cursor-pointer text-center items-center justify-center text-light-50 ${getServerColor(i)} ${
|
||||
$selectedServer === server._id ? "" : ""
|
||||
}`}
|
||||
class={`w-16 h-16 p-1 rounded-md flex cursor-pointer text-light-50 border-4 border-transparent text-gray-200 hover:text-gray-500`}
|
||||
class:border-gray-400={$selectedServer === server._id}
|
||||
on:click={() => selectServer(server)}
|
||||
>
|
||||
{server.name.slice(0, 2).toLocaleUpperCase()}
|
||||
<div class={`flex w-full h-full text-center items-center justify-center rounded-md ${getServerColor(i)}`}>
|
||||
{server.name.slice(0,2).toLocaleUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<Link
|
||||
to="/server/add"
|
||||
class="flex justify-center items-center text-4xl no-underline text-gray-400 cursor-pointer">+</Link
|
||||
class="flex justify-center items-center text-4xl no-underline text-gray-200 cursor-pointer hover:text-gray-500"
|
||||
>+</Link
|
||||
>
|
||||
</div>
|
||||
<Link
|
||||
to="/settings"
|
||||
class="flex mt-auto justify-center items-center text-4xl no-underline cursor-pointer"
|
||||
>
|
||||
<CogIcon width="30" height="30" class="fill-gray-200 hover:fill-gray-500" />
|
||||
</Link>
|
||||
{#if isDevelopment}
|
||||
<button class="mt-auto" on:click={() => location.reload()}>Refresh</button>
|
||||
<button class="text-8px text-red-500 mt-8 mb-4" on:click={() => location.reload()}>Refresh</button>
|
||||
{/if}
|
||||
</aside>
|
||||
|
||||
<style>
|
||||
aside {
|
||||
width: 70px;
|
||||
width: 80px;
|
||||
}
|
||||
</style>
|
||||
|
27
desktop/local-app/src/lib/TextInput.svelte
Normal file
27
desktop/local-app/src/lib/TextInput.svelte
Normal file
@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
export let id: string;
|
||||
export let value: string = "";
|
||||
export let required: boolean = false;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
change: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={`flex items-center w-full h-10 border-1 rounded-md overflow-hidden text-gray-200 text-md appearance-none focus:outline-none`}
|
||||
>
|
||||
<input
|
||||
{id}
|
||||
type="text"
|
||||
class="flex-grow h-full border-none mx-2 bg-transparent appearance-none focus:outline-none"
|
||||
{value}
|
||||
{required}
|
||||
on:change={(e) => {
|
||||
value = e.target.value;
|
||||
dispatch("change", { value });
|
||||
}}
|
||||
/>
|
||||
</div>
|
25
desktop/local-app/src/lib/ToggleSwitch.svelte
Normal file
25
desktop/local-app/src/lib/ToggleSwitch.svelte
Normal file
@ -0,0 +1,25 @@
|
||||
<script lang="ts">
|
||||
export let id: string;
|
||||
export let value: boolean;
|
||||
export let title: string = null;
|
||||
</script>
|
||||
|
||||
<div class="flex w-full my-2">
|
||||
<label for={id} class="flex items-center cursor-pointer">
|
||||
<div class="relative">
|
||||
<input {id} type="checkbox" class="sr-only" checked={value} />
|
||||
<div class="w-10 h-4 bg-gray-400 rounded-full shadow-inner" />
|
||||
<div class="dot absolute w-6 h-6 bg-gray-500 rounded-full shadow -left-1 -top-1 transition" />
|
||||
</div>
|
||||
{#if title}
|
||||
<div class="ml-4 text-gray-200 text-sm">{title}</div>
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
input:checked ~ .dot {
|
||||
transform: translateX(100%);
|
||||
background-color: #0369a1;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
import { writable, get } from "svelte/store";
|
||||
|
||||
type Server = {
|
||||
export type Server = {
|
||||
_id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
@ -11,15 +11,19 @@ export const newServer = writable<Omit<Server, "_id">>({
|
||||
url: "",
|
||||
});
|
||||
export const servers = writable<Server[]>([]);
|
||||
export const selectedServer = writable<string | undefined>(undefined);
|
||||
export const selectedServer = writable<string | undefined>("");
|
||||
|
||||
export async function selectServer(server: Server) {
|
||||
await window.WorkAdventureDesktopApi.selectServer(server._id);
|
||||
selectedServer.set(server._id);
|
||||
}
|
||||
|
||||
export async function addServer(event: Event) {
|
||||
export async function addServer() {
|
||||
const addedServer = await window?.WorkAdventureDesktopApi?.addServer(get(newServer));
|
||||
if (!addedServer?._id) {
|
||||
console.log(addedServer);
|
||||
throw new Error(addedServer);
|
||||
}
|
||||
newServer.set({ name: "", url: "" });
|
||||
servers.update((s) => [...s, addedServer]);
|
||||
await selectServer(addedServer);
|
||||
|
4
desktop/local-app/src/svg.d.ts
vendored
Normal file
4
desktop/local-app/src/svg.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module "*.svg" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
@ -1,12 +1,36 @@
|
||||
<script lang="ts">
|
||||
import { newServer, addServer } from '../store';
|
||||
import InputField from "~/lib/InputField.svelte";
|
||||
import TextInput from "~/lib/TextInput.svelte";
|
||||
|
||||
import { newServer, addServer } from "~/store";
|
||||
|
||||
let error = "";
|
||||
async function _addServer() {
|
||||
try {
|
||||
await addServer();
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
error = e.message;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex w-full h-full justify-center items-center">
|
||||
|
||||
<form class="flex flex-col justify-center space-y-2" on:submit|preventDefault={addServer}>
|
||||
<input type="text" class="w-full h-12 px-4 py-2 bg-gray-200 rounded-lg" placeholder="Name" required bind:value={$newServer.name}>
|
||||
<input type="text" class="w-full h-12 px-4 py-2 bg-gray-200 rounded-lg" placeholder="Url" required bind:value={$newServer.url}>
|
||||
<input type="submit" value="Add server" />
|
||||
<form class="flex flex-col justify-center" on:submit|preventDefault={_addServer}>
|
||||
<!-- <input type="text" class="w-full h-12 px-4 py-2 bg-gray-200 rounded-lg" placeholder="Url" required > -->
|
||||
<InputField title="Name" id="name">
|
||||
<TextInput bind:value={$newServer.name} required id="name" />
|
||||
</InputField>
|
||||
<InputField title="Url" id="url">
|
||||
<TextInput bind:value={$newServer.url} required id="url" />
|
||||
</InputField>
|
||||
{#if error}
|
||||
<div class="text-red-500 text-center mb-2">{error}</div>
|
||||
{/if}
|
||||
<input
|
||||
type="submit"
|
||||
value="Add server"
|
||||
class="mt-4 rounded-md p-2 bg-gray-300 cursor-pointer hover:bg-gray-400"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,7 +1,18 @@
|
||||
<script lang="ts">
|
||||
import logo from "../../../assets/icons/logo-text.png";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import Logo from "~/../../assets/icons/logo.svg";
|
||||
|
||||
let version = "";
|
||||
|
||||
onMount(async () => {
|
||||
version = await window?.WorkAdventureDesktopApi?.getVersion();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex w-full h-full justify-center items-center">
|
||||
<img src={logo} alt="WorkAdeventure logo" />
|
||||
<div class="flex flex-col w-full h-full justify-center items-center">
|
||||
<Logo height="100" class="my-auto" />
|
||||
<div class="flex my-4 items-center space-x-4">
|
||||
<span class="text-gray-300 text-lg ">Desktop-App Version: {version}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
59
desktop/local-app/src/views/Settings.svelte
Normal file
59
desktop/local-app/src/views/Settings.svelte
Normal file
@ -0,0 +1,59 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
import ToggleSwitch from "~/lib/ToggleSwitch.svelte";
|
||||
import InputField from "~/lib/InputField.svelte";
|
||||
import KeyRecord from "~/lib/KeyRecord.svelte";
|
||||
|
||||
const shortCuts = writable<Record<string, string> | undefined>({});
|
||||
|
||||
onMount(async () => {
|
||||
shortCuts.set(await window?.WorkAdventureDesktopApi?.getShortcuts());
|
||||
});
|
||||
|
||||
async function saveShortcut(key: string, value: string) {
|
||||
await window?.WorkAdventureDesktopApi?.saveShortcut(key, value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col w-full h-full justify-center items-center">
|
||||
<h1 class="text-gray-200 text-2xl mb-6">Settings</h1>
|
||||
|
||||
<div class="flex flex-col justify-start max-w-152">
|
||||
{#if $shortCuts}
|
||||
<InputField
|
||||
id="toggle-camera"
|
||||
title="Toggle Mute"
|
||||
description="Set a shortcut to turn your microphone on and off"
|
||||
>
|
||||
<KeyRecord
|
||||
id="toggle-mute"
|
||||
value={$shortCuts.mute_toggle}
|
||||
on:change={(e) => saveShortcut("mute_toggle", e.detail)}
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
id="toggle-camera"
|
||||
title="Toggle Camera"
|
||||
description="Set a shortcut to turn your camera on and off"
|
||||
>
|
||||
<KeyRecord
|
||||
id="toggle-camera"
|
||||
value={$shortCuts.camera_toggle}
|
||||
on:change={(e) => saveShortcut("camera_toggle", e.detail)}
|
||||
/>
|
||||
</InputField>
|
||||
{/if}
|
||||
|
||||
<InputField id="toggle-autostart" title="Toggle autostart">
|
||||
<ToggleSwitch
|
||||
id="toggle-autostart"
|
||||
value={true}
|
||||
title="Autostart WorkAdventure after your PC started"
|
||||
on:change={(e) => {}}
|
||||
/>
|
||||
</InputField>
|
||||
</div>
|
||||
</div>
|
@ -13,7 +13,10 @@
|
||||
* of JS in `.svelte` files.
|
||||
*/
|
||||
"allowJs": true,
|
||||
"checkJs": true
|
||||
"checkJs": true,
|
||||
"paths": {
|
||||
"~/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
|
@ -2,7 +2,8 @@
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node"
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
|
@ -1,7 +1,26 @@
|
||||
import { defineConfig } from "vite";
|
||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||
import WindiCSS from "vite-plugin-windicss";
|
||||
import { svelteSVG } from "rollup-plugin-svelte-svg";
|
||||
import path from "path";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [svelte(), WindiCSS()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"~": `${path.resolve(__dirname, "src")}/`,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
svelte(),
|
||||
svelteSVG({
|
||||
// optional SVGO options
|
||||
// pass empty object to enable defaults
|
||||
svgo: {},
|
||||
// vite-specific
|
||||
// https://vitejs.dev/guide/api-plugin.html#plugin-ordering
|
||||
// enforce: 'pre' | 'post'
|
||||
enforce: "pre",
|
||||
}),
|
||||
WindiCSS(),
|
||||
],
|
||||
});
|
||||
|
@ -2,6 +2,11 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@16bits/nes.css@^2.3.2":
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@16bits/nes.css/-/nes.css-2.3.2.tgz#e69db834119b33ae8d3cb044f106a07a17cadd6f"
|
||||
integrity sha512-nEM5PIth+Bab5JSOa4uUR+PMNUsNTYxA55oVlG3gXI/4LoYtWS767Uv9Pu/KCbHXVvnIjt4ZXt13kZw3083qTw==
|
||||
|
||||
"@antfu/utils@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.4.0.tgz#df100ed9922d7359bf6c99083765b5207086b9a7"
|
||||
@ -9,6 +14,11 @@
|
||||
dependencies:
|
||||
"@types/throttle-debounce" "^2.1.0"
|
||||
|
||||
"@fontsource/press-start-2p@^4.5.2":
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@fontsource/press-start-2p/-/press-start-2p-4.5.2.tgz#062d56ce6dcffdd28f8ca80d9e5b86a473a37c15"
|
||||
integrity sha512-1Wwk85zlUiirPTIw25V3z4wLXbrqaOqDV7g5akjPuthg+hY5Wv0zOPXcHRVBwb+Igh4qVLHUd6O5X27BgWTbkg==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
@ -49,6 +59,11 @@
|
||||
magic-string "^0.25.7"
|
||||
svelte-hmr "^0.14.9"
|
||||
|
||||
"@trysound/sax@0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
|
||||
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
|
||||
|
||||
"@tsconfig/svelte@^2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/svelte/-/svelte-2.0.1.tgz#0e8d7caa693e9b2afce5e622c0475bb0fd89c12c"
|
||||
@ -116,6 +131,11 @@ binary-extensions@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
boolbase@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@ -156,11 +176,47 @@ chokidar@^3.4.1:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
commander@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
||||
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
css-select@^4.1.3:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd"
|
||||
integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
css-what "^5.1.0"
|
||||
domhandler "^4.3.0"
|
||||
domutils "^2.8.0"
|
||||
nth-check "^2.0.1"
|
||||
|
||||
css-tree@^1.1.2, css-tree@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
|
||||
integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
|
||||
dependencies:
|
||||
mdn-data "2.0.14"
|
||||
source-map "^0.6.1"
|
||||
|
||||
css-what@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe"
|
||||
integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==
|
||||
|
||||
csso@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
|
||||
integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==
|
||||
dependencies:
|
||||
css-tree "^1.1.2"
|
||||
|
||||
debug@^4.3.3:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
@ -178,6 +234,41 @@ detect-indent@^6.0.0:
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
|
||||
integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
|
||||
|
||||
dom-serializer@^1.0.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91"
|
||||
integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==
|
||||
dependencies:
|
||||
domelementtype "^2.0.1"
|
||||
domhandler "^4.2.0"
|
||||
entities "^2.0.0"
|
||||
|
||||
domelementtype@^2.0.1, domelementtype@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
|
||||
integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
|
||||
|
||||
domhandler@^4.2.0, domhandler@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626"
|
||||
integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==
|
||||
dependencies:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
domutils@^2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
|
||||
integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
|
||||
dependencies:
|
||||
dom-serializer "^1.0.1"
|
||||
domelementtype "^2.2.0"
|
||||
domhandler "^4.2.0"
|
||||
|
||||
entities@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||
|
||||
es6-promise@^3.1.2:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
|
||||
@ -303,6 +394,11 @@ esbuild@^0.14.14:
|
||||
esbuild-windows-64 "0.14.23"
|
||||
esbuild-windows-arm64 "0.14.23"
|
||||
|
||||
estree-walker@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
||||
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
||||
|
||||
estree-walker@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
|
||||
@ -379,6 +475,11 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hotkeys-js@^3.8.7:
|
||||
version "3.8.7"
|
||||
resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.8.7.tgz#c16cab978b53d7242f860ca3932e976b92399981"
|
||||
integrity sha512-ckAx3EkUr5XjDwjEHDorHxRO2Kb7z6Z2Sxul4MbBkN8Nho7XDslQsgMJT+CiJ5Z4TgRxxvKHEpuLE3imzqy4Lg==
|
||||
|
||||
import-fresh@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
@ -460,6 +561,11 @@ magic-string@^0.25.7:
|
||||
dependencies:
|
||||
sourcemap-codec "^1.4.4"
|
||||
|
||||
mdn-data@2.0.14:
|
||||
version "2.0.14"
|
||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
|
||||
integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
@ -525,6 +631,13 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
nth-check@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
|
||||
integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@ -576,6 +689,11 @@ postcss@^8.4.6:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
prettier-plugin-svelte@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-2.6.0.tgz#0e845b560b55cd1d951d6c50431b4949f8591746"
|
||||
integrity sha512-NPSRf6Y5rufRlBleok/pqg4+1FyGsL0zYhkYP6hnueeL1J/uCm3OfOZPsLX4zqD9VAdcXfyEL2PYqGv8ZoOSfA==
|
||||
|
||||
prettier@^2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
|
||||
@ -619,6 +737,21 @@ rimraf@^2.5.2:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rollup-plugin-svelte-svg@^1.0.0-beta.6:
|
||||
version "1.0.0-beta.6"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-svelte-svg/-/rollup-plugin-svelte-svg-1.0.0-beta.6.tgz#0ee3deae2329abb1c90f50b83598aaf0bb0559fc"
|
||||
integrity sha512-6uJb9kuaqK6p+DvkgphhGN18wvUzdT6h7MQC2B8P1omi9omC9lQC54pwaot21h6z9ibhGPLG9a1XFLeDQth/kg==
|
||||
dependencies:
|
||||
rollup-pluginutils "^2.8.2"
|
||||
svgo "^2.3.1"
|
||||
|
||||
rollup-pluginutils@^2.8.2:
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
|
||||
integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
|
||||
dependencies:
|
||||
estree-walker "^0.6.1"
|
||||
|
||||
rollup@^2.59.0:
|
||||
version "2.67.3"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.67.3.tgz#3f04391fc296f807d067c9081d173e0a33dbd37e"
|
||||
@ -665,6 +798,11 @@ source-map-js@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
source-map@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
@ -675,6 +813,11 @@ sourcemap-codec@^1.3.0, sourcemap-codec@^1.4.4:
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||
|
||||
stable@^0.1.8:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
||||
|
||||
strip-indent@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
|
||||
@ -739,6 +882,19 @@ svelte@^3.44.0:
|
||||
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.46.4.tgz#0c46bc4a3e20a2617a1b7dc43a722f9d6c084a38"
|
||||
integrity sha512-qKJzw6DpA33CIa+C/rGp4AUdSfii0DOTCzj/2YpSKKayw5WGSS624Et9L1nU1k2OVRS9vaENQXp2CVZNU+xvIg==
|
||||
|
||||
svgo@^2.3.1:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24"
|
||||
integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
|
||||
dependencies:
|
||||
"@trysound/sax" "0.2.0"
|
||||
commander "^7.2.0"
|
||||
css-select "^4.1.3"
|
||||
css-tree "^1.1.3"
|
||||
csso "^4.2.0"
|
||||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
|
@ -3,11 +3,12 @@ import { app, BrowserWindow, globalShortcut } from "electron";
|
||||
import { createWindow, getWindow } from "./window";
|
||||
import { createTray } from "./tray";
|
||||
import autoUpdater from "./auto-updater";
|
||||
import updateAutoLaunch from "./update-auto-launch";
|
||||
import ipc, { emitMutedKeyPress } from "./ipc";
|
||||
import { updateAutoLaunch } from "./auto-launch";
|
||||
import ipc from "./ipc";
|
||||
import settings from "./settings";
|
||||
import { setLogLevel } from "./log";
|
||||
import "./serve"; // prepare custom url scheme
|
||||
import { loadShortcuts } from "./shortcuts";
|
||||
|
||||
function init() {
|
||||
const appLock = app.requestSingleInstanceLock();
|
||||
@ -56,10 +57,7 @@ function init() {
|
||||
await createWindow();
|
||||
createTray();
|
||||
|
||||
// TODO
|
||||
globalShortcut.register("Alt+CommandOrControl+M", () => {
|
||||
emitMutedKeyPress();
|
||||
});
|
||||
loadShortcuts();
|
||||
});
|
||||
|
||||
// Quit when all windows are closed.
|
||||
@ -81,6 +79,10 @@ function init() {
|
||||
app.on("quit", () => {
|
||||
// TODO
|
||||
});
|
||||
|
||||
app.on("will-quit", () => {
|
||||
globalShortcut.unregisterAll();
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import AutoLaunch from "auto-launch";
|
||||
import isDev from "electron-is-dev";
|
||||
import { app } from "electron";
|
||||
import electronIsDev from "electron-is-dev";
|
||||
|
||||
import settings from "./settings";
|
||||
|
||||
export default async () => {
|
||||
export async function updateAutoLaunch() {
|
||||
let isAutoLaunchEnabled = settings.get("auto_launch_enabled");
|
||||
|
||||
// set default to enabled
|
||||
@ -14,7 +14,7 @@ export default async () => {
|
||||
}
|
||||
|
||||
// Don't run this in development
|
||||
if (isDev) {
|
||||
if (electronIsDev) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -38,4 +38,4 @@ export default async () => {
|
||||
openAtLogin: isAutoLaunchEnabled,
|
||||
openAsHidden: true,
|
||||
});
|
||||
};
|
||||
}
|
@ -1,21 +1,32 @@
|
||||
import { ipcMain } from "electron";
|
||||
import { ipcMain, app } from "electron";
|
||||
import electronIsDev from "electron-is-dev";
|
||||
import { createAndShowNotification } from "./notification";
|
||||
import { Server } from "./preload-local-app/types";
|
||||
import settings from "./settings";
|
||||
import { saveShortcut } from "./shortcuts";
|
||||
import { getWindow, hideAppView, showAppView } from "./window";
|
||||
|
||||
export function emitMutedKeyPress() {
|
||||
export function emitMuteToggle() {
|
||||
const mainWindow = getWindow();
|
||||
if (!mainWindow) {
|
||||
throw new Error("Main window not found");
|
||||
}
|
||||
|
||||
mainWindow.webContents.send("app:on-muted-key-press");
|
||||
mainWindow.webContents.send("app:on-camera-toggle");
|
||||
}
|
||||
|
||||
export function emitCameraToggle() {
|
||||
const mainWindow = getWindow();
|
||||
if (!mainWindow) {
|
||||
throw new Error("Main window not found");
|
||||
}
|
||||
|
||||
mainWindow.webContents.send("app:on-mute-toggle");
|
||||
}
|
||||
|
||||
export default () => {
|
||||
ipcMain.handle("is-development", () => electronIsDev);
|
||||
ipcMain.handle("get-version", () => (electronIsDev ? "dev" : app.getVersion()));
|
||||
|
||||
// app ipc
|
||||
ipcMain.on("app:notify", (event, txt) => {
|
||||
@ -30,6 +41,7 @@ export default () => {
|
||||
ipcMain.handle("local-app:getServers", () => {
|
||||
return (
|
||||
settings.get("servers") || [
|
||||
// TODO: remove this default server
|
||||
{
|
||||
_id: "1",
|
||||
name: "WA Demo",
|
||||
@ -51,8 +63,17 @@ export default () => {
|
||||
return true;
|
||||
});
|
||||
|
||||
ipcMain.handle("local-app:addServer", (event, server: Omit<Server, "_id">) => {
|
||||
ipcMain.handle("local-app:addServer", async (event, server: Omit<Server, "_id">) => {
|
||||
const servers = settings.get("servers") || [];
|
||||
|
||||
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`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return new Error("Invalid server url");
|
||||
}
|
||||
|
||||
const newServer = {
|
||||
...server,
|
||||
_id: `${servers.length + 1}`,
|
||||
@ -70,4 +91,8 @@ export default () => {
|
||||
);
|
||||
return true;
|
||||
});
|
||||
|
||||
ipcMain.handle("local-app:saveShortcut", (event, shortcut, key) => saveShortcut(shortcut, key));
|
||||
|
||||
ipcMain.handle("local-app:getShortcuts", (event) => settings.get("shortcuts") || {});
|
||||
};
|
||||
|
@ -1,12 +1,14 @@
|
||||
import { contextBridge, ipcRenderer, IpcRendererEvent } from "electron";
|
||||
import { SettingsData } from "src/settings";
|
||||
import type { WorkAdventureDesktopApi } from "./types";
|
||||
|
||||
const api: WorkAdventureDesktopApi = {
|
||||
desktop: true,
|
||||
isDevelopment: () => ipcRenderer.invoke("is-development"),
|
||||
getVersion: () => ipcRenderer.invoke("get-version"),
|
||||
notify: (txt: string) => ipcRenderer.send("app:notify", txt),
|
||||
onMutedKeyPress: (callback: (event: IpcRendererEvent) => void) =>
|
||||
ipcRenderer.on("app:on-muted-key-press", callback),
|
||||
onMuteToggle: (callback: (event: IpcRendererEvent) => void) => ipcRenderer.on("app:on-mute-toggle", callback),
|
||||
onCameraToggle: (callback: (event: IpcRendererEvent) => void) => ipcRenderer.on("app:on-camera-toggle", callback),
|
||||
};
|
||||
|
||||
contextBridge.exposeInMainWorld("WorkAdventureDesktopApi", api);
|
||||
|
@ -3,6 +3,8 @@ import type { IpcRendererEvent } from "electron";
|
||||
export type WorkAdventureDesktopApi = {
|
||||
desktop: boolean;
|
||||
isDevelopment: () => Promise<boolean>;
|
||||
getVersion: () => Promise<string>;
|
||||
notify: (txt: string) => void;
|
||||
onMutedKeyPress: (callback: (event: IpcRendererEvent) => void) => void;
|
||||
onMuteToggle: (callback: (event: IpcRendererEvent) => void) => void;
|
||||
onCameraToggle: (callback: (event: IpcRendererEvent) => void) => void;
|
||||
};
|
||||
|
@ -1,14 +1,19 @@
|
||||
import { contextBridge, ipcRenderer } from "electron";
|
||||
import { SettingsData } from "src/settings";
|
||||
import type { Server, WorkAdventureLocalAppApi } from "./types";
|
||||
|
||||
const api: WorkAdventureLocalAppApi = {
|
||||
desktop: true,
|
||||
isDevelopment: () => ipcRenderer.invoke("is-development"),
|
||||
getVersion: () => ipcRenderer.invoke("get-version"),
|
||||
showLocalApp: () => ipcRenderer.invoke("local-app:showLocalApp"),
|
||||
getServers: () => ipcRenderer.invoke("local-app:getServers"),
|
||||
selectServer: (serverId: string) => ipcRenderer.invoke("local-app:selectServer", serverId),
|
||||
addServer: (server: Omit<Server, "_id">) => ipcRenderer.invoke("local-app:addServer", server),
|
||||
removeServer: (serverId: Server["_id"]) => ipcRenderer.invoke("local-app:removeServer", serverId),
|
||||
saveShortcut: (shortcut: keyof SettingsData["shortcuts"], key: string | null) =>
|
||||
ipcRenderer.invoke("local-app:saveShortcut", shortcut, key),
|
||||
getShortcuts: () => ipcRenderer.invoke("local-app:getShortcuts"),
|
||||
};
|
||||
|
||||
contextBridge.exposeInMainWorld("WorkAdventureDesktopApi", api);
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { SettingsData } from "src/settings";
|
||||
|
||||
export type Server = {
|
||||
_id: string;
|
||||
name: string;
|
||||
@ -7,9 +9,12 @@ export type Server = {
|
||||
export type WorkAdventureLocalAppApi = {
|
||||
desktop: boolean;
|
||||
isDevelopment: () => Promise<boolean>;
|
||||
getVersion: () => Promise<string>;
|
||||
showLocalApp: () => Promise<void>;
|
||||
getServers: () => Promise<Server[]>;
|
||||
selectServer: (serverId: string) => Promise<Error | boolean>;
|
||||
addServer: (server: Omit<Server, "_id">) => Promise<Server>;
|
||||
removeServer: (serverId: Server["_id"]) => Promise<boolean>;
|
||||
saveShortcut: (shortcut: keyof SettingsData["shortcuts"], key: string | null) => Promise<void>;
|
||||
getShortcuts: () => Promise<SettingsData["shortcuts"]>;
|
||||
};
|
||||
|
@ -2,10 +2,11 @@ import ElectronLog from "electron-log";
|
||||
import Settings from "electron-settings";
|
||||
import type { Server } from "./preload-local-app/types";
|
||||
|
||||
type SettingsData = {
|
||||
export type SettingsData = {
|
||||
log_level: ElectronLog.LogLevel;
|
||||
auto_launch_enabled: boolean;
|
||||
servers: Server[];
|
||||
shortcuts: Record<"mute_toggle" | "camera_toggle", string | null>;
|
||||
};
|
||||
|
||||
let settings: SettingsData;
|
||||
|
29
desktop/src/shortcuts.ts
Normal file
29
desktop/src/shortcuts.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { globalShortcut } from "electron";
|
||||
import settings, { SettingsData } from "./settings";
|
||||
import { emitCameraToggle, emitMuteToggle } from "./ipc";
|
||||
|
||||
export function loadShortcuts() {
|
||||
globalShortcut.unregisterAll();
|
||||
|
||||
const shortcuts = settings.get("shortcuts");
|
||||
|
||||
// // mute key
|
||||
if (shortcuts?.mute_toggle && shortcuts.mute_toggle.length > 0) {
|
||||
globalShortcut.register(shortcuts.mute_toggle, () => {
|
||||
emitMuteToggle();
|
||||
});
|
||||
}
|
||||
|
||||
if (shortcuts?.camera_toggle && shortcuts.camera_toggle.length > 0) {
|
||||
globalShortcut.register(shortcuts.camera_toggle, () => {
|
||||
emitCameraToggle();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function saveShortcut(shortcut: keyof SettingsData["shortcuts"], key: string | null) {
|
||||
const shortcuts = settings.get("shortcuts") || <SettingsData["shortcuts"]>{};
|
||||
shortcuts[shortcut] = key;
|
||||
settings.set("shortcuts", shortcuts);
|
||||
loadShortcuts();
|
||||
}
|
Loading…
Reference in New Issue
Block a user