Skip to content

Commit 793f081

Browse files
authored
Merge pull request #29 from webxdc/delete_devices
Delete devices
2 parents d5e2b28 + 10435f0 commit 793f081

File tree

5 files changed

+89
-15
lines changed

5 files changed

+89
-15
lines changed

backend/app.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,7 @@ export function createFrontend(
5151
});
5252
app.get<{}, Instance[]>("/instances", (req, res) => {
5353
res.json(
54-
Array.from(instances.instances.values()).map((instance) => ({
55-
id: instance.id,
56-
port: instance.port,
57-
url: instance.url,
58-
color: instance.color,
59-
}))
54+
instances.list()
6055
);
6156
});
6257
app.post<{}, Instance>("/instances", (req, res) => {
@@ -69,6 +64,11 @@ export function createFrontend(
6964
color: instance.color,
7065
});
7166
});
67+
app.delete<{id: string}, Instance[]>("/instances/:id", (req, res) => {
68+
instances.delete(parseInt(req.params.id));
69+
res.json(instances.list())
70+
});
71+
7272
app.post<{}, { status: string }>("/clear", (req, res) => {
7373
instances.clear();
7474
res.json({

backend/instance.ts

+30-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Location } from "./location";
77
import { createPeer, InjectExpress } from "./app";
88
import { AppInfo } from "./appInfo";
99
import { getColorForId } from "./color";
10+
import { Instance as FrontendInstance } from '../types/instance';
1011

1112
export type Options = {
1213
basePort: number;
@@ -32,6 +33,7 @@ type RequestInfoMessage = {
3233
class Instance {
3334
id: string;
3435
color: string;
36+
server: any;
3537

3638
constructor(
3739
public app: expressWs.Application,
@@ -44,10 +46,14 @@ class Instance {
4446
}
4547

4648
start() {
47-
this.app.listen(this.port, () => {
49+
this.server = this.app.listen(this.port, () => {
4850
console.log(`Starting webxdc instance at port ${this.port}`);
4951
});
5052
}
53+
54+
close() {
55+
this.server.close()
56+
}
5157
}
5258

5359
export class Instances {
@@ -133,7 +139,10 @@ export class Instances {
133139
parsed.serial,
134140
() => {
135141
return broadcast(wss, JSON.stringify({ type: "clear" }));
136-
}
142+
},
143+
() => {
144+
return broadcast(wss, JSON.stringify({ type: "delete" }));
145+
},
137146
);
138147
} else if (isRequestInfoMessage(parsed)) {
139148
ws.send(
@@ -154,6 +163,16 @@ export class Instances {
154163
return instance;
155164
}
156165

166+
delete(id: number) {
167+
let instance = this.instances.get(id);
168+
if (instance == null) {
169+
throw new Error(`Instance with id ${id} can't be deleted because it does not exist`);
170+
}
171+
instance.close();
172+
this.processor.removeClient(instance.id);
173+
this.instances.delete(id);
174+
}
175+
157176
start() {
158177
for (const instance of this.instances.values()) {
159178
instance.start();
@@ -167,6 +186,15 @@ export class Instances {
167186
onMessage(onMessage: OnMessage) {
168187
this._onMessage = onMessage;
169188
}
189+
190+
list(): FrontendInstance[]{
191+
return Array.from(this.instances.values()).map((instance) => ({
192+
id: instance.id,
193+
port: instance.port,
194+
url: instance.url,
195+
color: instance.color,
196+
}))
197+
}
170198
}
171199

172200
function broadcast(wss: Server<WebSocket>, data: string): boolean {

backend/message.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ type UpdateListenerMulti = (
1212
) => boolean;
1313

1414
type ClearListener = () => boolean;
15+
type DeleteListener = () => boolean;
1516

1617
type Connect = (
1718
updateListener: UpdateListenerMulti,
1819
serial: number,
19-
clearListener?: ClearListener
20+
clearListener?: ClearListener,
21+
deleteListener?: DeleteListener,
2022
) => void;
2123

2224
export type WebXdcMulti = {
@@ -31,12 +33,14 @@ export type OnMessage = (message: Message) => void;
3133
export interface IProcessor {
3234
createClient(id: string): WebXdcMulti;
3335
clear(): void;
36+
removeClient(id: string): void;
3437
}
3538

3639
class Client implements WebXdcMulti {
3740
updateListener: UpdateListenerMulti | null = null;
3841
clearListener: ClearListener | null = null;
3942
updateSerial: number | null = null;
43+
deleteListener: DeleteListener | null = null;
4044

4145
constructor(public processor: Processor, public id: string) {}
4246

@@ -47,7 +51,8 @@ class Client implements WebXdcMulti {
4751
connect(
4852
listener: UpdateListenerMulti,
4953
serial: number,
50-
clearListener: ClearListener = () => true
54+
clearListener: ClearListener = () => true,
55+
deleteListener: DeleteListener = () => true,
5156
): void {
5257
this.processor.onMessage({
5358
type: "connect",
@@ -83,6 +88,8 @@ class Client implements WebXdcMulti {
8388
}
8489
return hasReceived;
8590
};
91+
92+
this.deleteListener = deleteListener;
8693
this.updateListener = updateListener;
8794
this.updateSerial = serial;
8895
this.processor.catchUp(updateListener, serial);
@@ -114,6 +121,14 @@ class Client implements WebXdcMulti {
114121
this.clearListener();
115122
this.processor.clearInstanceIds.add(this.id);
116123
}
124+
125+
// sends a message to the all clients to shut down
126+
delete() {
127+
if ( this.deleteListener == null ) {
128+
return;
129+
}
130+
this.deleteListener()
131+
}
117132
}
118133

119134
class Processor implements IProcessor {
@@ -130,6 +145,12 @@ class Processor implements IProcessor {
130145
return client;
131146
}
132147

148+
removeClient(id: string) {
149+
let client_index = this.clients.findIndex((client) => client.id == id);
150+
this.clients[client_index].delete();
151+
this.clients.splice(client_index, 1);
152+
}
153+
133154
distribute(instanceId: string, update: Update<JsonValue>, descr: string) {
134155
this.currentSerial++;
135156
const receivedUpdate: ReceivedUpdate<JsonValue> = {

frontend/InstanceHeader.tsx

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Component, Show, createMemo, JSX, Accessor } from "solid-js";
2-
import { Flex, Text, Badge, Tooltip, IconButton } from "@hope-ui/solid";
2+
import { Flex, Text, Badge, Tooltip, IconButton, notificationService } from "@hope-ui/solid";
33
import { IoRefreshOutline, IoStop, IoPlay } from "solid-icons/io";
4-
import { FiExternalLink } from "solid-icons/fi";
4+
import { FiExternalLink, FiTrash } from "solid-icons/fi";
55

66
import type { Instance as InstanceData } from "../types/instance";
7-
import { sent, received } from "./store";
7+
import { sent, received, mutateInstances } from "./store";
88
import { Search } from "./Sidebar";
99

1010
const InstanceHeader: Component<{
@@ -19,6 +19,15 @@ const InstanceHeader: Component<{
1919
return sent(props.instance.id);
2020
});
2121

22+
const handleRemoveInstance = async (id: string) => {
23+
let new_instances = await (await fetch(`/instances/${id}`, { method: "DELETE" })).json()
24+
mutateInstances(new_instances);
25+
notificationService.show({
26+
title: `Deleted instance ${id}`,
27+
});
28+
};
29+
30+
2231
const receivedCount = createMemo(() => {
2332
return received(props.instance.id);
2433
});
@@ -92,6 +101,11 @@ const InstanceHeader: Component<{
92101
disabled={!props.isStarted()}
93102
icon={<IoRefreshOutline size={22} color="#000000" />}
94103
/>
104+
<InstanceButton
105+
label="Delete"
106+
onClick={() => handleRemoveInstance(props.instance.id)}
107+
icon={<FiTrash size={22} color="#000000" />}
108+
/>
95109
</Flex>
96110
</Flex>
97111
);

sim/create.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ type InfoMessage = {
1919
info: Info;
2020
};
2121

22-
type Message = UpdatesMessage | ClearMessage | InfoMessage;
22+
type DeleteMessage = {
23+
type: "delete";
24+
};
25+
26+
type Message = UpdatesMessage | ClearMessage | InfoMessage | DeleteMessage;
2327

2428
export type TransportMessageCallback = (message: Message) => void;
2529

@@ -33,7 +37,7 @@ export type Transport = {
3337
address(): string;
3438
name(): string;
3539
setInfo(info: Info): void;
36-
// getInfo(): Promise<Info>;
40+
// getInfo(): Promise<Info>;
3741
};
3842

3943
type Log = (...args: any[]) => void;
@@ -66,6 +70,9 @@ export function createWebXdc(
6670
} else if (isInfoMessage(message)) {
6771
log("info", message.info);
6872
transport.setInfo(message.info);
73+
} else if (isDeleteMessage(message)) {
74+
log("delete");
75+
window.top?.close()
6976
}
7077
});
7178
transport.onConnect(() => {
@@ -94,3 +101,7 @@ function isClearMessage(data: Message): data is ClearMessage {
94101
function isInfoMessage(data: Message): data is InfoMessage {
95102
return data.type === "info";
96103
}
104+
105+
function isDeleteMessage(data: Message): data is InfoMessage {
106+
return data.type === "delete";
107+
}

0 commit comments

Comments
 (0)