mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
🆕 YoutubeTV Broadcasting in rooms !
This commit is contained in:
@@ -26,3 +26,4 @@ export * from './room/widgets';
|
|||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './wired';
|
export * from './wired';
|
||||||
|
export * from './youtube';
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
let _youtubeEnabled = false;
|
||||||
|
|
||||||
|
export const getYoutubeRoomEnabled = () => _youtubeEnabled;
|
||||||
|
export const setYoutubeRoomEnabled = (enabled: boolean) => { _youtubeEnabled = enabled; };
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './YouTubeRoomState';
|
||||||
@@ -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<NavigatorRoomSettingsMiscTabViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { roomData = null } = props;
|
||||||
|
const [ youtubeEnabled, setYoutubeEnabled ] = useState(getYoutubeRoomEnabled());
|
||||||
|
const [ cooldown, setCooldown ] = useState(false);
|
||||||
|
|
||||||
|
useMessageEvent<YouTubeRoomSettingsEvent>(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 (
|
||||||
|
<>
|
||||||
|
<div className="mb-3">
|
||||||
|
<div className="font-bold text-sm mb-2">{ LocalizeText('product.type.other') }</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<div className={`p-3 rounded transition-colors ${cooldown ? 'bg-gray-200 opacity-60' : 'bg-gray-100'}`}>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<div className="font-bold text-sm">📺 YouTube TV</div>
|
||||||
|
<div className="text-xs text-gray-500">Allow YouTube video broadcasting in this room</div>
|
||||||
|
</div>
|
||||||
|
<label className="relative inline-flex items-center cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={ youtubeEnabled }
|
||||||
|
disabled={ cooldown }
|
||||||
|
onChange={ e => toggleYouTube(e.target.checked) }
|
||||||
|
className="w-5 h-5"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@ import { NavigatorRoomSettingsAccessTabView } from './NavigatorRoomSettingsAcces
|
|||||||
import { NavigatorRoomSettingsBasicTabView } from './NavigatorRoomSettingsBasicTabView';
|
import { NavigatorRoomSettingsBasicTabView } from './NavigatorRoomSettingsBasicTabView';
|
||||||
import { NavigatorRoomSettingsModTabView } from './NavigatorRoomSettingsModTabView';
|
import { NavigatorRoomSettingsModTabView } from './NavigatorRoomSettingsModTabView';
|
||||||
import { NavigatorRoomSettingsRightsTabView } from './NavigatorRoomSettingsRightsTabView';
|
import { NavigatorRoomSettingsRightsTabView } from './NavigatorRoomSettingsRightsTabView';
|
||||||
|
import { NavigatorRoomSettingsMiscTabView } from './NavigatorRoomSettingsMiscTabView';
|
||||||
import { NavigatorRoomSettingsVipChatTabView } from './NavigatorRoomSettingsVipChatTabView';
|
import { NavigatorRoomSettingsVipChatTabView } from './NavigatorRoomSettingsVipChatTabView';
|
||||||
|
|
||||||
const TABS: string[] = [
|
const TABS: string[] = [
|
||||||
@@ -14,7 +15,8 @@ const TABS: string[] = [
|
|||||||
'navigator.roomsettings.tab.2',
|
'navigator.roomsettings.tab.2',
|
||||||
'navigator.roomsettings.tab.3',
|
'navigator.roomsettings.tab.3',
|
||||||
'navigator.roomsettings.tab.4',
|
'navigator.roomsettings.tab.4',
|
||||||
'navigator.roomsettings.tab.5'
|
'navigator.roomsettings.tab.5',
|
||||||
|
'product.type.other'
|
||||||
];
|
];
|
||||||
|
|
||||||
export const NavigatorRoomSettingsView: FC<{}> = props =>
|
export const NavigatorRoomSettingsView: FC<{}> = props =>
|
||||||
@@ -205,6 +207,8 @@ export const NavigatorRoomSettingsView: FC<{}> = props =>
|
|||||||
<NavigatorRoomSettingsVipChatTabView handleChange={ handleChange } roomData={ roomData } /> }
|
<NavigatorRoomSettingsVipChatTabView handleChange={ handleChange } roomData={ roomData } /> }
|
||||||
{ (currentTab === TABS[4]) &&
|
{ (currentTab === TABS[4]) &&
|
||||||
<NavigatorRoomSettingsModTabView handleChange={ handleChange } roomData={ roomData } /> }
|
<NavigatorRoomSettingsModTabView handleChange={ handleChange } roomData={ roomData } /> }
|
||||||
|
{ (currentTab === TABS[5]) &&
|
||||||
|
<NavigatorRoomSettingsMiscTabView roomData={ roomData } /> }
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
</NitroCardView>
|
</NitroCardView>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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 { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { GetConfigurationValue, MessengerIconState, OpenMessengerChat, VisitDesktop } from '../../api';
|
import { GetConfigurationValue, MessengerIconState, OpenMessengerChat, setYoutubeRoomEnabled, VisitDesktop } from '../../api';
|
||||||
import { Flex, LayoutAvatarImageView, LayoutItemCountView } from '../../common';
|
import { Flex, LayoutAvatarImageView, LayoutItemCountView } from '../../common';
|
||||||
import { useAchievements, useFriends, useInventoryUnseenTracker, useMessageEvent, useMessenger, useNitroEvent, useSessionInfo } from '../../hooks';
|
import { useAchievements, useFriends, useInventoryUnseenTracker, useMessageEvent, useMessenger, useNitroEvent, useSessionInfo } from '../../hooks';
|
||||||
import { ToolbarItemView } from './ToolbarItemView';
|
import { ToolbarItemView } from './ToolbarItemView';
|
||||||
@@ -13,6 +13,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
|||||||
const { isInRoom } = props;
|
const { isInRoom } = props;
|
||||||
const [ isMeExpanded, setMeExpanded ] = useState(false);
|
const [ isMeExpanded, setMeExpanded ] = useState(false);
|
||||||
const [ useGuideTool, setUseGuideTool ] = useState(false);
|
const [ useGuideTool, setUseGuideTool ] = useState(false);
|
||||||
|
const [ youtubeEnabled, setYoutubeEnabled ] = useState(false);
|
||||||
const { userFigure = null } = useSessionInfo();
|
const { userFigure = null } = useSessionInfo();
|
||||||
const { getFullCount = 0 } = useInventoryUnseenTracker();
|
const { getFullCount = 0 } = useInventoryUnseenTracker();
|
||||||
const { getTotalUnseen = 0 } = useAchievements();
|
const { getTotalUnseen = 0 } = useAchievements();
|
||||||
@@ -20,6 +21,20 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
|||||||
const { iconState = MessengerIconState.HIDDEN } = useMessenger();
|
const { iconState = MessengerIconState.HIDDEN } = useMessenger();
|
||||||
const isMod = GetSessionDataManager().isModerator;
|
const isMod = GetSessionDataManager().isModerator;
|
||||||
|
|
||||||
|
useMessageEvent<YouTubeRoomSettingsEvent>(YouTubeRoomSettingsEvent, event =>
|
||||||
|
{
|
||||||
|
const enabled = event.getParser().youtubeEnabled;
|
||||||
|
setYoutubeEnabled(enabled);
|
||||||
|
setYoutubeRoomEnabled(enabled);
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isInRoom) {
|
||||||
|
setYoutubeEnabled(false);
|
||||||
|
setYoutubeRoomEnabled(false);
|
||||||
|
}
|
||||||
|
}, [isInRoom]);
|
||||||
|
|
||||||
const openYouTubePlayer = () =>
|
const openYouTubePlayer = () =>
|
||||||
{
|
{
|
||||||
window.dispatchEvent(new CustomEvent('youtube:toggle'));
|
window.dispatchEvent(new CustomEvent('youtube:toggle'));
|
||||||
@@ -71,7 +86,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<YouTubePlayerView />
|
{ youtubeEnabled && <YouTubePlayerView /> }
|
||||||
<AnimatePresence> { isMeExpanded && ( <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.3 }}>
|
<AnimatePresence> { isMeExpanded && ( <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.3 }}>
|
||||||
<ToolbarMeView setMeExpanded={ setMeExpanded } unseenAchievementCount={ getTotalUnseen } useGuideTool={ useGuideTool } />
|
<ToolbarMeView setMeExpanded={ setMeExpanded } unseenAchievementCount={ getTotalUnseen } useGuideTool={ useGuideTool } />
|
||||||
</motion.div> )}
|
</motion.div> )}
|
||||||
@@ -101,7 +116,8 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
|
|||||||
</ToolbarItemView>
|
</ToolbarItemView>
|
||||||
{ isInRoom &&
|
{ isInRoom &&
|
||||||
<ToolbarItemView icon="camera" onClick={ event => CreateLinkEvent('camera/toggle') } /> }
|
<ToolbarItemView icon="camera" onClick={ event => CreateLinkEvent('camera/toggle') } /> }
|
||||||
<ToolbarItemView icon="youtube" onClick={ openYouTubePlayer } />
|
{ youtubeEnabled &&
|
||||||
|
<ToolbarItemView icon="youtube" onClick={ openYouTubePlayer } /> }
|
||||||
{ isMod &&
|
{ isMod &&
|
||||||
<ToolbarItemView icon="modtools" onClick={ event => CreateLinkEvent('mod-tools/toggle') } /> }
|
<ToolbarItemView icon="modtools" onClick={ event => CreateLinkEvent('mod-tools/toggle') } /> }
|
||||||
{ isMod &&
|
{ isMod &&
|
||||||
|
|||||||
@@ -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 { FC, useEffect, useRef, useState } from "react";
|
||||||
import YouTube from "react-youtube";
|
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 { NitroCardContentView, NitroCardHeaderView, NitroCardView, LayoutAvatarImageView } from "../../common";
|
||||||
import { useFurnitureYoutubeWidget, useMessageEvent } from "../../hooks";
|
import { useFurnitureYoutubeWidget, useMessageEvent } from "../../hooks";
|
||||||
|
|
||||||
@@ -36,14 +36,17 @@ export const YouTubePlayerView: FC<{}> = () => {
|
|||||||
const [history, setHistory] = useState<string[]>([]);
|
const [history, setHistory] = useState<string[]>([]);
|
||||||
const [showVolumeSlider, setShowVolumeSlider] = useState(true);
|
const [showVolumeSlider, setShowVolumeSlider] = useState(true);
|
||||||
const playerRef = useRef<any>(null);
|
const playerRef = useRef<any>(null);
|
||||||
|
|
||||||
const { objectId: youtubeObjectId, videoId: roomVideoId, currentVideoState, hasControl } = useFurnitureYoutubeWidget();
|
const { objectId: youtubeObjectId, videoId: roomVideoId, currentVideoState, hasControl } = useFurnitureYoutubeWidget();
|
||||||
|
|
||||||
const [spectators, setSpectators] = useState< { id: number; name: string; look: string }[] >([]);
|
const [spectators, setSpectators] = useState< { id: number; name: string; look: string }[] >([]);
|
||||||
const [broadcastVideo, setBroadcastVideo] = useState("");
|
const [broadcastVideo, setBroadcastVideo] = useState("");
|
||||||
const [broadcastSender, setBroadcastSender] = useState("");
|
const [broadcastSender, setBroadcastSender] = useState("");
|
||||||
const [broadcastPlaylist, setBroadcastPlaylist] = useState<string[]>([]);
|
const [broadcastPlaylist, setBroadcastPlaylist] = useState<string[]>([]);
|
||||||
const [watcherIds, setWatcherIds] = useState<Set<number>>(new Set());
|
const [watcherIds, setWatcherIds] = useState<Set<number>>(new Set());
|
||||||
|
const [youtubeEnabled, setYoutubeEnabled] = useState(getYoutubeRoomEnabled());
|
||||||
|
|
||||||
|
useMessageEvent<YouTubeRoomSettingsEvent>(YouTubeRoomSettingsEvent, event => {
|
||||||
|
setYoutubeEnabled(event.getParser().youtubeEnabled);
|
||||||
|
});
|
||||||
useMessageEvent<YouTubeRoomBroadcastEvent>(YouTubeRoomBroadcastEvent, event => {
|
useMessageEvent<YouTubeRoomBroadcastEvent>(YouTubeRoomBroadcastEvent, event => {
|
||||||
const parser = event.getParser();
|
const parser = event.getParser();
|
||||||
setBroadcastVideo(parser.videoId);
|
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"}`}
|
className={`flex-1 p-2 rounded text-white text-sm ${(!!broadcastVideo && !isMyRoom) ? "bg-gray-800" : "bg-gray-700"}`}
|
||||||
placeholder="YouTube URL / video ID"
|
placeholder="YouTube URL / video ID"
|
||||||
/>
|
/>
|
||||||
{isMyRoom && videoId && (
|
{isMyRoom && youtubeEnabled && videoId && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user