aboutsummaryrefslogtreecommitdiff
path: root/assets/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'assets/src/network')
-rw-r--r--assets/src/network/channel/connection.ts32
-rw-r--r--assets/src/network/channel/messages/handler.ts93
-rw-r--r--assets/src/network/channel/request.ts2
-rw-r--r--assets/src/network/channel/share.ts8
4 files changed, 126 insertions, 9 deletions
diff --git a/assets/src/network/channel/connection.ts b/assets/src/network/channel/connection.ts
index 52d85d1..6d6f3de 100644
--- a/assets/src/network/channel/connection.ts
+++ b/assets/src/network/channel/connection.ts
@@ -1,4 +1,11 @@
import { Channel, Push, Socket } from "phoenix";
+import {
+ Handler,
+ Handlers,
+ registerTokenHandler,
+ UnregisterHandler,
+} from "./messages/handler";
+import type { AnyMessage } from "./messages/messages";
import { startRequest } from "./request";
import { startShare } from "./share";
import { connectSocket, fetchToken } from "./socket";
@@ -22,6 +29,7 @@ export type Connection = {
channel: Channel | null;
token: string | null;
state: ConnectionState;
+ handlers: Handlers;
type: Type;
};
@@ -30,6 +38,7 @@ const connection: Connection = {
channel: null,
token: null,
state: ConnectionState.CONNECTING_SOCKET,
+ handlers: {},
type: Type.NONE,
};
@@ -55,6 +64,21 @@ export function send(event: string, data: any): Push {
return connection.channel.push(event, data);
}
+export function onWithToken<Message extends AnyMessage>(
+ event: string,
+ token: string | null,
+ handler: Handler<Message>
+): UnregisterHandler {
+ return registerTokenHandler(connection.handlers, event, token, handler);
+}
+
+export function on<Message extends AnyMessage>(
+ event: string,
+ handler: Handler<Message>
+): UnregisterHandler {
+ return onWithToken(event, null, handler);
+}
+
export function getOwnToken(): string {
if (connection.state <= ConnectionState.FETCHING_TOKEN) {
throw new Error("There is no token yet.");
@@ -63,6 +87,14 @@ export function getOwnToken(): string {
return connection.token;
}
+export function getChannel(): Channel {
+ if (connection.state <= ConnectionState.FETCHING_TOKEN) {
+ throw new Error("There is no channel yet.");
+ }
+
+ return connection.channel;
+}
+
function updateState(state: ConnectionState) {
// TODO: Notify state listeners
connection.state = state;
diff --git a/assets/src/network/channel/messages/handler.ts b/assets/src/network/channel/messages/handler.ts
new file mode 100644
index 0000000..5cfe327
--- /dev/null
+++ b/assets/src/network/channel/messages/handler.ts
@@ -0,0 +1,93 @@
+import { getChannel } from "../connection";
+import type { AnyMessage } from "./messages";
+
+export type Handlers = {
+ [event: string]: EventHandler<unknown>;
+};
+
+type EventHandler<Message extends AnyMessage> = {
+ tokenHandler: TokenHandler<Message>;
+ directHandlers: Handler<Message>[];
+};
+
+export type TokenHandler<Message extends AnyMessage> = {
+ [token: string]: Handler<Message>;
+};
+
+export type Handler<Message extends AnyMessage> = (message?: Message) => void;
+
+export type UnregisterHandler = () => void;
+
+export function registerTokenHandler<Message extends AnyMessage>(
+ handlers: Handlers,
+ event: string,
+ token: string | null,
+ handler: Handler<Message>
+): UnregisterHandler {
+ let eventHandler = handlers[event];
+
+ // If this event did not yet have any handlers registered we have to register it
+ if (eventHandler === undefined) {
+ eventHandler = {
+ tokenHandler: {},
+ directHandlers: [],
+ };
+
+ handlers[event] = eventHandler;
+
+ registerNewEvent<Message>(eventHandler, event);
+ }
+
+ let unregister: UnregisterHandler;
+
+ if (token === null) {
+ const directHandlers = eventHandler.directHandlers;
+ directHandlers.push(handler);
+
+ unregister = () => {
+ const index = directHandlers.findIndex(h => h === handler);
+ directHandlers.splice(index, 1);
+ };
+ } else {
+ const tokenHandler = eventHandler.tokenHandler;
+ tokenHandler[token] = handler;
+
+ unregister = () => {
+ delete tokenHandler[token];
+ };
+ }
+
+ return unregister;
+}
+
+function registerNewEvent<Message extends AnyMessage>(
+ eventHandler: EventHandler<Message>,
+ event: string
+) {
+ const callback = (data: Message) => {
+ handleEvent<Message>(eventHandler, data);
+ };
+
+ getChannel().on(event, callback);
+}
+
+function handleEvent<Message extends AnyMessage>(
+ eventHandler: EventHandler<Message>,
+ message: Message
+) {
+ if (message["token"] !== undefined) {
+ const token = message["token"];
+
+ const handler: Handler<Message> = eventHandler.tokenHandler[token];
+
+ if (handler === undefined) {
+ throw new Error("Received message for an unknown token.");
+ }
+
+ handler(message);
+ }
+
+ for (const handler of eventHandler.directHandlers) {
+ handler(message);
+ }
+}
diff --git a/assets/src/network/channel/request.ts b/assets/src/network/channel/request.ts
index 801eee1..dd18aab 100644
--- a/assets/src/network/channel/request.ts
+++ b/assets/src/network/channel/request.ts
@@ -9,6 +9,4 @@ export async function startRequest(connection: Connection) {
getShareToken()
);
connection.channel = requestChannel;
-
- // TODO: Handle incoming messages from the request channel
}
diff --git a/assets/src/network/channel/share.ts b/assets/src/network/channel/share.ts
index 10a34fa..f93e8cb 100644
--- a/assets/src/network/channel/share.ts
+++ b/assets/src/network/channel/share.ts
@@ -8,10 +8,4 @@ export async function startShare(connection: Connection) {
connection.token
);
connection.channel = shareChannel;
-
- shareChannel.on("new_request", onNewRequest);
-}
-
-function onNewRequest(data) {
- requests.addRequest(data);
-}
+} \ No newline at end of file