app: change how client list is fetched

The old method was that a message would come in via postMessage that
indicates we should send a request to the client-list endpoint to
download a new list. Now, the message that comes via postMessage
contains the list, and the client-list endpoint has been repurposed to
request a new list via postMessage instead of in the web response. This
saves some back-and-forth between processes, and also some needless
conversion to and from a string.
This commit is contained in:
Adam
2024-09-10 04:32:00 +01:00
parent 09e04eb9b9
commit 1375b0a2f0
8 changed files with 89 additions and 97 deletions

View File

File diff suppressed because one or more lines are too long

6
app/dist/assets/index-DpEEoeII.js vendored Normal file
View File

File diff suppressed because one or more lines are too long

2
app/dist/index.html vendored
View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bolt Launcher</title>
<script type="module" crossorigin src="/assets/index-BK0TY0V3.js"></script>
<script type="module" crossorigin src="/assets/index-DpEEoeII.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-ClMLwyz1.css">
</head>
<body>

View File

@@ -1,10 +1,10 @@
<script lang="ts">
import Modal from '$lib/Components/CommonUI/Modal.svelte';
import { bolt } from '$lib/State/Bolt';
import { getNewClientListPromise, savePluginConfig } from '$lib/Util/functions';
import { requestNewClientListPromise, savePluginConfig } from '$lib/Util/functions';
import { type PluginConfig } from '$lib/Util/interfaces';
import { logger } from '$lib/Util/Logger';
import { clientListPromise } from '$lib/Util/store';
import { clientList } from '$lib/Util/store';
let modal: Modal;
@@ -92,15 +92,15 @@
};
// get connected client list
clientListPromise.set(getNewClientListPromise());
$: $clientListPromise.then((x) => {
if (!x.some((x) => x.uid === selectedClientId)) {
requestNewClientListPromise();
$: {
if (!$clientList.some((x) => x.uid === selectedClientId)) {
isClientSelected = false;
}
});
}
// function to start a plugin
const startPlugin = (client: string, id: string, path: string, main: string) => {
const startPlugin = (client: number, id: string, path: string, main: string) => {
const pathWithCorrectSeps: string =
bolt.platform === 'windows' ? path.replaceAll('\\', '/') : path;
const newPath = pathWithCorrectSeps.endsWith(platformFileSep)
@@ -110,28 +110,36 @@
var xml = new XMLHttpRequest();
xml.onreadystatechange = () => {
if (xml.readyState == 4) {
clientListPromise.set(getNewClientListPromise());
requestNewClientListPromise();
logger.info(`Start-plugin status: ${xml.statusText.trim()}`);
}
};
xml.open(
'GET',
'/start-plugin?'.concat(new URLSearchParams({ client, id, path: newPath, main }).toString()),
'/start-plugin?'.concat(
new URLSearchParams({ client: client.toString(), id, path: newPath, main }).toString()
),
true
);
xml.send();
};
// function to stop a plugin, by the client ID and plugin activation ID
const stopPlugin = (client: string, uid: string) => {
const stopPlugin = (client: number, uid: number) => {
var xml = new XMLHttpRequest();
xml.onreadystatechange = () => {
if (xml.readyState == 4) {
clientListPromise.set(getNewClientListPromise());
requestNewClientListPromise();
logger.info(`Stop-plugin status: ${xml.statusText.trim()}`);
}
};
xml.open('GET', '/stop-plugin?'.concat(new URLSearchParams({ client, uid }).toString()), true);
xml.open(
'GET',
'/stop-plugin?'.concat(
new URLSearchParams({ client: client.toString(), uid: uid.toString() }).toString()
),
true
);
xml.send();
};
@@ -143,7 +151,7 @@
// connected clients list
var isClientSelected: boolean = false;
var selectedClientId: string;
var selectedClientId: number;
let pluginConfigDirty: boolean = false;
</script>
@@ -169,31 +177,25 @@
Manage Plugins
</button>
<hr class="p-1 dark:border-slate-700" />
{#await $clientListPromise}
<p>loading...</p>
{:then clients}
{#if clients.length == 0}
<p>(start an RS3 game client with plugins enabled and it will be listed here.)</p>
{:else}
{#each clients as client}
<button
on:click={() => {
selectedClientId = client.uid;
isClientSelected = true;
}}
class="m-1 h-[28px] w-[95%] rounded-lg border-2 {isClientSelected &&
selectedClientId === client.uid
? 'border-black bg-blue-500 text-black'
: 'border-blue-500 text-black dark:text-white'} hover:opacity-75"
>
{client.identity || unnamedClientName}
</button>
<br />
{/each}
{/if}
{:catch}
<p>error</p>
{/await}
{#if $clientList.length == 0}
<p>(start an RS3 game client with plugins enabled and it will be listed here.)</p>
{:else}
{#each $clientList as client}
<button
on:click={() => {
selectedClientId = client.uid;
isClientSelected = true;
}}
class="m-1 h-[28px] w-[95%] rounded-lg border-2 {isClientSelected &&
selectedClientId === client.uid
? 'border-black bg-blue-500 text-black'
: 'border-blue-500 text-black dark:text-white'} hover:opacity-75"
>
{client.identity || unnamedClientName}
</button>
<br />
{/each}
{/if}
</div>
<div class="h-full pt-10">
{#if bolt.hasBoltPlugins}
@@ -286,33 +288,27 @@
<br />
<br />
<hr class="p-1 dark:border-slate-700" />
{#await $clientListPromise}
<p>loading...</p>
{:then clients}
{#each clients as client}
{#if client.uid === selectedClientId}
{#each client.plugins as activePlugin}
{#if Object.keys(bolt.pluginList).includes(activePlugin.id)}
<p>
{bolt.pluginList[activePlugin.id].name ?? activePlugin.id}
<button
class="bg-rose-500 rounded-sm shadow-lg hover:opacity-75"
on:click={() => {
stopPlugin(selectedClientId, activePlugin.uid);
}}
>
<img src="svgs/xmark-solid.svg" class="h-4 w-4" alt="Close" />
</button>
</p>
{:else}
<p>{activePlugin.id}</p>
{/if}
{/each}
{/if}
{/each}
{:catch}
<p>error</p>
{/await}
{#each $clientList as client}
{#if client.uid === selectedClientId}
{#each client.plugins as activePlugin}
{#if Object.keys(bolt.pluginList).includes(activePlugin.id)}
<p>
{bolt.pluginList[activePlugin.id].name ?? activePlugin.id}
<button
class="rounded-sm bg-rose-500 shadow-lg hover:opacity-75"
on:click={() => {
stopPlugin(selectedClientId, activePlugin.uid);
}}
>
<img src="svgs/xmark-solid.svg" class="h-4 w-4" alt="Close" />
</button>
</p>
{:else}
<p>{activePlugin.id}</p>
{/if}
{/each}
{/if}
{/each}
{:catch}
<p>error</p>
{/await}

View File

@@ -1,7 +1,7 @@
import { BoltService } from '$lib/Services/BoltService';
import { bolt } from '$lib/State/Bolt';
import { GlobalState } from '$lib/State/GlobalState';
import { type Direct6Token, type GameClient } from '$lib/Util/interfaces';
import { type Direct6Token } from '$lib/Util/interfaces';
import { logger } from '$lib/Util/Logger';
import { get } from 'svelte/store';
@@ -254,22 +254,17 @@ export function launchHdos(
xml.send();
}
export function getNewClientListPromise(): Promise<GameClient[]> {
return new Promise((resolve, reject) => {
const xml = new XMLHttpRequest();
xml.open('GET', '/list-game-clients', true);
xml.onreadystatechange = () => {
if (xml.readyState == 4) {
if (xml.status == 200 && xml.getResponseHeader('content-type') === 'application/json') {
const dict = JSON.parse(xml.responseText);
resolve(<GameClient[]>dict);
} else {
reject(`error (${xml.responseText})`);
}
export function requestNewClientListPromise(): void {
const xml = new XMLHttpRequest();
xml.open('GET', '/list-game-clients', true);
xml.onreadystatechange = () => {
if (xml.readyState == 4) {
if (xml.status != 200) {
logger.error(`Error requesting client list: ${xml.status}: ${xml.responseText}`);
}
};
xml.send();
});
}
};
xml.send();
}
// TODO: move to BoltService

View File

@@ -38,12 +38,12 @@ export interface Direct6Token {
// "id" is the UUID string of the installed plugin, uid uniquely identifies this specific instance of it
export interface GameClientPlugin {
id: string;
uid: string;
uid: number;
}
// connected game client for plugin management purposes
export interface GameClient {
uid: string;
uid: number;
identity?: string;
plugins: GameClientPlugin[];
}
@@ -83,7 +83,8 @@ interface ExternalUrlMessage {
}
interface GameClientListMessage {
type: 'gameClientListUpdate';
type: 'gameClientList';
clients: GameClient[];
}
export type BoltMessage =

View File

@@ -1,5 +1,5 @@
import type { GameClient } from '$lib/Util/interfaces';
import { writable, type Writable } from 'svelte/store';
// TODO: remove clientListPromise
export const clientListPromise: Writable<Promise<GameClient[]>> = writable();
// TODO: remove clientList
export const clientList: Writable<GameClient[]> = writable([]);

View File

@@ -4,10 +4,9 @@ import { type Session } from '$lib/Services/UserService';
import { Platform, bolt } from '$lib/State/Bolt';
import { GlobalState } from '$lib/State/GlobalState';
import { initConfig } from '$lib/Util/Config';
import { getNewClientListPromise } from '$lib/Util/functions';
import { type BoltMessage } from '$lib/Util/interfaces';
import { logger } from '$lib/Util/Logger';
import { clientListPromise } from '$lib/Util/store';
import { clientList } from '$lib/Util/store';
import AuthApp from '@/AuthApp.svelte';
import BoltApp from '@/BoltApp.svelte';
import { get } from 'svelte/store';
@@ -132,8 +131,9 @@ function addMessageListeners(): void {
xml.send(event.data.url);
break;
}
case 'gameClientListUpdate':
clientListPromise.set(getNewClientListPromise());
case 'gameClientList':
console.log(event.data.clients);
clientList.set(event.data.clients);
break;
default: {
const type = (event.data as { type: string | undefined })?.type ?? 'no type provided';