From 45d87c2832f1b822f28c8437a6c7d6b3f890b8e5 Mon Sep 17 00:00:00 2001 From: talksik Date: Sat, 7 May 2022 10:14:17 -0500 Subject: [PATCH] good progress on socket mesh --- packages/api/sockets/index.ts | 229 +++++++++------ packages/core/models/masterLineData.model.ts | 21 +- packages/core/sockets/channels.ts | 64 ++++- .../src/controller/lineDataProvider.tsx | 266 ++++++++++++------ packages/desktop/src/pages/overlay/index.tsx | 8 + .../src/pages/terminal/details/index.tsx | 18 +- packages/desktop/src/styles/index.css | 8 + 7 files changed, 411 insertions(+), 203 deletions(-) diff --git a/packages/api/sockets/index.ts b/packages/api/sockets/index.ts index ba40d55..47613ad 100644 --- a/packages/api/sockets/index.ts +++ b/packages/api/sockets/index.ts @@ -1,10 +1,16 @@ -import SocketChannels, { - ConnectToLine, - SomeoneConnected, - SomeoneTuned, - TuneToLine, - UserBroadcastPull, - UserBroadcastingPush, +import { + ConnectToLineRequest, + ServerRequestChannels, + ServerResponseChannels, + SomeoneConnectedResponse, + SomeoneTunedResponse, + SomeoneUntunedFromLineResponse, + StartBroadcastingRequest, + StopBroadcastingRequest, + TuneToLineRequest, + UntuneFromLineRequest, + UserStartedBroadcastingResponse, + UserStoppedBroadcastingResponse, } from "@nirvana/core/sockets/channels"; import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients"; @@ -22,6 +28,7 @@ const jwt = require("jsonwebtoken"); const config = loadConfig(); +// NOTE: client socket connections should never have to deal with socketIds const socketIdsToUserIds: { [socketId: string]: string; } = {}; @@ -67,97 +74,147 @@ export default function InitializeWs(io: any) { // ?verification that user is in a particular line to be tuned into it or just generally in it? /** CONNECT | User wants to subscribe to live emissions of a line */ - socket.on(SocketChannels.CONNECT_TO_LINE, (req: ConnectToLine) => { - // add this user to the room - console.log(`${socket.id} user joined room for line ${req.lineId}`); - - const roomName = `connectedLine:${req.lineId}`; - socket.join(roomName); - - console.log(`${socket.id} now in rooms ${socket.rooms}`); - - const clientUserIdsInRoom = [...io.sockets.adapter.rooms.get(roomName)]; - - io.in(roomName).emit( - SocketChannels.SOMEONE_CONNECTED_TO_LINE, - new SomeoneConnected(req.lineId, userInfo.userId, clientUserIdsInRoom) - ); - }); - - /** TUNE | User tunes into the line either temporarily or toggled in */ - socket.on(SocketChannels.TUNE_TO_LINE, async (req: TuneToLine) => { - console.log(`${socket.id} user tuned into room for line ${req.lineId}`); - - const roomName = `tunedLine:${req.lineId}`; - socket.join(roomName); - - console.log(`${socket.id} now in rooms ${socket.rooms}`); - - // persist tuning in if user is toggle tuning in - if (req.keepTunedIn) { - await LineService.updateLineMemberState( - req.lineId, - userInfo.userId, - LineMemberState.TUNED - ); - } else { - // just updates the - await LineService.updateLineMemberVisitDate( - req.lineId, - userInfo.userId - ); - } - - const clientUserIdsInRoom = io.sockets.adapter.rooms - .get(roomName) - .map((socketId: any) => socketIdsToUserIds[socketId]); - - // we want to notify everyone connected to the line even if they are not tuned in - const connectedLine = `connectedLine:${req.lineId}`; - - io.in(connectedLine).emit( - SocketChannels.SOMEONE_TUNED_TO_LINE, - new SomeoneTuned(req.lineId, userInfo.userId, clientUserIdsInRoom) - ); - }); - - /** BROADCAST UPDATE | tell all who are connected to line, not just tuned into, that there is an update to someone broadcasting */ socket.on( - SocketChannels.USER_BROADCAST_PUSH_PULL, - (req: UserBroadcastingPush) => { + ServerRequestChannels.CONNECT_TO_LINE, + (req: ConnectToLineRequest) => { + // add this user to the room + console.log(`${socket.id} user joined room for line ${req.lineId}`); + const roomName = `connectedLine:${req.lineId}`; + socket.join(roomName); + + console.log(`${socket.id} now in rooms ${socket.rooms}`); + + const clientUserIdsInRoom = [ + ...io.sockets.adapter.rooms.get(roomName), + ].map( + (otherUserSocketId: string) => socketIdsToUserIds[otherUserSocketId] + ); io.in(roomName).emit( - SocketChannels.USER_BROADCAST_PUSH_PULL, - new UserBroadcastPull(req.lineId, userInfo.userId, req.isTurningOn) + ServerResponseChannels.SOMEONE_CONNECTED_TO_LINE, + new SomeoneConnectedResponse( + req.lineId, + userInfo.userId, + clientUserIdsInRoom + ) ); } ); - socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => { - // TODO: only get the socket ids of the relevant rooms for this user - // return all Socket instances - const allConnectedSockets = Array.from(await io.of("/").sockets.keys()); + /** TUNE | User tunes into the line either temporarily or toggled in */ + socket.on( + ServerRequestChannels.TUNE_INTO_LINE, + async (req: TuneToLineRequest) => { + console.log( + `${socket.id} user tuned into room for line ${req.lineId}` + ); - io.to(socket.id).emit(SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, { - socketIds: allConnectedSockets, - } as GetAllSocketClients); - }); + const roomName = `tunedLine:${req.lineId}`; + socket.join(roomName); - socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => { - console.log(payload); + console.log(`${socket.id} now in rooms ${socket.rooms}`); - const sendingBackData: ReceiveSignal = { - simplePeerSignal: payload.simplePeerSignal, - senderUserSocketId: socket.id, - isGoingBackToInitiator: payload.isAnswerer ? true : false, - }; + // persist tuning in if user is toggle tuning in + if (req.keepTunedIn) { + await LineService.updateLineMemberState( + req.lineId, + userInfo.userId, + LineMemberState.TUNED + ); + } else { + // just updates the + await LineService.updateLineMemberVisitDate( + req.lineId, + userInfo.userId + ); + } - io.to(payload.userSocketIdToSignal).emit( - SocketChannels.RECEIVE_SIGNAL, - sendingBackData - ); - }); + const clientUserIdsInRoom = [ + ...io.sockets.adapter.rooms.get(roomName), + ].map( + (otherUserSocketId: string) => socketIdsToUserIds[otherUserSocketId] + ); + + // we want to notify everyone connected to the line even if they are not tuned in + const connectedLine = `connectedLine:${req.lineId}`; + + io.in(connectedLine).emit( + ServerResponseChannels.SOMEONE_TUNED_INTO_LINE, + new SomeoneTunedResponse( + req.lineId, + userInfo.userId, + clientUserIdsInRoom + ) + ); + } + ); + + /** + * TODO: handle when user wants to completely leave a line (delete or removed from one) + */ + socket.on(ServerRequestChannels.DISCONNECT_FROM_LINE, () => + console.log("not implemented") + ); + + /** + * Notify all users when someone UNTUNES from a room + * ?might not be needed, all users' memory of tuned in users is irrelevant? don't need real time? but UI will show # of users tuned in? + */ + socket.on( + ServerRequestChannels.UNTUNE_FROM_LINE, + async (req: UntuneFromLineRequest) => { + const roomName = `tunedLine:${req.lineId}`; + socket.leave(roomName); + + console.log("someone left room"); + + io.in(roomName).emit( + ServerResponseChannels.SOMEONE_UNTUNED_FROM_LINE, + new SomeoneUntunedFromLineResponse(req.lineId, userInfo.userId) + ); + } + ); + + /** BROADCAST UPDATE | tell all who are connected to line, not just tuned into, that there is an update to someone broadcasting */ + socket.on( + ServerRequestChannels.BROADCAST_TO_LINE, + (req: StartBroadcastingRequest) => { + const roomName = `connectedLine:${req.lineId}`; + + io.in(roomName).emit( + ServerResponseChannels.SOMEONE_STARTED_BROADCASTING, + new UserStartedBroadcastingResponse(req.lineId, userInfo.userId) + ); + } + ); + + socket.on( + ServerRequestChannels.STOP_BROADCAST_TO_LINE, + (req: StopBroadcastingRequest) => { + const roomName = `connectedLine:${req.lineId}`; + + io.in(roomName).emit( + ServerResponseChannels.SOMEONE_STOPPED_BROADCASTING, + new UserStoppedBroadcastingResponse(req.lineId, userInfo.userId) + ); + } + ); + + // socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => { + // console.log(payload); + + // const sendingBackData: ReceiveSignal = { + // simplePeerSignal: payload.simplePeerSignal, + // senderUserSocketId: socket.id, + // isGoingBackToInitiator: payload.isAnswerer ? true : false, + // }; + + // io.to(payload.userSocketIdToSignal).emit( + // SocketChannels.RECEIVE_SIGNAL, + // sendingBackData + // ); + // }); // ==== DISCONNECT ==== socket.on("disconnect", () => { diff --git a/packages/core/models/masterLineData.model.ts b/packages/core/models/masterLineData.model.ts index 5b004ce..357d391 100644 --- a/packages/core/models/masterLineData.model.ts +++ b/packages/core/models/masterLineData.model.ts @@ -8,14 +8,21 @@ import { User } from "./user.model"; // speed...I'm developing full stack and I just want all of the data and don't want to change this model // repeatedly and trace data back and forth export default class MasterLineData { - // if someone else is buzzing on the line - isOtherBroadcasting?: boolean = false; - // if I am buzzing in the line - isUserBroadcasting?: boolean = false; + // NOTE: these properties should be kept optional cuzz default values won't show up for + // all clients who are casting response objects + + // not really necessary, but clients can know all connected folks + // -> if they wanted to get the feeling of people being right there + connectedMemberIds?: string[]; + + // all of the current session tuned in folks for user to see + // -> use as source of truth whether or not I am tuned in or not for UI to avoid confusion + // -> + tunedInMemberIds?: string[]; + // list of user Ids of everyone who is buzzing in this line - currentBroadcasters: string[] = []; - // ?current people tuned into the line...not sure if this is a product decision but can support it - tunedInMemberIds: string[] = []; + // -> all connected line members be able to show this in the right activity section of the lineRow + currentBroadcastersUserIds?: string[]; constructor( // full line object diff --git a/packages/core/sockets/channels.ts b/packages/core/sockets/channels.ts index b7bd5b5..af51bf4 100644 --- a/packages/core/sockets/channels.ts +++ b/packages/core/sockets/channels.ts @@ -23,15 +23,42 @@ enum SocketChannels { TUNE_TO_LINE = "TUNE_TO_LINE", SOMEONE_TUNED_TO_LINE = "SOMEONE_TUNED_TO_LINE", + SOMEONE_UNTUNED_FROM_LINE = "SOMEONE_UNTUNED_FROM_LINE", + USER_BROADCAST_PUSH_PULL = "USER_BROADCAST_PUSH_PULL", } +// ! MAKE SURE THAT THE ENUMS BETWEEN REQUEST AND RESPONSE DON'T OVERLAP??? +// ?maybe won't matter since it's different for server and client? +export enum ServerRequestChannels { + CONNECT_TO_LINE = "CONNECT_TO_LINE", + + DISCONNECT_FROM_LINE = "DISCONNECT_FROM_LINE", // TODO: not implementing now + + TUNE_INTO_LINE = "TUNE_INTO_LINE", // pass in if user wants to toggle/persist? or is this just temporary? + UNTUNE_FROM_LINE = "UNTUNE_FROM_LINE", + + BROADCAST_TO_LINE = "BROADCAST_TO_LINE", + STOP_BROADCAST_TO_LINE = "STOP_BROADCAST_TO_LINE", +} + +export enum ServerResponseChannels { + SOMEONE_CONNECTED_TO_LINE = "SOMEONE_CONNECTED_TO_LINE", + SOMEONE_DISCONNECTED_FROM_LINE = "SOMEONE_DISCONNECTED_FROM_LINE", + + SOMEONE_TUNED_INTO_LINE = "SOMEONE_TUNED_INTO_LINE", // allows all current tuned in folks to create peer objects + SOMEONE_UNTUNED_FROM_LINE = "SOMEONE_UNTUNED_FROM_LINE", // discard peer + + SOMEONE_STARTED_BROADCASTING = "SOMEONE_STARTED_BROADCASTING", //show their stream tracks + SOMEONE_STOPPED_BROADCASTING = "SOMEONE_STOPPED_BROADCASTING", // stop showing their stream tracks +} + export default SocketChannels; -export class ConnectToLine { +export class ConnectToLineRequest { constructor(public lineId: string) {} } -export class SomeoneConnected { +export class SomeoneConnectedResponse { constructor( public lineId: string, public userId: string, @@ -39,29 +66,38 @@ export class SomeoneConnected { ) {} } -export class TuneToLine { +export class TuneToLineRequest { constructor(public lineId: string, public keepTunedIn: boolean = false) {} } -export class SomeoneTuned { +export class SomeoneTunedResponse { constructor( public lineId: string, public userId: string, public allTunedIntoUserIds: string[] ) {} } - -export class UserBroadcastingPush { - constructor(public lineId: string, public isTurningOn: boolean = true) {} +export class UntuneFromLineRequest { + constructor(public lineId: string) {} } -export class UserBroadcastPull { - // is the user turning their broadcasting on or off for a specific line? - constructor( - public lineId: string, - public userId: string, - public isTurningOn: boolean = true - ) {} +export class SomeoneUntunedFromLineResponse { + constructor(public lineId: string, public userId: string) {} } +export class StartBroadcastingRequest { + constructor(public lineId: string) {} +} +export class UserStartedBroadcastingResponse { + constructor(public lineId: string, public userId: string) {} +} + +export class StopBroadcastingRequest { + constructor(public lineId: string) {} +} +export class UserStoppedBroadcastingResponse { + constructor(public lineId: string, public userId: string) {} +} + +// ?another approach to use switch statements, but it just requires same mess, just less methods with socket but who cares right now export class SocketEmitter { constructor(public channel: SocketChannels, data: T) {} } diff --git a/packages/desktop/src/controller/lineDataProvider.tsx b/packages/desktop/src/controller/lineDataProvider.tsx index 68b8d6f..8d29f2f 100644 --- a/packages/desktop/src/controller/lineDataProvider.tsx +++ b/packages/desktop/src/controller/lineDataProvider.tsx @@ -1,18 +1,21 @@ import { $jwtToken, $selectedLineId } from "./recoil"; import { - ConnectToLine, - SomeoneConnected, - SomeoneTuned, - TuneToLine, - UserBroadcastPull, - UserBroadcastingPush, + ConnectToLineRequest, + ServerRequestChannels, + ServerResponseChannels, + SomeoneConnectedResponse, + SomeoneTunedResponse, + StartBroadcastingRequest, + StopBroadcastingRequest, + TuneToLineRequest, + UserStartedBroadcastingResponse, } from "@nirvana/core/sockets/channels"; import React, { useContext, useState } from "react"; import { Socket, io } from "socket.io-client"; import { useCallback, useEffect } from "react"; +import { LineMemberState } from "@nirvana/core/models/line.model"; import MasterLineData from "@nirvana/core/models/masterLineData.model"; -import SocketChannels from "@nirvana/core/sockets/channels"; import { User } from "@nirvana/core/models"; import { queryClient } from "../pages/nirvanaApp"; import toast from "react-hot-toast"; @@ -26,32 +29,9 @@ function useSocketHandler(linesData: MasterLineData[]) { const [linesMap, setLinesMap] = useState({}); - useEffect(() => { - console.log(linesData); - if (linesData) { - setLinesMap((prevMappings) => { - // go through the lines from the persistent store - - // get all of the id's and map assign to the main object - - // ?prolly have no previous at this point...but I'm okay with override since this - // ?useeffect is triggered on the refetching of the persistent store so we - // ?are prolly looking to do a full app refresh and connection refresh - const newMap = { ...prevMappings }; - - linesData.map((masterLine) => { - newMap[masterLine.lineDetails._id.toString()] = masterLine; - - handleConnectToLine(masterLine.lineDetails._id.toString()); - - // tune into lines - }); - - return newMap; - }); - } - }, [linesData, setLinesMap]); - + /** + * handle ws connection + */ useEffect(() => { $ws = io("http://localhost:5000", { query: { token: jwtToken }, @@ -69,67 +49,151 @@ function useSocketHandler(linesData: MasterLineData[]) { // this should overall remount this component currently which is what we want for new data queryClient.invalidateQueries("SERVER_CHECK"); }); - - // when me or anyone just initially connects to line - $ws.on( - SocketChannels.SOMEONE_CONNECTED_TO_LINE, - (res: SomeoneConnected) => { - // TODO: change the correct masterLineData to contain this - - console.log( - `connected to line...here are all of the users in the conected line ${res.lineId}`, - res.allConnectedIntoUserIds - ); - } - ); - - // whether toggle tuned or temporarily - $ws.on(SocketChannels.SOMEONE_TUNED_TO_LINE, (res: SomeoneTuned) => { - // TODO: change the correct master line data to show user who's tuned in - - toast( - `another user (${res.userId}) tuned into line ${res.lineId} that you are in also` - ); - - console.log( - `here are all of the users in the tuned in room`, - res.allTunedIntoUserIds - ); - }); - - $ws.on( - SocketChannels.USER_BROADCAST_PUSH_PULL, - (pull: UserBroadcastPull) => { - toast.success( - `someone or myself buzz on or off in line ${pull.lineId}` - ); - - const newMap = {}; - - // todo: check if it's the user or someone else broadcasting - - if (newMap[pull.lineId]) - newMap[pull.lineId].isUserBroadcasting = pull.isTurningOn; - } - ); }, []); - const handleConnectToLine = (lineId: string) => { - $ws.emit(SocketChannels.CONNECT_TO_LINE, new ConnectToLine(lineId)); - }; + /** + * initiate listeners + */ + useEffect(() => { + // when me or anyone just initially connects to line + $ws.on( + ServerResponseChannels.SOMEONE_CONNECTED_TO_LINE, + (res: SomeoneConnectedResponse) => { + console.log( + `connected to line...here are all of the updated in the conected line ${res.lineId}...this isn't reliable considering it's not updated later`, + res.allConnectedIntoUserIds + ); + + setLinesMap((prevLinesMap) => { + const newMap = { ...prevLinesMap }; + + if (newMap[res.lineId]) + newMap[res.lineId].connectedMemberIds = [ + ...(newMap[res.lineId]?.connectedMemberIds ?? []), + res.userId, + ]; + + return newMap; + }); + } + ); + + // someone tuning in, including perhaps me | either toggled in or just temporary + $ws.on( + ServerResponseChannels.SOMEONE_TUNED_INTO_LINE, + (res: SomeoneTunedResponse) => { + console.log( + `here are all of updated users in the tuned in room`, + res.allTunedIntoUserIds + ); + + // TODO: if toggled in, make sure to update the current line member in the lines map so that + // we can know to untune if user selects another line + + // below, we are setting the list of tuned in folks based on fresh list from the server + // better than just adding and removing? i think so, but have to handle not interrupting existing peer connections as this changes + setLinesMap((prevLinesMap) => { + const newMap = { ...prevLinesMap }; + + // TODO: update the relevant lineMember (based on which userId is given): state and last visit date if current user is joining + + if (newMap[res.lineId]) + newMap[res.lineId].currentBroadcastersUserIds = [ + ...(newMap[res.lineId].tunedInMemberIds ?? []), + res.userId, + ]; + + return newMap; + }); + } + ); + + // could + $ws.on( + ServerResponseChannels.SOMEONE_STARTED_BROADCASTING, + (res: UserStartedBroadcastingResponse) => { + toast.success(`someone or myself buzz on or off in line ${res.lineId}`); + + setLinesMap((prevLinesMap) => { + const newMap = { ...prevLinesMap }; + + // todo: check if it's the user or someone else broadcasting + + if (newMap[res.lineId]) + newMap[res.lineId].currentBroadcastersUserIds = [ + ...(newMap[res.lineId].currentBroadcastersUserIds ?? []), + res.userId, + ]; + + return newMap; + }); + } + ); + }, [setLinesMap]); + + /** handle initial data coming in and creating the initial line map + * and doing initial connections/tune ins ?could trigger this later? + */ + useEffect(() => { + console.log(linesData); + if (linesData) { + setLinesMap((prevMappings) => { + // go through the lines from the persistent store + + // get all of the id's and map assign to the main object + + // ?prolly have no previous at this point...but I'm okay with override since this + // ?useeffect is triggered on the refetching of the persistent store so we + // ?are prolly looking to do a full app refresh and connection refresh + const newMap = { ...prevMappings }; + + linesData.map((masterLine) => { + const lineId = masterLine.lineDetails._id.toString(); + newMap[lineId] = masterLine; + + handleConnectToLine(lineId); + + // tune into lines that I should be + if (masterLine.currentUserMember.state === LineMemberState.TUNED) { + // don't need to turn toggle on, it's already on + handleTuneToLine(lineId, false); + } + }); + + return newMap; + }); + } + }, [linesData, setLinesMap]); + + /** handlers for emitting events to server */ + const handleConnectToLine = useCallback( + (lineId: string) => { + $ws.emit( + ServerRequestChannels.CONNECT_TO_LINE, + new ConnectToLineRequest(lineId) + ); + }, + [$ws] + ); /** * toggle into a specific line * @param temporary: denotes whether we are just listening in or want to persist "toggling" it on so that it shows up in overlay * TODO: have loading state for this particular part of context value */ - const handleTuneToLine = (lineId: string, turnToggleOn: boolean = false) => { - // they already are in the socket room for updates including media connections and disconnections - // but set the flag so that the line row can know whether or not to start the webrtc process - // and know when to get out or disconnect from the webrtc when the flag turns off + const handleTuneToLine = useCallback( + (lineId: string, turnToggleOn: boolean = false) => { + // they already are in the socket room for updates including media connections and disconnections + // but set the flag so that the line row can know whether or not to start the webrtc process + // and know when to get out or disconnect from the webrtc when the flag turns off - $ws.emit(SocketChannels.TUNE_TO_LINE, new TuneToLine(lineId, turnToggleOn)); - }; + $ws.emit( + ServerRequestChannels.TUNE_INTO_LINE, + new TuneToLineRequest(lineId, turnToggleOn) + ); + }, + [$ws] + ); /** * This is when the user wants to tell everyone that they are streaming/broadcasting/buzzing to @@ -142,12 +206,23 @@ function useSocketHandler(linesData: MasterLineData[]) { * * @param lineId the line that the current user is talking into */ - const handleUserBroadcast = useCallback( - (lineId: string, isTurningOn: boolean = true) => { + const handleStartBroadcast = useCallback( + (lineId: string) => { // emit telling people $ws.emit( - SocketChannels.USER_BROADCAST_PUSH_PULL, - new UserBroadcastingPush(lineId, isTurningOn) + ServerRequestChannels.BROADCAST_TO_LINE, + new StartBroadcastingRequest(lineId) + ); + }, + [$ws] + ); + + const handleStopBroadcast = useCallback( + (lineId: string) => { + // emit telling people + $ws.emit( + ServerRequestChannels.STOP_BROADCAST_TO_LINE, + new StopBroadcastingRequest(lineId) ); // ?handle recording here as well? or record the incoming stream instead? @@ -170,10 +245,15 @@ function useSocketHandler(linesData: MasterLineData[]) { return { linesMap, - handleConnectToLine, - handleTuneToLine, - handleUserBroadcast, - handleFetchMoreAudioBlocks, + emitters: $ws + ? { + handleConnectToLine, + handleTuneToLine, + handleStartBroadcast, + handleStopBroadcast, + handleFetchMoreAudioBlocks, + } + : {}, }; } diff --git a/packages/desktop/src/pages/overlay/index.tsx b/packages/desktop/src/pages/overlay/index.tsx index f669844..8f4ddf5 100644 --- a/packages/desktop/src/pages/overlay/index.tsx +++ b/packages/desktop/src/pages/overlay/index.tsx @@ -93,6 +93,14 @@ export default function Overlay() { // socket.emit(SocketChannels.JOIN_LIVE_ROOM); + // would already have all of the tuned in sockets in array + // then create a peer for each...tell others to create also because they would have received + // "SOMEONE_TUNED_INTO_LINE" + + // need a peer connection with every userId in the list of tunedInFolks so that when it comes time to broadcast + // it's super simple in that we just start playing the stream from the appropriate peer who is associated with the correct userId + // small validation to consider is that the broadcasterUserIds are in the list of tunedInUserIds + // socket.on( // SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, // (data: GetAllSocketClients) => { diff --git a/packages/desktop/src/pages/terminal/details/index.tsx b/packages/desktop/src/pages/terminal/details/index.tsx index 9f511ce..05faec0 100644 --- a/packages/desktop/src/pages/terminal/details/index.tsx +++ b/packages/desktop/src/pages/terminal/details/index.tsx @@ -7,6 +7,7 @@ import LineIcon from "../../../components/lines/lineIcon/index"; import { LineMemberState } from "@nirvana/core/models/line.model"; import MasterLineData from "@nirvana/core/models/masterLineData.model"; import { Tooltip } from "antd"; +import { useGetUserDetails } from "../../../controller"; import { useLineDataProvider } from "../../../controller/lineDataProvider"; import { useRecoilState } from "recoil"; @@ -15,11 +16,22 @@ export default function LineDetailsTerminal({ }: { selectedLine: MasterLineData; }) { + const { data: userDetails } = useGetUserDetails(); const isUserToggleTuned = useMemo( () => selectedLine?.currentUserMember?.state === LineMemberState.TUNED, [selectedLine] ); + // seeing if I am in the list of broadcasters + // the source of truth from the socket connections telling me if my clicking actually made a round trip + const isUserBroadcasting = useMemo( + () => + selectedLine?.currentBroadcastersUserIds?.includes( + userDetails?.user._id.toString() + ), + [userDetails, selectedLine] + ); + return ( <>
@@ -54,9 +66,10 @@ export default function LineDetailsTerminal({ + {/* TODO: move to on hover of line row */}