diff --git a/packages/app/src/pages/live_control/index.jsx b/packages/app/src/pages/live_control/index.jsx
index c307e7f9..41b6af2f 100644
--- a/packages/app/src/pages/live_control/index.jsx
+++ b/packages/app/src/pages/live_control/index.jsx
@@ -32,6 +32,131 @@ const StreamingKeyView = (props) => {
}
+const LivestreamsCategoriesSelector = (props) => {
+ const [categories, setCategories] = React.useState([])
+ const [loading, setLoading] = React.useState(true)
+
+ const loadData = async () => {
+ setLoading(true)
+
+ const categories = await Livestream.getCategories().catch((err) => {
+ console.error(err)
+
+ app.message.error("Failed to load categories")
+
+ return null
+ })
+
+ console.log(`Loaded categories >`, categories)
+
+ setLoading(false)
+
+ if (categories) {
+ setCategories(categories)
+ }
+ }
+
+ React.useEffect(() => {
+ loadData()
+ }, [])
+
+ if (loading) {
+ return
+ }
+
+ return props.updateStreamInfo("category", value)}
+ >
+ {
+ categories.map((category) => {
+ return {category.label}
+ })
+ }
+
+}
+
+const StreamInfoEditor = (props) => {
+ const [streamInfo, setStreamInfo] = React.useState(props.defaultStreamInfo ?? {})
+
+ const updateStreamInfo = (key, value) => {
+ setStreamInfo({
+ ...streamInfo,
+ [key]: value,
+ })
+ }
+
+ const saveStreamInfo = async () => {
+ if (typeof props.onSave === "function") {
+ return await props.onSave(streamInfo)
+ }
+
+ // peform default save
+ const result = await Livestream.updateLivestreamInfo(streamInfo).catch((err) => {
+ console.error(err)
+
+ app.message.error("Failed to update stream info")
+
+ return false
+ })
+
+ if (result) {
+ app.message.success("Stream info updated")
+ }
+
+ if (typeof props.onSaveComplete === "function") {
+ await props.onSaveComplete(result)
+ }
+
+ return result
+ }
+
+ return
+
+
+ Title
+
+
+
updateStreamInfo("title", e.target.value)}
+ />
+
+
+
+
+ Description
+
+
+
updateStreamInfo("description", e.target.value)}
+ />
+
+
+
+
+ Save
+
+
+}
+
export default (props) => {
const [streamInfo, setStreamInfo] = React.useState({})
const [addresses, setAddresses] = React.useState({})
@@ -39,6 +164,19 @@ export default (props) => {
const [isConnected, setIsConnected] = React.useState(false)
const [streamingKey, setStreamingKey] = React.useState(null)
+ const onClickEditInfo = () => {
+ app.ModalController.open(() => {
+ if (result) {
+ app.ModalController.close()
+
+ fetchStreamInfo()
+ }
+ }}
+ />)
+ }
+
const regenerateStreamingKey = async () => {
antd.Modal.confirm({
title: "Regenerate streaming key",
@@ -125,15 +263,35 @@ export default (props) => {
+
+
+ Description
+
+
+
+ {streamInfo?.description ?? "No description"}
+
+
+
Category
- {streamInfo?.category ?? "No category"}
+ {streamInfo?.category?.label ?? "No category"}
+
+
+
}
+ onClick={onClickEditInfo}
+ >
+ Edit info
+
+
diff --git a/packages/app/src/pages/live_control/index.less b/packages/app/src/pages/live_control/index.less
index ce9dda92..3f693d07 100644
--- a/packages/app/src/pages/live_control/index.less
+++ b/packages/app/src/pages/live_control/index.less
@@ -8,7 +8,7 @@
display: flex;
flex-direction: row;
- height: 20vh;
+ height: fit-content;
padding: 15px;
@@ -21,7 +21,7 @@
.preview {
height: 100%;
- max-width: 400px;
+ width: 300px;
img {
width: 100%;
@@ -38,6 +38,7 @@
flex-direction: column;
padding: 20px 0;
+ width: 100%;
.status {
margin-bottom: 20px;
@@ -83,7 +84,7 @@
.title {
display: inline-flex;
flex-direction: row;
-
+
justify-content: space-between;
align-items: center;
@@ -114,8 +115,29 @@
div {
display: inline-flex;
flex-direction: row;
-
+
align-items: center;
justify-content: center;
}
+}
+
+.streamInfoEditor {
+ display: flex;
+ flex-direction: column;
+
+ .field {
+ display: flex;
+ flex-direction: column;
+
+ margin-bottom: 20px;
+
+ .value {
+ margin-top: 5px;
+ margin-left: 20px;
+
+ .ant-select {
+ min-width: 200px;
+ }
+ }
+ }
}
\ No newline at end of file