From bd5ecc1ab0ccc026ae0bc9a19a364f2aaa15a3bc Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 24 Jul 2023 00:46:00 +0200 Subject: [PATCH 1/5] outsource to react hook --- src/App.tsx | 48 +++---------------------------- src/hooks/useTSRemoteApp.tsx | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 44 deletions(-) create mode 100644 src/hooks/useTSRemoteApp.tsx diff --git a/src/App.tsx b/src/App.tsx index 0186e1f..0a7f10e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,53 +5,13 @@ import { useEffect, useState } from "react"; import Viewer from "./Viewer"; import { useSearchParams } from "react-router-dom"; import { TS5ConnectionHandler } from "@handlers/teamspeak/connectionHandler"; +import useTSRemoteApp from "./hooks/useTSRemoteApp"; export default function App() { const [searchParams] = useSearchParams(); - - const [clients, setClients] = useState([]); - const [channels, setChannels] = useState([]); - const [connections, setConnections] = useState([]); - const [activeConnectionId, setActiveConnectionId] = useState(1); - - const [currentConnection, setCurrentConnection] = useState(undefined); - const [currentChannel, setCurrentChannel] = useState(undefined); - const [currentClient, setCurrentClient] = useState(undefined); - - function setCurrentStates() { - const currentConnection = connections.find((connection) => connection.id === activeConnectionId); - setCurrentConnection(currentConnection); - - if (currentConnection) { - const currentClient = clients.find((client) => client.id === currentConnection.clientId); - setCurrentClient(currentClient); - if (currentClient) { - const currentChannel = channels.find((channel) => channel.id === currentClient.channel?.id); - setCurrentChannel(currentChannel); - if (currentChannel) { - return currentChannel; - } - } - } - } - - useEffect(() => { - const remoteAppPort = searchParams.get("remoteAppPort"); - - console.log(searchParams.get("hideNonTalking")); - const tsConnection: ITS5ConnectionHandler = new TS5ConnectionHandler( - parseInt(remoteAppPort ?? "5899"), - setConnections, - setChannels, - setClients, - setActiveConnectionId - ); - tsConnection.connect(); - }, []); - - useEffect(() => { - setCurrentStates(); - }, [clients, channels, connections, activeConnectionId]); + const { clients, channels, connections, activeConnectionId, currentChannel } = useTSRemoteApp({ + remoteAppPort: 5899, + }); return (
diff --git a/src/hooks/useTSRemoteApp.tsx b/src/hooks/useTSRemoteApp.tsx new file mode 100644 index 0000000..d80f0fe --- /dev/null +++ b/src/hooks/useTSRemoteApp.tsx @@ -0,0 +1,56 @@ +import { TS5ConnectionHandler } from "@/handlers/teamspeak/connectionHandler"; +import { IClient, IChannel, IConnection, ITS5ConnectionHandler } from "@/interfaces/teamspeak"; +import { useEffect, useState } from "react"; + +export default function useTSRemoteApp({ remoteAppPort = 5899 }: { remoteAppPort: number }) { + const [clients, setClients] = useState([]); + const [channels, setChannels] = useState([]); + const [connections, setConnections] = useState([]); + const [activeConnectionId, setActiveConnectionId] = useState(1); + + const [currentConnection, setCurrentConnection] = useState(undefined); + const [currentChannel, setCurrentChannel] = useState(undefined); + const [currentClient, setCurrentClient] = useState(undefined); + + function setCurrentStates() { + const currentConnection = connections.find((connection) => connection.id === activeConnectionId); + setCurrentConnection(currentConnection); + + if (currentConnection) { + const currentClient = clients.find((client) => client.id === currentConnection.clientId); + setCurrentClient(currentClient); + if (currentClient) { + const currentChannel = channels.find((channel) => channel.id === currentClient.channel?.id); + setCurrentChannel(currentChannel); + if (currentChannel) { + return currentChannel; + } + } + } + } + + useEffect(() => { + const tsConnection: ITS5ConnectionHandler = new TS5ConnectionHandler( + remoteAppPort, + setConnections, + setChannels, + setClients, + setActiveConnectionId + ); + tsConnection.connect(); + }, []); + + useEffect(() => { + setCurrentStates(); + }, [clients, channels, connections, activeConnectionId]); + + return { + clients, + channels, + connections, + activeConnectionId, + currentConnection, + currentChannel, + currentClient, + }; +} From da518bbd1e68faa65a961a7f658b0838d519b41f Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 24 Jul 2023 00:47:55 +0200 Subject: [PATCH 2/5] add searchparams port --- src/App.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 0a7f10e..5a4d5a9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,16 +1,14 @@ /* eslint-disable react-hooks/exhaustive-deps */ import "@styles/App.scss"; -import { IChannel, IClient, IConnection, ITS5ConnectionHandler } from "@interfaces/teamspeak"; -import { useEffect, useState } from "react"; +import { IClient } from "@interfaces/teamspeak"; import Viewer from "./Viewer"; import { useSearchParams } from "react-router-dom"; -import { TS5ConnectionHandler } from "@handlers/teamspeak/connectionHandler"; import useTSRemoteApp from "./hooks/useTSRemoteApp"; export default function App() { const [searchParams] = useSearchParams(); - const { clients, channels, connections, activeConnectionId, currentChannel } = useTSRemoteApp({ - remoteAppPort: 5899, + const { clients, activeConnectionId, currentChannel } = useTSRemoteApp({ + remoteAppPort: parseInt(searchParams.get("remoteAppPort") ?? "5899"), }); return ( From 793ae71186a9a110cd32c36e83fcaf3ac97c0522 Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 24 Jul 2023 00:50:08 +0200 Subject: [PATCH 3/5] better readability --- src/hooks/useTSRemoteApp.tsx | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/hooks/useTSRemoteApp.tsx b/src/hooks/useTSRemoteApp.tsx index d80f0fe..5bd2c86 100644 --- a/src/hooks/useTSRemoteApp.tsx +++ b/src/hooks/useTSRemoteApp.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import { TS5ConnectionHandler } from "@/handlers/teamspeak/connectionHandler"; import { IClient, IChannel, IConnection, ITS5ConnectionHandler } from "@/interfaces/teamspeak"; import { useEffect, useState } from "react"; @@ -12,23 +13,6 @@ export default function useTSRemoteApp({ remoteAppPort = 5899 }: { remoteAppPort const [currentChannel, setCurrentChannel] = useState(undefined); const [currentClient, setCurrentClient] = useState(undefined); - function setCurrentStates() { - const currentConnection = connections.find((connection) => connection.id === activeConnectionId); - setCurrentConnection(currentConnection); - - if (currentConnection) { - const currentClient = clients.find((client) => client.id === currentConnection.clientId); - setCurrentClient(currentClient); - if (currentClient) { - const currentChannel = channels.find((channel) => channel.id === currentClient.channel?.id); - setCurrentChannel(currentChannel); - if (currentChannel) { - return currentChannel; - } - } - } - } - useEffect(() => { const tsConnection: ITS5ConnectionHandler = new TS5ConnectionHandler( remoteAppPort, @@ -41,7 +25,17 @@ export default function useTSRemoteApp({ remoteAppPort = 5899 }: { remoteAppPort }, []); useEffect(() => { - setCurrentStates(); + const currentConnection = connections.find((connection) => connection.id === activeConnectionId); + setCurrentConnection(currentConnection); + + if (currentConnection) { + const currentClient = clients.find((client) => client.id === currentConnection.clientId); + setCurrentClient(currentClient); + if (currentClient) { + const currentChannel = channels.find((channel) => channel.id === currentClient.channel?.id); + setCurrentChannel(currentChannel); + } + } }, [clients, channels, connections, activeConnectionId]); return { From 728afd5d1c1973fc034ab76d30e7b07ec58f090f Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 24 Jul 2023 01:59:57 +0200 Subject: [PATCH 4/5] remove handler from this package and use seperate package --- package-lock.json | 245 +++++++++++++- package.json | 1 + src/App.tsx | 3 +- src/handlers/teamspeak/connectionHandler.ts | 132 -------- src/handlers/teamspeak/dataHandler.ts | 205 ------------ src/handlers/teamspeak/messageHandler.ts | 197 ----------- src/hooks/useTSRemoteApp.tsx | 50 --- src/interfaces/teamspeak.ts | 341 -------------------- 8 files changed, 233 insertions(+), 941 deletions(-) delete mode 100644 src/handlers/teamspeak/connectionHandler.ts delete mode 100644 src/handlers/teamspeak/dataHandler.ts delete mode 100644 src/handlers/teamspeak/messageHandler.ts delete mode 100644 src/hooks/useTSRemoteApp.tsx delete mode 100644 src/interfaces/teamspeak.ts diff --git a/package-lock.json b/package-lock.json index 4ea785e..beeeeb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "ts5-obs-overlay", - "version": "0.0.0", + "version": "1.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ts5-obs-overlay", - "version": "0.0.0", + "version": "1.1.3", "dependencies": { "@types/node": "^20.4.2", "jest": "^29.6.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.1", + "react-ts5-remote-app-api": "^1.0.2", "sass": "^1.63.6" }, "devDependencies": { @@ -586,6 +587,26 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", @@ -1489,6 +1510,52 @@ "node": ">=14" } }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.2.tgz", + "integrity": "sha512-0ghSOCMcA7fl1JM+0gYRf+Q/HWyg+zg7/gDSc+fRLmlJWcW5K1I+CLRzaRhXf4Y3DRyPnnDo4M2ktw+a6JcDEg==", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1514,7 +1581,7 @@ "version": "1.3.62", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.62.tgz", "integrity": "sha512-J58hWY+/G8vOr4J6ZH9hLg0lMSijZtqIIf4HofZezGog/pVX6sJyBJ40dZ1ploFkDIlWTWvJyqtpesBKS73gkQ==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "engines": { "node": ">=10" @@ -1704,6 +1771,26 @@ "node": ">=10" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, "node_modules/@types/babel__core": { "version": "7.20.1", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", @@ -1741,6 +1828,11 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -1800,13 +1892,13 @@ "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.14.tgz", - "integrity": "sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==", - "dev": true, + "version": "18.2.15", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.15.tgz", + "integrity": "sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==", + "devOptional": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -1826,7 +1918,7 @@ "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", - "dev": true + "devOptional": true }, "node_modules/@types/semver": { "version": "7.5.0", @@ -2130,7 +2222,6 @@ "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -2147,6 +2238,14 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2222,6 +2321,11 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2567,6 +2671,11 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2584,7 +2693,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true + "devOptional": true }, "node_modules/debug": { "version": "4.3.4", @@ -2629,6 +2738,14 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.4.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", @@ -2952,6 +3069,11 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -4217,6 +4339,11 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -4734,6 +4861,34 @@ "react-dom": ">=16.8" } }, + "node_modules/react-ts5-remote-app-api": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/react-ts5-remote-app-api/-/react-ts5-remote-app-api-1.0.2.tgz", + "integrity": "sha512-AkeU4rTD9jdDF026J50DtYVLfzo+CAi7tBZUkTDOHjLXqmUeXoffHEGIL11rq3Q2y9/1C8lNsYmXbkgp/XZpWw==", + "dependencies": { + "@rollup/plugin-typescript": "^11.1.2", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rollup-plugin-typescript-paths": "^1.4.0", + "ts-node": "^10.9.1", + "tslib": "^2.6.0" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-ts5-remote-app-api/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4834,7 +4989,7 @@ "version": "3.26.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz", "integrity": "sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==", - "dev": true, + "devOptional": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -4846,6 +5001,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-typescript-paths": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript-paths/-/rollup-plugin-typescript-paths-1.4.0.tgz", + "integrity": "sha512-6EgeLRjTVmymftEyCuYu91XzY5XMB5lR0YrJkeT0D7OG2RGSdbNL+C/hfPIdc/sjMa9Sl5NLsxIr6C/+/5EUpA==", + "peerDependencies": { + "typescript": ">=3.4" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5121,11 +5284,53 @@ "node": ">=8.0" } }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "devOptional": true }, "node_modules/tsutils": { "version": "3.21.0", @@ -5178,7 +5383,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5225,6 +5429,11 @@ "punycode": "^2.1.0" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", @@ -5407,6 +5616,14 @@ "node": ">=12" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index c06b74f..b107385 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.1", + "react-ts5-remote-app-api": "^1.0.2", "sass": "^1.63.6" }, "devDependencies": { diff --git a/src/App.tsx b/src/App.tsx index 5a4d5a9..b16e6b0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,8 @@ /* eslint-disable react-hooks/exhaustive-deps */ import "@styles/App.scss"; -import { IClient } from "@interfaces/teamspeak"; import Viewer from "./Viewer"; import { useSearchParams } from "react-router-dom"; -import useTSRemoteApp from "./hooks/useTSRemoteApp"; +import useTSRemoteApp, { IClient } from "react-ts5-remote-app-api"; export default function App() { const [searchParams] = useSearchParams(); diff --git a/src/handlers/teamspeak/connectionHandler.ts b/src/handlers/teamspeak/connectionHandler.ts deleted file mode 100644 index 6d6ad6a..0000000 --- a/src/handlers/teamspeak/connectionHandler.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { IAuthSenderPayload, IChannel, IClient, IConnection, ITS5ConnectionHandler, ITS5DataHandler, ITS5MessageHandler } from "@interfaces/teamspeak"; -import { TS5DataHandler } from "./dataHandler"; -import { TS5MessageHandler } from "./messageHandler"; -import Logger from "@/utils/logger"; - - -// Establish connection to TS5 client -// Main class -export class TS5ConnectionHandler implements ITS5ConnectionHandler { - ws: WebSocket; // Websocket connection to TS5 client - authenticated = false; // Is the connection authenticated? - remoteAppPort: number; // Port of TS5 client - dataHandler: ITS5DataHandler; // Handles data/lists and states - messageHandler: ITS5MessageHandler; // Handles messages received from TS5 client - - constructor( - // Port of TS5 client - remoteAppPort: number, - - // State setters for dataHandler - setConnections: React.Dispatch>, - setChannels: React.Dispatch>, - setClients: React.Dispatch>, - setActiveConnectionStateId: React.Dispatch>, - ) { - - - // Create websocket connection to TS5 client - this.remoteAppPort = remoteAppPort; - this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`); - - // Create dataHandler and messageHandler - this.dataHandler = new TS5DataHandler(setConnections, setChannels, setClients); - this.messageHandler = new TS5MessageHandler(this.ws, this.dataHandler, setActiveConnectionStateId); - } - - reconnect() { - Logger.log("Reconnecting...") - this.ws.close(); - - this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`); - - this.dataHandler.clearAll(); - this.authenticated = false; - this.connect(); - } - - // Connect to TS5 client - connect() { - Logger.log('Connecting to TS5 client...'); - - // Create authentication payload - const initalPayload: IAuthSenderPayload = { - type: "auth", - payload: { - identifier: "de.tealfire.obs", - version: "1.1.3", - name: "TS5 OBS Overlay", - description: "A OBS overlay for TS5 by DerTyp876", - content: { - apiKey: localStorage.getItem("apiKey") ?? "", - }, - }, - }; - - this.ws.onopen = () => { - // Send authentication payload to TS5 client - this.ws.send(JSON.stringify(initalPayload)); - Logger.wsSent(initalPayload); - }; - - this.ws.onclose = (event) => { - Logger.log("WebSocket connection closed", event); - - // If the connection was closed before authentication, remove the API key from local storage - // OBS weirdly caches the localstorage and is very stubborn about clearing it (even when clicken "Clear Cache") - if (!this.authenticated) { - Logger.log("WebSocket connection closed before authentication"); - localStorage.removeItem("apiKey"); - } - - setTimeout(() => { - this.reconnect(); - }, 2000); - }; - - // Handle messages received from TS5 client - // See TS5MessageHandler class - this.ws.onmessage = (event) => { - const data = JSON.parse(event.data); - - Logger.wsReceived(data) - - switch (data.type) { - case "auth": - this.messageHandler.handleAuthMessage(data); - this.authenticated = true; - break; - case "clientMoved": - this.messageHandler.handleClientMovedMessage(data); - break; - case "clientPropertiesUpdated": - this.messageHandler.handleClientPropertiesUpdatedMessage(data); - break; - case "talkStatusChanged": - this.messageHandler.handleTalkStatusChangedMessage(data); - break; - case "serverPropertiesUpdated": - this.messageHandler.handleServerPropertiesUpdatedMessage(data); - break; - case "connectStatusChanged": - this.messageHandler.handleConnectStatusChangedMessage(data); - break; - case "clientSelfPropertyUpdated": - this.messageHandler.handleClientSelfPropertyUpdatedMessage(data); - break; - case "channels": - this.messageHandler.handleChannelsMessage(data); - break; - default: - Logger.log(`No handler for event type: ${data.type}`); - break; - } - }; - } -} - - - - - - diff --git a/src/handlers/teamspeak/dataHandler.ts b/src/handlers/teamspeak/dataHandler.ts deleted file mode 100644 index 1df8df7..0000000 --- a/src/handlers/teamspeak/dataHandler.ts +++ /dev/null @@ -1,205 +0,0 @@ -import Logger from "@/utils/logger"; -import { IConnection, IChannel, IClient, ITS5DataHandler } from "@interfaces/teamspeak"; - - -/** - * Handles data received from TS5 client (list of connections, channels and clients) - * Updates the states of App.tsx - */ -export class TS5DataHandler implements ITS5DataHandler { - // Local lists of connections, channels and clients - // These lists are used to keep track of the data, independent of the App.tsx state - localConnections: IConnection[]; - localChannels: IChannel[]; - localClients: IClient[]; - - // State setters for App.tsx - setConnections: React.Dispatch>; - setChannels: React.Dispatch>; - setClients: React.Dispatch>; - - constructor( - // State setters for App.tsx - setConnections: React.Dispatch>, - setChannels: React.Dispatch>, - setClients: React.Dispatch> - ) { - this.setConnections = setConnections; - this.setChannels = setChannels; - this.setClients = setClients; - - this.localConnections = []; - this.localChannels = []; - this.localClients = []; - } - - // Update App.tsx states - private updateConnectionsState() { - this.setConnections([...this.localConnections]); - } - - private updateChannelsState() { - this.setChannels([...this.localChannels]); - } - - private updateClientsState() { - this.setClients([...this.localClients]); - } - - // Clear all data - clearAll() { - this.localConnections = []; - this.localChannels = []; - this.localClients = []; - - this.updateConnectionsState(); - this.updateChannelsState(); - this.updateClientsState(); - } - - // Add data to local lists and update states - addConnection(connection: IConnection) { - Logger.log("Adding connection...", connection) - - const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id); - - if (existingConnection == undefined) { - this.localConnections.push(connection); - this.updateConnectionsState(); - Logger.log("Connection added") - } else { - Logger.log("Connection already exists") - } - } - - addChannel(channel: IChannel) { - Logger.log("Adding channel...", channel) - const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id); - - if (existingChannel == undefined) { - this.localChannels.push(channel); - this.updateChannelsState(); - Logger.log("Channel added") - } else { - Logger.log("Channel already exists") - } - } - - addClient(client: IClient) { - Logger.log("Adding client...", client) - const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id); - - if (existingClient == undefined) { - this.localClients.push(client); - this.updateClientsState(); - Logger.log("Client added") - } else { - Logger.log("Client already exists") - } - } - - // Update data in local lists and update states - updateConnection(connection: IConnection) { - Logger.log("Updating connection...", connection) - const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id); - - if (existingConnection !== undefined) { - this.localConnections[this.localConnections.indexOf(existingConnection)] = connection; - this.updateConnectionsState(); - Logger.log("Connection updated") - } else { - Logger.log("Connection does not exist") - } - } - - updateChannel(channel: IChannel) { - Logger.log("Updating channel...", channel) - const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id); - - if (existingChannel !== undefined) { - this.localChannels[this.localChannels.indexOf(existingChannel)] = channel; - this.updateChannelsState(); - Logger.log("Channel updated") - } else { - Logger.log("Channel does not exist") - } - } - - updateClient(client: IClient) { - Logger.log("Updating client...", client) - const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id); - - if (existingClient !== undefined) { - this.localClients[this.localClients.indexOf(existingClient)] = client; - this.updateClientsState(); - Logger.log("Client updated") - } else { - Logger.log("Client does not exist") - } - } - - // Remove data from local lists and update states - removeConnection(connection: IConnection) { - Logger.log("Removing connection...", connection) - const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id); - - if (existingConnection !== undefined) { - this.localConnections.splice(this.localConnections.indexOf(existingConnection), 1); - - // Remove all channels and clients associated with the connection - this.localChannels = this.localChannels.filter((localChannel: IChannel) => localChannel.connection.id !== connection.id); - this.localClients = this.localClients.filter((localClient: IClient) => localClient.channel?.connection.id !== connection.id); - - this.updateChannelsState(); - this.updateClientsState(); - this.updateConnectionsState(); - Logger.log("Connection removed") - } else { - Logger.log("Connection does not exist") - } - } - - removeChannel(channel: IChannel) { - Logger.log("Removing channel...", channel) - const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id); - - if (existingChannel !== undefined) { - this.localChannels.splice(this.localChannels.indexOf(existingChannel), 1); - - // Remove all clients associated with the channel - this.localClients = this.localClients.filter((localClient: IClient) => localClient.channel?.id !== channel.id); - - this.updateClientsState(); - this.updateChannelsState(); - Logger.log("Channel removed") - } else { - Logger.log("Channel does not exist") - } - } - - removeClient(client: IClient) { - Logger.log("Removing client...", client) - const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id); - - if (existingClient !== undefined) { - this.localClients.splice(this.localClients.indexOf(existingClient), 1); - this.updateClientsState(); - Logger.log("Client removed") - } else { - Logger.log("Client does not exist") - } - } - - // Helper functions - getConnectionById(id: number): IConnection | undefined { - return this.localConnections.find((connection: IConnection) => connection.id === id); - } - - getChannelById(id: number, connectionId: number): IChannel | undefined { - return this.localChannels.find((channel: IChannel) => channel.id === id && channel.connection?.id === connectionId); - } - - getClientById(id: number, connectionId: number): IClient | undefined { - return this.localClients.find((client: IClient) => client.id === id && client.channel?.connection.id === connectionId); - } -} \ No newline at end of file diff --git a/src/handlers/teamspeak/messageHandler.ts b/src/handlers/teamspeak/messageHandler.ts deleted file mode 100644 index 3e5dd41..0000000 --- a/src/handlers/teamspeak/messageHandler.ts +++ /dev/null @@ -1,197 +0,0 @@ -import Logger from "@/utils/logger"; -import { IChannelInfos, IConnection, IChannel, IAuthMessage, IClientInfo, IClientMovedMessage, IClient, IClientPropertiesUpdatedMessage, ITalkStatusChangedMessage, IClientSelfPropertyUpdatedMessage, IServerPropertiesUpdatedMessage, IConnectStatusChangedMessage, IChannelsMessage, ITS5MessageHandler, ITS5DataHandler } from "@interfaces/teamspeak"; - -// Handle incoming messages from TS5 client -export class TS5MessageHandler implements ITS5MessageHandler { - ws: WebSocket; - dataHandler: ITS5DataHandler; - - setActiveConnectionStateId: React.Dispatch>; - activeConnectionId = 0; - - constructor(ws: WebSocket, dataHandler: ITS5DataHandler, setActiveConnectionStateId: React.Dispatch>) { - this.ws = ws; - this.dataHandler = dataHandler; - this.setActiveConnectionStateId = setActiveConnectionStateId; - } - - setActiveConnection(connectionId: number) { - this.activeConnectionId = connectionId; - this.setActiveConnectionStateId(connectionId); - } - - parseChannelInfos(channelInfos: IChannelInfos, connection: IConnection) { - channelInfos.rootChannels.forEach((channel: IChannel) => { - this.dataHandler.addChannel({ ...channel, connection: connection }); - - if (channelInfos) { - if (channelInfos.subChannels !== null && channel.id in channelInfos.subChannels) { - channelInfos.subChannels[channel.id].forEach((subChannel: IChannel) => { - this.dataHandler.addChannel({ ...subChannel, connection: connection }); - }); - } - } - }); - } - - // This message is sent by the TS5 server when the client is connected - // It contains the initial data - handleAuthMessage(data: IAuthMessage) { - localStorage.setItem("apiKey", data.payload.apiKey); - - // Process auth payload and add initial data - data.payload.connections.forEach((connection: IConnection) => { - this.dataHandler.addConnection(connection); - - // Add channels - if (connection.channelInfos !== undefined) { - this.parseChannelInfos(connection.channelInfos, connection); - } - - // Add clients - connection.clientInfos?.forEach((clientInfo: IClientInfo) => { - const clientChannel: IChannel | undefined = this.dataHandler.getChannelById(clientInfo.channelId, connection.id); - - if (clientChannel !== undefined) { - this.dataHandler.addClient({ - id: clientInfo.id, - talkStatus: 0, - channel: { ...clientChannel, connection: connection }, - properties: clientInfo.properties, - }); - } - }); - }); - } - - // This message is sent by the TS5 server when a client moves a channel OR joins/leaves the server - handleClientMovedMessage(data: IClientMovedMessage) { - const client: IClient | undefined = this.dataHandler.getClientById(data.payload.clientId, data.payload.connectionId); - - - //* This gets called when we are connecting to the server and the new clients get loaded - if (+data.payload.oldChannelId == 0) { // Create new client(when connecting to server) - //set timout to wait for channels to be created - setTimeout(() => { - const newChannel = this.dataHandler.getChannelById(data.payload.newChannelId, data.payload.connectionId); - if (newChannel !== undefined) { - this.dataHandler.addClient( - { - id: data.payload.clientId, - talkStatus: 0, - channel: newChannel, - properties: data.payload.properties, - }); - Logger.ts(`New Client found (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`) - } - }, 2000); - - } else {//* This gets called when a client moves a channel OR joins/leaves the server - const newChannel: IChannel | undefined = this.dataHandler.getChannelById(data.payload.newChannelId, data.payload.connectionId); - - if (newChannel === undefined || newChannel.id === 0) { - Logger.ts(`Client left (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`) - if (client !== undefined) { - this.dataHandler.removeClient(client); - } - return; - } - - if (client !== undefined) { // Client already exists - Logger.ts(`Client moved (${client.channel.connection.id} - ${client.id} - ${client.properties.nickname})`) - - this.dataHandler.updateClient({ - ...client, - channel: newChannel, - }); - - } else { // Client does not exist - // Client joined - Logger.ts(`Client joined (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`) - - this.dataHandler.addClient( - { - id: data.payload.clientId, - talkStatus: 0, - channel: newChannel, - properties: data.payload.properties, - } - ); - } - } - } - - handleClientPropertiesUpdatedMessage(data: IClientPropertiesUpdatedMessage) { - const client: IClient | undefined = this.dataHandler.getClientById(data.payload.clientId, data.payload.connectionId); - - if (client !== undefined) { - this.dataHandler.updateClient({ - ...client, - properties: data.payload.properties, - }); - } - } - - handleTalkStatusChangedMessage(data: ITalkStatusChangedMessage) { - const client: IClient | undefined = this.dataHandler.getClientById(data.payload.clientId, data.payload.connectionId); - - if (client !== undefined) { - this.dataHandler.updateClient({ - ...client, - talkStatus: data.payload.status, - }); - } - - // console.log(this.dataHandler.localConnections) - // console.log(this.dataHandler.localChannels) - // console.log(this.dataHandler.localClients) - - } - handleClientSelfPropertyUpdatedMessage(data: IClientSelfPropertyUpdatedMessage) { - const connection: IConnection | undefined = this.dataHandler.getConnectionById(this.activeConnectionId); - - if (data.payload.flag == "inputHardware" || connection == undefined) { // sadly thats the only way to detect if a server is active or not - this.setActiveConnection(data.payload.connectionId); - } - } - - handleServerPropertiesUpdatedMessage(data: IServerPropertiesUpdatedMessage) { - const connection: IConnection | undefined = this.dataHandler.getConnectionById(data.payload.connectionId); - - if (connection !== undefined) { // Update existing connection - this.dataHandler.updateConnection({ - ...connection, - properties: data.payload.properties, - }); - } - } - - handleConnectStatusChangedMessage(data: IConnectStatusChangedMessage) { - if (data.payload.status === 0) { // Disconnected from server - const connection: IConnection | undefined = this.dataHandler.getConnectionById(data.payload.connectionId); - - if (connection !== undefined) { - this.dataHandler.removeConnection(connection); - } - } - - // Status 1-3 are the connection steps (connecting, authenticating, etc.) (i guess) - - if (data.payload.status === 4) { // Connected to server - this.dataHandler.addConnection({ - id: data.payload.connectionId, - clientId: data.payload.info.clientId, - }); - } - } - - handleChannelsMessage(data: IChannelsMessage) { - // Wait a bit for the connection to be added - setTimeout(() => { - const connection: IConnection | undefined = this.dataHandler.getConnectionById(data.payload.connectionId); - if (connection !== undefined) { - this.parseChannelInfos(data.payload.info, connection); - } - }, 1000); - } -} \ No newline at end of file diff --git a/src/hooks/useTSRemoteApp.tsx b/src/hooks/useTSRemoteApp.tsx deleted file mode 100644 index 5bd2c86..0000000 --- a/src/hooks/useTSRemoteApp.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { TS5ConnectionHandler } from "@/handlers/teamspeak/connectionHandler"; -import { IClient, IChannel, IConnection, ITS5ConnectionHandler } from "@/interfaces/teamspeak"; -import { useEffect, useState } from "react"; - -export default function useTSRemoteApp({ remoteAppPort = 5899 }: { remoteAppPort: number }) { - const [clients, setClients] = useState([]); - const [channels, setChannels] = useState([]); - const [connections, setConnections] = useState([]); - const [activeConnectionId, setActiveConnectionId] = useState(1); - - const [currentConnection, setCurrentConnection] = useState(undefined); - const [currentChannel, setCurrentChannel] = useState(undefined); - const [currentClient, setCurrentClient] = useState(undefined); - - useEffect(() => { - const tsConnection: ITS5ConnectionHandler = new TS5ConnectionHandler( - remoteAppPort, - setConnections, - setChannels, - setClients, - setActiveConnectionId - ); - tsConnection.connect(); - }, []); - - useEffect(() => { - const currentConnection = connections.find((connection) => connection.id === activeConnectionId); - setCurrentConnection(currentConnection); - - if (currentConnection) { - const currentClient = clients.find((client) => client.id === currentConnection.clientId); - setCurrentClient(currentClient); - if (currentClient) { - const currentChannel = channels.find((channel) => channel.id === currentClient.channel?.id); - setCurrentChannel(currentChannel); - } - } - }, [clients, channels, connections, activeConnectionId]); - - return { - clients, - channels, - connections, - activeConnectionId, - currentConnection, - currentChannel, - currentClient, - }; -} diff --git a/src/interfaces/teamspeak.ts b/src/interfaces/teamspeak.ts deleted file mode 100644 index 5f50673..0000000 --- a/src/interfaces/teamspeak.ts +++ /dev/null @@ -1,341 +0,0 @@ -// Classes -export interface ITS5ConnectionHandler { - ws: WebSocket; - authenticated: boolean; - remoteAppPort: number; - dataHandler: ITS5DataHandler; - messageHandler: ITS5MessageHandler; - reconnect(): void; - connect(): void; -} - -export interface ITS5DataHandler { - localConnections: IConnection[]; - localChannels: IChannel[]; - localClients: IClient[]; - setConnections: React.Dispatch>; - setChannels: React.Dispatch>; - setClients: React.Dispatch>; - clearAll(): void; - addConnection(connection: IConnection): void; - addChannel(channel: IChannel): void; - addClient(client: IClient): void; - updateConnection(connection: IConnection): void; - updateChannel(channel: IChannel): void; - updateClient(client: IClient): void; - removeConnection(connection: IConnection): void; - removeChannel(channel: IChannel): void; - removeClient(client: IClient): void; - getConnectionById(id: number): IConnection | undefined; - getChannelById(id: number, connectionId: number): IChannel | undefined; - getClientById(id: number, connectionId: number): IClient | undefined; -} - -export interface ITS5MessageHandler { - ws: WebSocket; - dataHandler: ITS5DataHandler; - setActiveConnectionStateId: React.Dispatch>; - activeConnectionId: number; - setActiveConnection(connectionId: number): void; - parseChannelInfos(channelInfos: IChannelInfos, connection: IConnection): void; - handleAuthMessage(data: IAuthMessage): void; - handleClientMovedMessage(data: IClientMovedMessage): void; - handleClientPropertiesUpdatedMessage(data: IClientPropertiesUpdatedMessage): void; - handleTalkStatusChangedMessage(data: ITalkStatusChangedMessage): void; - handleClientSelfPropertyUpdatedMessage(data: IClientSelfPropertyUpdatedMessage): void; - handleServerPropertiesUpdatedMessage(data: IServerPropertiesUpdatedMessage): void; - handleConnectStatusChangedMessage(data: IConnectStatusChangedMessage): void; - handleChannelsMessage(data: IChannelsMessage): void; -} - -// Remote App -export interface IAuthSenderPayload { - type: "auth"; - payload: { - identifier: string; - version: string; - name: string; - description: string; - content: { - apiKey: string; - }; - }; -} - -export interface IClient { - id: number; - talkStatus: number; - channel: IChannel; - properties: IClientProperties; -} - -export interface IChannel { - id: number; - connection: IConnection; - order: string; - parentId: string; - properties: IChannelProperties; -} - -export interface IConnection { - channelInfos?: IChannelInfos; - clientId: number; - clientInfos?: IClientInfo[]; - id: number; - properties?: IServerProperties; -} - - -export interface IChannelProperties { - bannerGfxUrl: string; - bannerMode: number; - codec: number; - codecIsUnencrypted: boolean; - codecLatencyFactor: number; - codecQuality: number; - deleteDelay: number; - description: string; - flagAreSubscribed: boolean; - flagDefault: boolean; - flagMaxclientsUnlimited: boolean; - flagMaxfamilyclientsInherited: boolean; - flagMaxfamilyclientsUnlimited: boolean; - flagPassword: boolean; - flagPermanent: boolean; - flagSemiPermanent: boolean; - forcedSilence: boolean; - iconId: number; - maxclients: number; - maxfamilyclients: number; - name: string; - namePhonetic: string; - neededTalkPower: number; - order: string; - permissionHints: number; - storageQuota: number; - topic: string; - uniqueIdentifier: string; -} - - -export interface IChannelInfos { - rootChannels: IChannel[]; - subChannels: { [key: number]: IChannel[] }; -} - -export interface IClientInfo { - channelId: number; - id: number; - properties: IClientProperties; -} - -export interface IClientProperties { - away: boolean; - awayMessage: string; - badges: string; - channelGroupId: string; - channelGroupInheritedChannelId: string; - country: string; - created: number; - databaseId: string; - defaultChannel: string; - defaultChannelPassword: string; - defaultToken: string; - description: string; - flagAvatar: string; - flagTalking: boolean; - iconId: number; - idleTime: number; - inputDeactivated: boolean; - inputHardware: boolean; - inputMuted: boolean; - integrations: string; - isChannelCommander: boolean; - isMuted: boolean; - isPrioritySpeaker: boolean; - isRecording: boolean; - isTalker: boolean; - lastConnected: number; - metaData: string; - monthBytesDownloaded: number; - monthBytesUploaded: number; - myteamspeakAvatar: string; - myteamspeakId: string; - neededServerQueryViewPower: number; - nickname: string; - nicknamePhonetic: string; - outputHardware: boolean; - outputMuted: boolean; - outputOnlyMuted: boolean; - permissionHints: number; - platform: string; - serverGroups: string; - serverPassword: string; - signedBadges: string; - talkPower: number; - talkRequest: number; - talkRequestMsg: string; - totalBytesDownloaded: number; - totalBytesUploaded: number; - totalConnections: number; - type: number; - uniqueIdentifier: string; - unreadMessages: number; - userTag: string; - version: string; - volumeModificator: number; -} - -export interface IServerProperties { - antiFloodPointsNeededCommandBlock: number; - antiFloodPointsNeededIpBlock: number; - antiFloodPointsNeededPluginBlock: number; - antiFloodPointsTickReduce: number; - askForPrivilegeKeyAfterNickname: boolean; - askForPrivilegeKeyForChannelCreation: boolean; - askForPrivilegeKeyForModify: boolean; - awayMessage: string; - badges: string; - channelGroupId: string; - channelGroupInheritedChannelId: string; - clientType: number; - connectionBandwidthReceived: number; - connectionBandwidthSent: number; - connectionClientIp: string; - connectionConnectedTime: number; - connectionFiletransferBandwidthReceived: number; - connectionFiletransferBandwidthSent: number; - connectionPacketloss: number; - connectionPing: number; - connectionPacketsReceived: number; - connectionPacketsSent: number; - connectionPort: number; - connectionQueryBandwidthReceived: number; - connectionQueryBandwidthSent: number; - connectionServerIp: string; - connectionServerPort: number; - connectionThrottleBandwidthReceived: number; - connectionThrottleBandwidthSent: number; - country: string; - created: number; - defaultChannel: string; - defaultChannelPassword: string; - defaultServerGroup: string; - defaultToken: string; - flagAvatar: string; - iconId: number; - inputHardware: boolean; - inputMuted: boolean; - isChannelCommander: boolean; - isMuted: boolean; - isPrioritySpeaker: boolean; - isRecording: boolean; - isTalker: boolean; - isTts: boolean; - metaData: string; - monthBytesDownloaded: number; - monthBytesUploaded: number; - myteamspeakAvatar: string; - myteamspeakId: string; - neededServerQueryViewPower: number; - nickname: string; - nicknamePhonetic: string; - outputHardware: boolean; - outputMuted: boolean; - outputOnlyMuted: boolean; - permissionHints: number; - platform: string; - serverPassword: string; - signedBadges: string; - talkPower: number; - talkRequest: number; - talkRequestMsg: string; - totalBytesDownloaded: number; - totalBytesUploaded: number; - totalConnections: number; - type: number; - uniqueIdentifier: string; - unreadMessages: number; - userTag: string; - version: string; - volumeModificator: number; -} - - -export interface IClientPropertiesUpdatedMessage { - type: "clientPropertiesUpdated"; - payload: { - clientId: number; - connectionId: number; - properties: IClientProperties; - }; -} - -export interface IClientMovedMessage { - type: "clientMoved"; - payload: { - properties: IClientProperties; - clientId: number; - connectionId: number; - newChannelId: number; - oldChannelId: number; - type: number; - visibility: number; - }; -} - -export interface ITalkStatusChangedMessage { - type: "talkStatusChanged"; - payload: { - clientId: number; - connectionId: number; - isWhisper: boolean; - status: number; - }; -} - -export interface IClientSelfPropertyUpdatedMessage { - type: "clientSelfPropertyUpdated"; - payload: { - connectionId: number; - flag: string; - newValue: boolean; - oldValue: boolean; - }; -} - -export interface IAuthMessage { - type: "auth"; - payload: { - apiKey: string; - connections: IConnection[]; - }; -} - -export interface IServerPropertiesUpdatedMessage { - type: "serverPropertiesUpdated"; - payload: { - connectionId: number; - properties: IServerProperties; - }; -} - -export interface IConnectStatusChangedMessage { - type: "connectStatusChanged"; - payload: { - connectionId: number; - error: number; - info: { - clientId: number; - } - status: number; - }; -} - -export interface IChannelsMessage { - type: "channels"; - payload: { - connectionId: number; - info: IChannelInfos - } -} \ No newline at end of file From 85872712838d741aee90f9bacc3f8fe65845b078 Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 24 Jul 2023 02:33:21 +0200 Subject: [PATCH 5/5] change version to 1.2.0 --- package-lock.json | 8 ++++---- package.json | 4 ++-- src/Viewer.tsx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index beeeeb7..70fbbce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.1", - "react-ts5-remote-app-api": "^1.0.2", + "react-ts5-remote-app-api": "^1.0.5", "sass": "^1.63.6" }, "devDependencies": { @@ -4862,9 +4862,9 @@ } }, "node_modules/react-ts5-remote-app-api": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/react-ts5-remote-app-api/-/react-ts5-remote-app-api-1.0.2.tgz", - "integrity": "sha512-AkeU4rTD9jdDF026J50DtYVLfzo+CAi7tBZUkTDOHjLXqmUeXoffHEGIL11rq3Q2y9/1C8lNsYmXbkgp/XZpWw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/react-ts5-remote-app-api/-/react-ts5-remote-app-api-1.0.5.tgz", + "integrity": "sha512-9eOoOYBbHBG8PFzyi4nzDJiP+IHk781AvdQ7Xe/72TPsf5XgvUbtjRVkhPjT0Kz9qSOUhof14+BjfcQQpHKIcA==", "dependencies": { "@rollup/plugin-typescript": "^11.1.2", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", diff --git a/package.json b/package.json index b107385..af04c6e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ts5-obs-overlay", "private": true, - "version": "1.1.3", + "version": "1.2.0", "type": "module", "scripts": { "dev": "vite", @@ -15,7 +15,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.1", - "react-ts5-remote-app-api": "^1.0.2", + "react-ts5-remote-app-api": "^1.0.5", "sass": "^1.63.6" }, "devDependencies": { diff --git a/src/Viewer.tsx b/src/Viewer.tsx index b3148e4..1cf6b15 100644 --- a/src/Viewer.tsx +++ b/src/Viewer.tsx @@ -1,5 +1,5 @@ -import { IChannel, IClient } from "@interfaces/teamspeak"; import "@styles/Viewer.scss"; +import { IChannel, IClient } from "react-ts5-remote-app-api"; export default function Viewer({ clients,