diff --git a/packages/app/src/pages/live_control/index.jsx b/packages/app/src/pages/live_control/index.jsx new file mode 100644 index 00000000..5903e7e8 --- /dev/null +++ b/packages/app/src/pages/live_control/index.jsx @@ -0,0 +1,147 @@ +import React from "react" +import * as antd from "antd" +import { Icons } from "components/Icons" + +import "./index.less" + +const StreamingKeyView = (props) => { + const [streamingKeyVisibility, setStreamingKeyVisibility] = React.useState(false) + + const toogleVisibility = (to) => { + setStreamingKeyVisibility(to ?? !streamingKeyVisibility) + } + + return
+ {streamingKeyVisibility ? + <> + toogleVisibility()} /> + + {props.streamingKey ?? "No streaming key available"} + + : +
toogleVisibility()} + > + + Click to show key +
+ } +
+} + +export default (props) => { + const [streamInfo, setStreamInfo] = React.useState(null) + + const [isConnected, setIsConnected] = React.useState(false) + const [targetServer, setTargetServer] = React.useState("No available server") + + const [streamingKey, setStreamingKey] = React.useState(null) + + const checkStreamingKey = async () => { + const result = await app.api.withEndpoints("main").get.streamingKey().catch((error) => { + console.error(error) + antd.message.error(error.message) + + return null + }) + + if (result) { + setStreamingKey(result.key) + } + } + + const regenerateStreamingKey = async () => { + antd.Modal.confirm({ + title: "Regenerate streaming key", + content: "Are you sure you want to regenerate the streaming key? After this, all other generated keys will be deleted.", + onOk: async () => { + const result = await app.api.withEndpoints("main").post.regenerateStreamingKey().catch((error) => { + console.error(error) + antd.message.error(error.message) + + return null + }) + + if (result) { + setStreamingKey(result.key) + } + } + }) + } + + React.useEffect(() => { + checkStreamingKey() + }, []) + + return
+
+
+ +
+ +
+
+ : } + > + {isConnected ? "Connected" : "Disconnected"} + +
+
+ + Title + +

+ {streamInfo?.title ?? "No title"} +

+
+ +
+ + Category + +

+ {streamInfo?.category ?? "No category"} +

+
+
+
+ +
+
+

Emission

+ +
+ Ingestion URL + + + {targetServer} + +
+ +
+
+
+ Streaming key +
+
+ regenerateStreamingKey()}> + + Regenerate + +
+
+ +
+ +
+
+
+ +
+

Additional options

