From 185677448c6945115a70f2b761f793f53ecc9b86 Mon Sep 17 00:00:00 2001 From: Natalie Bridgers Date: Tue, 5 May 2026 18:19:26 -0500 Subject: [PATCH] popout all(?) widgets --- js/app/src/linking-config.ts | 8 +++ js/app/src/navigation-types.ts | 4 ++ js/app/src/screens/popout-info-widget.tsx | 51 ++++++++++++++++ js/app/src/screens/popout-livestream.tsx | 44 ++++++++++++++ js/app/src/screens/popout-multistream.tsx | 36 ++++++++++++ js/app/src/screens/popout-stream-monitor.tsx | 54 +++++++++++++++++ js/app/src/shell.tsx | 24 ++++++++ .../content/docs/features/live-dashboard.md | 58 +++++++++++++++++++ 8 files changed, 279 insertions(+) create mode 100644 js/app/src/screens/popout-info-widget.tsx create mode 100644 js/app/src/screens/popout-livestream.tsx create mode 100644 js/app/src/screens/popout-multistream.tsx create mode 100644 js/app/src/screens/popout-stream-monitor.tsx create mode 100644 js/docs/src/content/docs/features/live-dashboard.md diff --git a/js/app/src/linking-config.ts b/js/app/src/linking-config.ts index b5c49d7d..e9041dc8 100644 --- a/js/app/src/linking-config.ts +++ b/js/app/src/linking-config.ts @@ -123,6 +123,10 @@ export const SCREEN_PATHS = { InfoWidgetEmbed: "info-widget", LegacyStream: "legacy/:user", DanmuOBS: "widgets/:user/danmu", + PopoutStreamMonitor: "widgets/stream-monitor", + PopoutInfoWidget: "widgets/info", + PopoutMultistream: "widgets/multistream", + PopoutLivestream: "widgets/livestream", } as const; /** @@ -222,6 +226,10 @@ export const streamplaceLinkingOptions: LinkingOptions state.openLoginModal); + const hideSidebar = useStore((x) => x.setSidebarHidden); + const showSidebar = useStore((x) => x.setSidebarUnhidden); + + useEffect(() => { + hideSidebar(); + return () => { + showSidebar(); + }; + }, [showSidebar]); + + if (!isReady) return ; + if (!userProfile) { + openLoginModal({ name: "PopoutInfoWidget" }); + return ; + } + + return ( + + + + + + + + ); +} diff --git a/js/app/src/screens/popout-livestream.tsx b/js/app/src/screens/popout-livestream.tsx new file mode 100644 index 00000000..cb36b9d0 --- /dev/null +++ b/js/app/src/screens/popout-livestream.tsx @@ -0,0 +1,44 @@ +import { + LivestreamProvider, + PlayerProvider, + zero, +} from "@streamplace/components"; +import LivestreamPanel from "components/live-dashboard/livestream-panel"; +import Loading from "components/loading/loading"; +import { useEffect } from "react"; +import { View } from "react-native"; +import { useStore } from "store"; +import { useIsReady, useUserProfile } from "store/hooks"; + +const { flex, p } = zero; + +export default function PopoutLivestream() { + const isReady = useIsReady(); + const userProfile = useUserProfile(); + const openLoginModal = useStore((state) => state.openLoginModal); + const hideSidebar = useStore((x) => x.setSidebarHidden); + const showSidebar = useStore((x) => x.setSidebarUnhidden); + + useEffect(() => { + hideSidebar(); + return () => { + showSidebar(); + }; + }, [showSidebar]); + + if (!isReady) return ; + if (!userProfile) { + openLoginModal({ name: "PopoutLivestream" }); + return ; + } + + return ( + + + + + + + + ); +} diff --git a/js/app/src/screens/popout-multistream.tsx b/js/app/src/screens/popout-multistream.tsx new file mode 100644 index 00000000..83566b77 --- /dev/null +++ b/js/app/src/screens/popout-multistream.tsx @@ -0,0 +1,36 @@ +import { zero } from "@streamplace/components"; +import MultistreamStatus from "components/live-dashboard/multistream-status"; +import Loading from "components/loading/loading"; +import { useEffect } from "react"; +import { View } from "react-native"; +import { useStore } from "store"; +import { useIsReady, useUserProfile } from "store/hooks"; + +const { flex } = zero; + +export default function PopoutMultistream() { + const isReady = useIsReady(); + const userProfile = useUserProfile(); + const openLoginModal = useStore((state) => state.openLoginModal); + const hideSidebar = useStore((x) => x.setSidebarHidden); + const showSidebar = useStore((x) => x.setSidebarUnhidden); + + useEffect(() => { + hideSidebar(); + return () => { + showSidebar(); + }; + }, [showSidebar]); + + if (!isReady) return ; + if (!userProfile) { + openLoginModal({ name: "PopoutMultistream" }); + return ; + } + + return ( + + + + ); +} diff --git a/js/app/src/screens/popout-stream-monitor.tsx b/js/app/src/screens/popout-stream-monitor.tsx new file mode 100644 index 00000000..39f8b409 --- /dev/null +++ b/js/app/src/screens/popout-stream-monitor.tsx @@ -0,0 +1,54 @@ +import { + LivestreamProvider, + PlayerProvider, + zero, +} from "@streamplace/components"; +import StreamMonitor from "components/live-dashboard/stream-monitor"; +import Loading from "components/loading/loading"; +import { useLiveUser } from "hooks/useLiveUser"; +import { useEffect } from "react"; +import { View } from "react-native"; +import { useStore } from "store"; +import { useIsReady, useUserProfile } from "store/hooks"; + +const { flex } = zero; + +function PopoutStreamMonitorInner() { + const isLive = useLiveUser(); + const profile = useUserProfile(); + const hideSidebar = useStore((x) => x.setSidebarHidden); + const showSidebar = useStore((x) => x.setSidebarUnhidden); + + useEffect(() => { + hideSidebar(); + return () => { + showSidebar(); + }; + }, [showSidebar]); + + return ( + + + + ); +} + +export default function PopoutStreamMonitor() { + const isReady = useIsReady(); + const userProfile = useUserProfile(); + const openLoginModal = useStore((state) => state.openLoginModal); + + if (!isReady) return ; + if (!userProfile) { + openLoginModal({ name: "PopoutStreamMonitor" }); + return ; + } + + return ( + + + + + + ); +} diff --git a/js/app/src/shell.tsx b/js/app/src/shell.tsx index 4768de4d..48c9ba87 100644 --- a/js/app/src/shell.tsx +++ b/js/app/src/shell.tsx @@ -60,6 +60,10 @@ import LiveDashboard from "src/screens/live-dashboard"; import MobileGoLive from "src/screens/mobile-go-live"; import MobileStream from "src/screens/mobile-stream"; import MultiScreen from "src/screens/multi"; +import PopoutInfoWidget from "src/screens/popout-info-widget"; +import PopoutLivestream from "src/screens/popout-livestream"; +import PopoutMultistream from "src/screens/popout-multistream"; +import PopoutStreamMonitor from "src/screens/popout-stream-monitor"; import SupportScreen from "src/screens/support"; import { useStore } from "store"; import { @@ -594,6 +598,26 @@ export default function Shell() { component={DanmuOBSScreen} options={{ headerShown: false }} /> + + + +