good progress on socket mesh
This commit is contained in:
@@ -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<LineIdToMasterLine>({});
|
||||
|
||||
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,
|
||||
}
|
||||
: {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<div className="flex flex-col flex-1 bg-gray-100 items-stretch justify-start relative border-l border-l-gray-100">
|
||||
@@ -54,9 +66,10 @@ export default function LineDetailsTerminal({
|
||||
<FiSettings className="text-gray-400 text-md" />
|
||||
</button>
|
||||
|
||||
{/* TODO: move to on hover of line row */}
|
||||
<Tooltip
|
||||
title={`${
|
||||
isUserToggleTuned ? "toggle tuned" : "temporarily tuned"
|
||||
isUserToggleTuned ? "click to untoggle" : "click to stay tuned in"
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
@@ -69,11 +82,10 @@ export default function LineDetailsTerminal({
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
{/* TODO: change to border and inset color for when inactive button */}
|
||||
<button
|
||||
className={`p-3 flex justify-center items-center shadow-lg
|
||||
hover:scale-105 transition-all ${
|
||||
selectedLine.isUserBroadcasting || selectedLine.isOtherBroadcasting
|
||||
isUserBroadcasting
|
||||
? "bg-teal-800 text-white"
|
||||
: "text-teal-800 border-teal-800 border"
|
||||
}`}
|
||||
|
||||
@@ -27,6 +27,14 @@ body {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* TODO: temporary...remove? later? */
|
||||
body {
|
||||
-webkit-user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.titlebar-button {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user