+
+
+
+} \ No newline at end of file diff --git a/packages/app/src/pages/live_control/index.less b/packages/app/src/pages/live_control/index.less new file mode 100644 index 00000000..bf0fe451 --- /dev/null +++ b/packages/app/src/pages/live_control/index.less @@ -0,0 +1,121 @@ +.streamingControlPanel { + display: flex; + flex-direction: column; + + transition: all 0.3s ease-in-out; + + .header { + display: flex; + flex-direction: row; + + height: 20vh; + + padding: 15px; + + border: 1px solid var(--border-color); + border-radius: 12px; + + margin-bottom: 20px; + + transition: all 0.3s ease-in-out; + + .preview { + height: 100%; + max-width: 400px; + + img { + width: 100%; + height: 100%; + + border-radius: 12px; + } + + margin-right: 40px; + } + + .details { + display: inline-flex; + flex-direction: column; + + padding: 20px 0; + + .status { + margin-bottom: 20px; + } + } + } + + .config { + display: flex; + + padding: 0 40px; + + transition: all 0.3s ease-in-out; + + code { + padding: 5px 8px; + font-size: 1rem; + + background-color: var(--background-color-accent); + color: var(--text-color); + + border-radius: 8px; + + font-family: "DM Mono", monospace; + + user-select: all; + } + + .panel { + display: flex; + flex-direction: column; + + margin-right: 50px; + + .content { + display: flex; + flex-direction: column; + + margin: 20px 20px 20px 0; + + width: 100%; + + .title { + display: inline-flex; + flex-direction: row; + + justify-content: space-between; + align-items: center; + + width: 100%; + margin-bottom: 8px; + } + } + } + } + +} + +.streamingKeyString { + display: inline-flex; + flex-direction: row; + + align-items: center; + justify-content: center; + + color: var(--text-color); + + svg { + font-size: 1.5rem; + + cursor: pointer; + } + + div { + display: inline-flex; + flex-direction: row; + + align-items: center; + justify-content: center; + } +} \ No newline at end of file diff --git a/packages/app/src/pages/streaming_control/index.jsx b/packages/app/src/pages/streaming_control/index.jsx deleted file mode 100755 index c54a38e9..00000000 --- a/packages/app/src/pages/streaming_control/index.jsx +++ /dev/null @@ -1,176 +0,0 @@ -import React from "react" -import * as antd from "antd" -import { Icons } from "components/Icons" - -import "./index.less" - -const StreamingKeyView = (props) => { - const [streamingKeyVisibility, setStreamingKeyVisibility] = React.useState(false) - - const toogleVisibility = (to) => { - setStreamingKeyVisibility(to ?? !streamingKeyVisibility) - } - - return
- {streamingKeyVisibility ? - <> - toogleVisibility()} /> -

- {props.streamingKey ?? "No streaming key available"} -

- : - <> - toogleVisibility()} /> - Show key - - } -
-} - -export default (props) => { - const [isConnected, setIsConnected] = React.useState(false) - const [targetServer, setTargetServer] = React.useState("No available server") - - const [streamingKey, setStreamingKey] = React.useState(null) - const [serverTier, setServerTier] = React.useState(null) - - const checkStreamingKey = async () => { - const result = await app.api.withEndpoints("main").get.streamingKey().catch((error) => { - console.error(error) - antd.message.error(error.message) - - return null - }) - - if (result) { - setStreamingKey(result.key) - } - } - - const checkTagetServer = async () => { - const result = await app.api.withEndpoints("main").get.targetStreamingServer() - - if (result) { - const targetServer = `${result.protocol}://${result.address}:${result.port}/${result.space}` - setTargetServer(targetServer) - } - } - - const regenerateStreamingKey = async () => { - antd.Modal.confirm({ - title: "Regenerate streaming key", - content: "Are you sure you want to regenerate the streaming key? After this, all other generated keys will be deleted.", - onOk: async () => { - const result = await app.api.withEndpoints("main").post.regenerateStreamingKey().catch((error) => { - console.error(error) - antd.message.error(error.message) - - return null - }) - - if (result) { - setStreamingKey(result.key) - } - } - }) - } - - React.useEffect(() => { - checkStreamingKey() - checkTagetServer() - // TODO: Use UserTier controller to check streaming service tier - // by now, we just use a fixed value - setServerTier("basic") - }, []) - - return
-
-

Connection Status

- -
- : } - > - {isConnected ? "Connected" : "Disconnected"} - -
-
- -
-

Stream information

- -
-
- - Title -
-
- -
-
- -
-
- - Category -
- -
- - - -
-
-
- -
-

Server info

- -
-
- - Server Address -
-
-

- {targetServer} -

-
-
- -
-
- - Streaming Key -
-
- -
-
- regenerateStreamingKey()}> - - Regenerate - -
-
- -
-
- - Usage Tier -
-
- - {serverTier} - -
-
-
-
-} \ No newline at end of file diff --git a/packages/app/src/pages/streaming_control/index.less b/packages/app/src/pages/streaming_control/index.less deleted file mode 100755 index c128686c..00000000 --- a/packages/app/src/pages/streaming_control/index.less +++ /dev/null @@ -1,36 +0,0 @@ -.streamingControlPanel { - display: inline-flex; - flex-direction: column; - - .info { - display: flex; - flex-direction: column; - - margin-bottom: 10px; - - .label { - - } - - .value { - margin-left: 10px; - font-family: "DM Mono", monospace; - - h4 { - // select all text - user-select: all; - margin: 0; - } - } - } - - > div { - margin-bottom: 20px; - } -} - -.streamingKeyString { - display: inline-flex; - flex-direction: row; - align-items: center; -} \ No newline at end of file