diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4020bcb..ec84c4e 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,14 +1,11 @@ module.exports = { env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - parser: '@typescript-eslint/parser', - parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, - plugins: ['react-refresh'], + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"], + parser: "@typescript-eslint/parser", + parserOptions: { ecmaVersion: "latest", sourceType: "module" }, + plugins: ["react-refresh"], rules: { - 'react-refresh/only-export-components': 'warn', + "react-refresh/only-export-components": "warn", + "react-hooks/exhaustive-deps": "ignore", }, -} +}; diff --git a/.prettierrc b/.prettierrc index f86d44a..944da1a 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,7 @@ { "tabWidth": 2, "useTabs": false, - "printWidth": 120, + "printWidth": 180, "singleQuote": false, "semi": true } diff --git a/public/images/viewer_example_background.png b/public/images/viewer_example_background.png new file mode 100644 index 0000000..870f3b3 Binary files /dev/null and b/public/images/viewer_example_background.png differ diff --git a/src/App.tsx b/src/App.tsx index 42fa8f9..eded429 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,22 +1,11 @@ import "@styles/App.scss"; import { Navigate, Route, Routes, useSearchParams } from "react-router-dom"; -import useTSRemoteApp, { IClient } from "react-ts5-remote-app-api"; import Viewer from "./Viewer"; import Generator from "./Generator"; export default function App() { const [searchParams] = useSearchParams(); - const { clients, activeConnectionId, currentChannel } = useTSRemoteApp({ - remoteAppPort: parseInt(searchParams.get("remoteAppPort") ?? "5899"), - auth: { - identifier: "de.tealfire.obs", - version: "2.0.0", - name: "TS5 OBS Overlay", - description: "A OBS overlay for TS5 by DerTyp7", - }, - logging: true, - }); return ( @@ -24,17 +13,10 @@ export default function App() { path="/" element={ { - if (client.channel?.id === currentChannel?.id && client.channel.connection.id === activeConnectionId) { - return client; - } - }) as IClient[] - } - channel={currentChannel} /> } /> diff --git a/src/Generator.tsx b/src/Generator.tsx index afe7fb9..3980c4a 100644 --- a/src/Generator.tsx +++ b/src/Generator.tsx @@ -1,11 +1,29 @@ -import React, { ChangeEvent } from "react"; +import React, { ChangeEvent, useRef, useState } from "react"; import "@styles/Generator.scss"; +import Viewer from "./Viewer"; export default function Generator() { - const [outputUrl, setOutputUrl] = React.useState("sdlgkhfldskgjhdkjfghlkdfsjghlkjdshg"); - const copiedTooltipRef = React.useRef(null); + const [outputUrl, setOutputUrl] = useState(new URL(window.location.href).toString()); + const copiedTooltipRef = useRef(null); - const [showChannelName, setShowChannelName] = React.useState(true); + const [remoteAppPort, setRemoteAppPort] = useState(5899); + const [showChannelName, setShowChannelName] = useState(true); + const [hideNonTalking, setHideNonTalking] = useState(false); + const [clientLimit, setClientLimit] = useState(0); + + React.useEffect(() => { + generateUrl(); + }, [remoteAppPort, showChannelName, hideNonTalking, clientLimit]); + + function generateUrl() { + const url = new URL(window.location.href.replace("/generate", "")); + url.searchParams.set("remoteAppPort", remoteAppPort.toString()); + url.searchParams.set("showChannelName", showChannelName.toString()); + url.searchParams.set("hideNonTalking", hideNonTalking.toString()); + url.searchParams.set("clientLimit", clientLimit.toString()); + + setOutputUrl(url.toString()); + } function copy() { navigator.clipboard.writeText(outputUrl); @@ -25,6 +43,10 @@ export default function Generator() { return (
+
+

TS5-OBS-Overlay Generator

+

by DerTyp7

+

{outputUrl} @@ -36,9 +58,9 @@ export default function Generator() { Copied!

-
-
-

Configurations

+
+
+

Configurations

) => { - setShowChannelName(e.target.checked); + setHideNonTalking(e.target.checked); }} /> @@ -66,15 +88,30 @@ export default function Generator() { ) => { - setShowChannelName(e.target.checked); + setClientLimit(parseInt(e.target.value)); }} />
+ +
+ ) => { + setRemoteAppPort(parseInt(e.target.value)); + }} + /> + +
-
s
+
+ +
); diff --git a/src/Viewer.tsx b/src/Viewer.tsx index 1cf6b15..a531660 100644 --- a/src/Viewer.tsx +++ b/src/Viewer.tsx @@ -1,27 +1,42 @@ import "@styles/Viewer.scss"; -import { IChannel, IClient } from "react-ts5-remote-app-api"; +import useTSRemoteApp, { IClient } from "react-ts5-remote-app-api"; export default function Viewer({ - clients, - channel, + remoteAppPort = 5899, showChannelName = false, hideNonTalking = false, clientLimit = 0, }: { - clients: IClient[] | undefined; - channel: IChannel | undefined; + remoteAppPort?: number; showChannelName?: boolean; hideNonTalking?: boolean; clientLimit?: number; }) { + const { clients, activeConnectionId, currentChannel } = useTSRemoteApp({ + remoteAppPort: remoteAppPort, + auth: { + identifier: "de.tealfire.obs", + version: "2.0.0", + name: "TS5 OBS Overlay", + description: "A OBS overlay for TS5 by DerTyp7", + }, + logging: true, + }); + + const currentClients = clients.map((client) => { + if (client.channel?.id === currentChannel?.id && client.channel.connection.id === activeConnectionId) { + return client; + } + }) as IClient[]; + return (
{showChannelName ? (
-

{channel?.properties.name}

+

{currentChannel?.properties.name}

) : null} - {clients?.map((client, i) => { + {currentClients?.map((client, i) => { //* Client limit if (clientLimit != 0 && i >= clientLimit) { return null; @@ -29,10 +44,7 @@ export default function Viewer({ if (client) { //* Non-talking client - if ( - hideNonTalking && - (client.properties.inputMuted || client.properties.outputMuted || client.talkStatus == 0) - ) { + if (hideNonTalking && (client.properties.inputMuted || client.properties.outputMuted || client.talkStatus == 0)) { return null; } @@ -73,16 +85,7 @@ export default function Viewer({ d="M88.62,54.15V64A24.69,24.69,0,0,1,64,88.62a25.26,25.26,0,0,1-8.38-1.46l-7.39,7.39A34,34,0,0,0,64,98.46,34.5,34.5,0,0,0,98.46,64V54.15a4.92,4.92,0,1,1,9.85,0V64a44.31,44.31,0,0,1-39.38,44v10.15H88.62a4.92,4.92,0,0,1,0,9.85H39.38a4.92,4.92,0,1,1,0-9.85H59.08V108A43.3,43.3,0,0,1,41,101.77L21.46,121.31a2.46,2.46,0,0,1-3.54,0L11.62,115a2.46,2.46,0,0,1,0-3.54l94.92-94.92a2.46,2.46,0,0,1,3.54,0l6.31,6.31a2.46,2.46,0,0,1,0,3.54ZM22.92,80.46A43.3,43.3,0,0,1,19.69,64V54.15a4.92,4.92,0,1,1,9.85,0V64a35.94,35.94,0,0,0,1.15,8.69ZM39.38,64V24.62a24.62,24.62,0,0,1,47.77-8.38Z" fill="#d8d8d8" /> - + ) : client.properties.outputMuted ? ( diff --git a/src/styles/Generator.scss b/src/styles/Generator.scss index 00f71c7..71b4b17 100644 --- a/src/styles/Generator.scss +++ b/src/styles/Generator.scss @@ -2,17 +2,6 @@ $breakpoint-1: 760px; $breakpoint-2: 565px; -body { - padding: 0; - margin: 0; - display: flex; - align-items: center; - justify-content: center; - height: 100vh; - width: 100vw; - background-color: #232528; -} - @keyframes tooltipAnimation { 0% { opacity: 0; @@ -25,26 +14,20 @@ body { } .generator { + background-color: #232528; + color: white; + width: 100%; display: flex; + height: 100%; flex-direction: column; align-items: center; - justify-content: center; gap: 50px; - color: white; + box-sizing: border-box; + padding: 50px 0; - button { - background-color: #202024; - color: #fff; - font-weight: bold; - border: 2px solid #31f399; - border-radius: 5px; - padding: 10px 20px; - cursor: pointer; - transition: all 300ms ease-in-out; - &:hover { - background-color: #42d486; - color: #202024; - } + .headline { + text-align: center; + letter-spacing: 1.8px; } .output { @@ -54,7 +37,7 @@ body { justify-content: center; column-gap: 20px; position: relative; - height: 20px; + height: 50px; .url { white-space: nowrap; @@ -98,39 +81,34 @@ body { font-weight: bold; } } - .configuration { + .generatorContent { display: flex; flex-direction: row; align-items: center; justify-content: center; - width: 100%; - flex: 1; + padding: 0 50px; gap: 30px; + width: 100%; + box-sizing: border-box; - h1 { - font-size: 1.2rem; - text-align: center; - } - - .options { + .configurations { display: flex; flex-direction: column; align-items: left; - justify-content: center; - height: 100%; - width: 100%; - border-right: 5px solid rgb(131, 131, 131); gap: 10px; - } - - .viewer { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; height: 100%; - width: 100%; - background-color: #fff; + flex: 1; + } + .preview { + flex: 1; + border: 2px solid #31f39973; + .viewer { + background-image: url("/images/viewer_example_background.png"); + background-repeat: no-repeat; + background-size: cover; + min-height: 500px; + padding: 10px; + } } .option { @@ -200,23 +178,3 @@ body { } } } - -// custom dark themed scrollbar -::-webkit-scrollbar { - width: 5px; - height: 15px; -} - -::-webkit-scrollbar-track { - background: #363638; - border-radius: 10px; -} - -::-webkit-scrollbar-thumb { - background: #31f39973; - border-radius: 10px; -} - -::-webkit-scrollbar-thumb:hover { - background: #48ee95; -} diff --git a/src/styles/Viewer.scss b/src/styles/Viewer.scss index 74ff59e..b7301bc 100644 --- a/src/styles/Viewer.scss +++ b/src/styles/Viewer.scss @@ -2,7 +2,6 @@ display: flex; flex-direction: column; gap: 0 0; - padding: 1rem; font-size: 3rem; .channelNameContainer { diff --git a/src/styles/index.scss b/src/styles/index.scss index b68e07f..d4e7eec 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -2,4 +2,78 @@ font-family: Arial, Helvetica, sans-serif; font-weight: bold; font-size: 1rem; + margin: 0; + padding: 0; +} + +body, +html { + height: 100vh; + width: 100vw; + display: flex; +} + +#root { + min-height: 100%; + width: 100%; +} + +h1 { + font-size: 1.8rem; +} + +h2 { + font-size: 1.5rem; +} + +h3 { + font-size: 1.2rem; +} + +h4 { + font-size: 1.1rem; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: bold; +} + +button { + background-color: #202024; + color: #fff; + font-weight: bold; + border: 2px solid #31f399; + border-radius: 5px; + padding: 10px 20px; + cursor: pointer; + transition: all 300ms ease-in-out; + &:hover { + background-color: #42d486; + color: #202024; + } +} + +// custom dark themed scrollbar +::-webkit-scrollbar { + width: 5px; + height: 15px; +} + +::-webkit-scrollbar-track { + background: #363638; + border-radius: 10px; +} + +::-webkit-scrollbar-thumb { + background: #31f39973; + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:hover { + background: #48ee95; }