diff --git a/packages/api/sockets/index.ts b/packages/api/sockets/index.ts index 3f1e583..08dca08 100644 --- a/packages/api/sockets/index.ts +++ b/packages/api/sockets/index.ts @@ -3,6 +3,8 @@ import SocketChannels, { SomeoneConnected, SomeoneTuned, TuneToLine, + UserBroadcastPull, + UserBroadcastingPush, } from "@nirvana/core/sockets/channels"; import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients"; @@ -95,6 +97,19 @@ export default function InitializeWs(io: any) { ); }); + /** 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) => { + const roomName = `connectedLine:${req.lineId}`; + + io.in(roomName).emit( + SocketChannels.USER_BROADCAST_PUSH_PULL, + new UserBroadcastPull(req.lineId, userInfo.userId, req.isTurningOn) + ); + } + ); + socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => { // TODO: only get the socket ids of the relevant rooms for this user // return all Socket instances diff --git a/packages/core/sockets/channels.ts b/packages/core/sockets/channels.ts index 819cab6..67011f4 100644 --- a/packages/core/sockets/channels.ts +++ b/packages/core/sockets/channels.ts @@ -22,6 +22,8 @@ enum SocketChannels { TUNE_TO_LINE = "TUNE_TO_LINE", SOMEONE_TUNED_TO_LINE = "SOMEONE_TUNED_TO_LINE", + + USER_BROADCAST_PUSH_PULL = "USER_BROADCAST_PUSH_PULL", } export default SocketChannels; @@ -47,3 +49,15 @@ export class SomeoneTuned { public allTunedIntoUserIds: string[] ) {} } + +export class UserBroadcastingPush { + constructor(public lineId: string, public isTurningOn: boolean = true) {} +} +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 + ) {} +} diff --git a/packages/desktop/src/controller/lineDataProvider.tsx b/packages/desktop/src/controller/lineDataProvider.tsx index 3185835..5a861db 100644 --- a/packages/desktop/src/controller/lineDataProvider.tsx +++ b/packages/desktop/src/controller/lineDataProvider.tsx @@ -3,6 +3,8 @@ import { ConnectToLine, SomeoneConnected, SomeoneTuned, + UserBroadcastPull, + UserBroadcastingPush, } from "@nirvana/core/sockets/channels"; import React, { useContext } from "react"; import { Socket, io } from "socket.io-client"; @@ -23,11 +25,13 @@ interface ILineDataContext { // represents the modified and up to date lines data with availability from session linesMap: LineIdToMasterLine; relevantUsers: User[]; + handleUserBroadcast: (lineId: string, isTurningOn: boolean) => void; } const LineDataContext = React.createContext({ linesMap: {}, relevantUsers: [], + handleUserBroadcast: (lineId: string, isTurningOn: boolean = true) => {}, }); let $ws: Socket; @@ -89,7 +93,27 @@ export function LineDataProvider({ children }) { res.allTunedIntoUserIds ); }); - }, []); + + $ws.on( + SocketChannels.USER_BROADCAST_PUSH_PULL, + (pull: UserBroadcastPull) => { + toast.success( + `someone or myself buzz on or off in line ${pull.lineId}` + ); + + setLinesMap((prevLinesMap) => { + const newMap = { ...prevLinesMap }; + + // todo: check if it's the user or someone else broadcasting + + if (newMap[pull.lineId]) + newMap[pull.lineId].isUserBroadcasting = true; + + return newMap; + }); + } + ); + }, [setLinesMap]); // connect through ws to enrich basic lines data useEffect(() => { @@ -115,7 +139,7 @@ export function LineDataProvider({ children }) { basicUserLinesData.data.masterLines.map((masterLine) => { newMap[masterLine.lineDetails._id.toString()] = masterLine; - handleConnect(masterLine.lineDetails._id.toString()); + handleConnectToLine(masterLine.lineDetails._id.toString()); // tune into lines }); @@ -125,7 +149,7 @@ export function LineDataProvider({ children }) { } }, [basicUserLinesData]); - const handleConnect = (lineId: string) => { + const handleConnectToLine = (lineId: string) => { $ws.emit(SocketChannels.CONNECT_TO_LINE, new ConnectToLine(lineId)); }; @@ -134,13 +158,38 @@ export function LineDataProvider({ children }) { * @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 handleTune = (lineId: string, turnToggleOn: boolean = false) => { + 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 // $ws.emit(SocketChannels.TUNE_INTO_LINE, new TuneIntoLine(lineId)); }; + /** + * This is when the user wants to tell everyone that they are streaming/broadcasting/buzzing to + * a specific line, whether they are toggle tuned or temporarily tuned in + * + * Note: They could be using push to talk or toggle broadcast + * + * Note: this is handling the data transmission as is the responsibility of this overall context provider + * and not necessarily the aspect of enabling and disabling streaming as webrtc is reliable enough for that + * + * @param lineId the line that the current user is talking into + */ + const handleUserBroadcast = useCallback( + (lineId: string, isTurningOn: boolean = true) => { + // emit telling people + $ws.emit( + SocketChannels.USER_BROADCAST_PUSH_PULL, + new UserBroadcastingPush(lineId, isTurningOn) + ); + + // ?handle recording here as well? or record the incoming stream instead? + // ?could just take in the audiochunks here and all, but not sure yet + }, + [$ws] + ); + /** * get more audio blocks for a certain line */ @@ -156,6 +205,7 @@ export function LineDataProvider({ children }) { const value: ILineDataContext = { linesMap, // TODO send the updated map instead of this array relevantUsers: [], + handleUserBroadcast, }; return ( diff --git a/packages/desktop/src/pages/terminal/details/index.tsx b/packages/desktop/src/pages/terminal/details/index.tsx index 46b44c2..f0690b4 100644 --- a/packages/desktop/src/pages/terminal/details/index.tsx +++ b/packages/desktop/src/pages/terminal/details/index.tsx @@ -83,10 +83,14 @@ export default function LineDetailsTerminal() { {/* TODO: change to border and inset color for when inactive button */} diff --git a/packages/desktop/src/pages/terminal/index.tsx b/packages/desktop/src/pages/terminal/index.tsx index fe63d93..c72565e 100644 --- a/packages/desktop/src/pages/terminal/index.tsx +++ b/packages/desktop/src/pages/terminal/index.tsx @@ -25,7 +25,7 @@ export default function NirvanaTerminal() { // simply using this query for specific data on loading // todo: add these properties in context provider value although more work down the line for control const { isLoading: isLoadingInitialLines } = useUserLines(); - const { linesMap } = useLineDataProvider(); + const { linesMap, handleUserBroadcast } = useLineDataProvider(); const allLines: MasterLineData[] = useMemo(() => { const masterLines: MasterLineData[] = Object.values(linesMap); @@ -53,18 +53,24 @@ export default function NirvanaTerminal() { setSelectedLineId(null); }, [setSelectedLineId]); + const handleStartBroadcast = useCallback(() => { + if (selectedLineId) handleUserBroadcast(selectedLineId, true); + }, [selectedLineId]); + const keyMap: KeyMap = useMemo( () => ({ DESELECT_LINE: "esc", + START_BROADCAST: "`", }), - [handleEscape] + [] ); const handlers = useMemo( () => ({ DESELECT_LINE: handleEscape, + START_BROADCAST: handleStartBroadcast, }), - [handleEscape] + [handleEscape, handleStartBroadcast] ); return (