From 4afdfd8f33b9f4d25d739fb5e8df1467f78f958b Mon Sep 17 00:00:00 2001 From: duckietm Date: Fri, 10 Apr 2026 09:26:50 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=86=95=20YoutubeTV=20Broadcasting=20in=20?= =?UTF-8?q?rooms=20!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/index.ts | 1 + src/api/youtube/YouTubeRoomState.ts | 4 ++ src/api/youtube/index.ts | 1 + .../NavigatorRoomSettingsMiscTabView.tsx | 58 +++++++++++++++++++ .../NavigatorRoomSettingsView.tsx | 6 +- src/components/toolbar/ToolbarView.tsx | 26 +++++++-- src/components/toolbar/YouTubePlayerView.tsx | 13 +++-- 7 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 src/api/youtube/YouTubeRoomState.ts create mode 100644 src/api/youtube/index.ts create mode 100644 src/components/navigator/views/room-settings/NavigatorRoomSettingsMiscTabView.tsx diff --git a/src/api/index.ts b/src/api/index.ts index 7089277..0f11ac4 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -26,3 +26,4 @@ export * from './room/widgets'; export * from './user'; export * from './utils'; export * from './wired'; +export * from './youtube'; diff --git a/src/api/youtube/YouTubeRoomState.ts b/src/api/youtube/YouTubeRoomState.ts new file mode 100644 index 0000000..364bf19 --- /dev/null +++ b/src/api/youtube/YouTubeRoomState.ts @@ -0,0 +1,4 @@ +let _youtubeEnabled = false; + +export const getYoutubeRoomEnabled = () => _youtubeEnabled; +export const setYoutubeRoomEnabled = (enabled: boolean) => { _youtubeEnabled = enabled; }; diff --git a/src/api/youtube/index.ts b/src/api/youtube/index.ts new file mode 100644 index 0000000..f8e540f --- /dev/null +++ b/src/api/youtube/index.ts @@ -0,0 +1 @@ +export * from './YouTubeRoomState'; diff --git a/src/components/navigator/views/room-settings/NavigatorRoomSettingsMiscTabView.tsx b/src/components/navigator/views/room-settings/NavigatorRoomSettingsMiscTabView.tsx new file mode 100644 index 0000000..5d151d3 --- /dev/null +++ b/src/components/navigator/views/room-settings/NavigatorRoomSettingsMiscTabView.tsx @@ -0,0 +1,58 @@ +import { YouTubeRoomSettingsComposer, YouTubeRoomSettingsEvent } from '@nitrots/nitro-renderer'; +import { FC, useState } from 'react'; +import { getYoutubeRoomEnabled, IRoomData, LocalizeText, SendMessageComposer, setYoutubeRoomEnabled } from '../../../../api'; +import { useMessageEvent } from '../../../../hooks'; + +interface NavigatorRoomSettingsMiscTabViewProps +{ + roomData: IRoomData; +} + +export const NavigatorRoomSettingsMiscTabView: FC = props => +{ + const { roomData = null } = props; + const [ youtubeEnabled, setYoutubeEnabled ] = useState(getYoutubeRoomEnabled()); + const [ cooldown, setCooldown ] = useState(false); + + useMessageEvent(YouTubeRoomSettingsEvent, event => + { + setYoutubeEnabled(event.getParser().youtubeEnabled); + }); + + const toggleYouTube = (enabled: boolean) => + { + if (cooldown) return; + setYoutubeEnabled(enabled); + setYoutubeRoomEnabled(enabled); + SendMessageComposer(new YouTubeRoomSettingsComposer(enabled)); + setCooldown(true); + setTimeout(() => setCooldown(false), 300); + }; + + return ( + <> +
+
{ LocalizeText('product.type.other') }
+
+
+
+
+
+
📺 YouTube TV
+
Allow YouTube video broadcasting in this room
+
+ +
+
+
+ + ); +}; diff --git a/src/components/navigator/views/room-settings/NavigatorRoomSettingsView.tsx b/src/components/navigator/views/room-settings/NavigatorRoomSettingsView.tsx index 29b7f85..2db729f 100644 --- a/src/components/navigator/views/room-settings/NavigatorRoomSettingsView.tsx +++ b/src/components/navigator/views/room-settings/NavigatorRoomSettingsView.tsx @@ -7,6 +7,7 @@ import { NavigatorRoomSettingsAccessTabView } from './NavigatorRoomSettingsAcces import { NavigatorRoomSettingsBasicTabView } from './NavigatorRoomSettingsBasicTabView'; import { NavigatorRoomSettingsModTabView } from './NavigatorRoomSettingsModTabView'; import { NavigatorRoomSettingsRightsTabView } from './NavigatorRoomSettingsRightsTabView'; +import { NavigatorRoomSettingsMiscTabView } from './NavigatorRoomSettingsMiscTabView'; import { NavigatorRoomSettingsVipChatTabView } from './NavigatorRoomSettingsVipChatTabView'; const TABS: string[] = [ @@ -14,7 +15,8 @@ const TABS: string[] = [ 'navigator.roomsettings.tab.2', 'navigator.roomsettings.tab.3', 'navigator.roomsettings.tab.4', - 'navigator.roomsettings.tab.5' + 'navigator.roomsettings.tab.5', + 'product.type.other' ]; export const NavigatorRoomSettingsView: FC<{}> = props => @@ -205,6 +207,8 @@ export const NavigatorRoomSettingsView: FC<{}> = props => } { (currentTab === TABS[4]) && } + { (currentTab === TABS[5]) && + } ); diff --git a/src/components/toolbar/ToolbarView.tsx b/src/components/toolbar/ToolbarView.tsx index 1788b76..3e7b98d 100644 --- a/src/components/toolbar/ToolbarView.tsx +++ b/src/components/toolbar/ToolbarView.tsx @@ -1,7 +1,7 @@ -import { CreateLinkEvent, Dispose, DropBounce, EaseOut, GetSessionDataManager, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait } from '@nitrots/nitro-renderer'; +import { CreateLinkEvent, Dispose, DropBounce, EaseOut, GetSessionDataManager, JumpBy, Motions, NitroToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait, YouTubeRoomSettingsEvent } from '@nitrots/nitro-renderer'; import { AnimatePresence, motion } from 'framer-motion'; -import { FC, useState } from 'react'; -import { GetConfigurationValue, MessengerIconState, OpenMessengerChat, VisitDesktop } from '../../api'; +import { FC, useEffect, useState } from 'react'; +import { GetConfigurationValue, MessengerIconState, OpenMessengerChat, setYoutubeRoomEnabled, VisitDesktop } from '../../api'; import { Flex, LayoutAvatarImageView, LayoutItemCountView } from '../../common'; import { useAchievements, useFriends, useInventoryUnseenTracker, useMessageEvent, useMessenger, useNitroEvent, useSessionInfo } from '../../hooks'; import { ToolbarItemView } from './ToolbarItemView'; @@ -13,6 +13,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => const { isInRoom } = props; const [ isMeExpanded, setMeExpanded ] = useState(false); const [ useGuideTool, setUseGuideTool ] = useState(false); + const [ youtubeEnabled, setYoutubeEnabled ] = useState(false); const { userFigure = null } = useSessionInfo(); const { getFullCount = 0 } = useInventoryUnseenTracker(); const { getTotalUnseen = 0 } = useAchievements(); @@ -20,6 +21,20 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => const { iconState = MessengerIconState.HIDDEN } = useMessenger(); const isMod = GetSessionDataManager().isModerator; + useMessageEvent(YouTubeRoomSettingsEvent, event => + { + const enabled = event.getParser().youtubeEnabled; + setYoutubeEnabled(enabled); + setYoutubeRoomEnabled(enabled); + }); + + useEffect(() => { + if (!isInRoom) { + setYoutubeEnabled(false); + setYoutubeRoomEnabled(false); + } + }, [isInRoom]); + const openYouTubePlayer = () => { window.dispatchEvent(new CustomEvent('youtube:toggle')); @@ -71,7 +86,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => return ( <> - + { youtubeEnabled && } { isMeExpanded && ( )} @@ -101,7 +116,8 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => { isInRoom && CreateLinkEvent('camera/toggle') } /> } - + { youtubeEnabled && + } { isMod && CreateLinkEvent('mod-tools/toggle') } /> } { isMod && diff --git a/src/components/toolbar/YouTubePlayerView.tsx b/src/components/toolbar/YouTubePlayerView.tsx index 9b1507e..029b36f 100644 --- a/src/components/toolbar/YouTubePlayerView.tsx +++ b/src/components/toolbar/YouTubePlayerView.tsx @@ -1,7 +1,7 @@ -import { ControlYoutubeDisplayPlaybackMessageComposer, YouTubeRoomBroadcastEvent, YouTubeRoomPlayComposer, YouTubeRoomWatchersEvent, YouTubeRoomWatchingComposer } from "@nitrots/nitro-renderer"; +import { ControlYoutubeDisplayPlaybackMessageComposer, YouTubeRoomBroadcastEvent, YouTubeRoomPlayComposer, YouTubeRoomSettingsEvent, YouTubeRoomWatchersEvent, YouTubeRoomWatchingComposer } from "@nitrots/nitro-renderer"; import { FC, useEffect, useRef, useState } from "react"; import YouTube from "react-youtube"; -import { GetRoomSession, GetSessionDataManager, LocalizeText, SendMessageComposer, YoutubeVideoPlaybackStateEnum } from "../../api"; +import { GetRoomSession, getYoutubeRoomEnabled, GetSessionDataManager, LocalizeText, SendMessageComposer, YoutubeVideoPlaybackStateEnum } from "../../api"; import { NitroCardContentView, NitroCardHeaderView, NitroCardView, LayoutAvatarImageView } from "../../common"; import { useFurnitureYoutubeWidget, useMessageEvent } from "../../hooks"; @@ -36,14 +36,17 @@ export const YouTubePlayerView: FC<{}> = () => { const [history, setHistory] = useState([]); const [showVolumeSlider, setShowVolumeSlider] = useState(true); const playerRef = useRef(null); - const { objectId: youtubeObjectId, videoId: roomVideoId, currentVideoState, hasControl } = useFurnitureYoutubeWidget(); - const [spectators, setSpectators] = useState< { id: number; name: string; look: string }[] >([]); const [broadcastVideo, setBroadcastVideo] = useState(""); const [broadcastSender, setBroadcastSender] = useState(""); const [broadcastPlaylist, setBroadcastPlaylist] = useState([]); const [watcherIds, setWatcherIds] = useState>(new Set()); + const [youtubeEnabled, setYoutubeEnabled] = useState(getYoutubeRoomEnabled()); + + useMessageEvent(YouTubeRoomSettingsEvent, event => { + setYoutubeEnabled(event.getParser().youtubeEnabled); + }); useMessageEvent(YouTubeRoomBroadcastEvent, event => { const parser = event.getParser(); setBroadcastVideo(parser.videoId); @@ -385,7 +388,7 @@ export const YouTubePlayerView: FC<{}> = () => { className={`flex-1 p-2 rounded text-white text-sm ${(!!broadcastVideo && !isMyRoom) ? "bg-gray-800" : "bg-gray-700"}`} placeholder="YouTube URL / video ID" /> - {isMyRoom && videoId && ( + {isMyRoom && youtubeEnabled && videoId && (