good progress on socket mesh

This commit is contained in:
talksik
2022-05-07 10:14:17 -05:00
parent ce4b89adf2
commit 45d87c2832
7 changed files with 411 additions and 203 deletions
+143 -86
View File
@@ -1,10 +1,16 @@
import SocketChannels, { import {
ConnectToLine, ConnectToLineRequest,
SomeoneConnected, ServerRequestChannels,
SomeoneTuned, ServerResponseChannels,
TuneToLine, SomeoneConnectedResponse,
UserBroadcastPull, SomeoneTunedResponse,
UserBroadcastingPush, SomeoneUntunedFromLineResponse,
StartBroadcastingRequest,
StopBroadcastingRequest,
TuneToLineRequest,
UntuneFromLineRequest,
UserStartedBroadcastingResponse,
UserStoppedBroadcastingResponse,
} from "@nirvana/core/sockets/channels"; } from "@nirvana/core/sockets/channels";
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients"; import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
@@ -22,6 +28,7 @@ const jwt = require("jsonwebtoken");
const config = loadConfig(); const config = loadConfig();
// NOTE: client socket connections should never have to deal with socketIds
const socketIdsToUserIds: { const socketIdsToUserIds: {
[socketId: string]: string; [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? // ?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 */ /** 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( socket.on(
SocketChannels.USER_BROADCAST_PUSH_PULL, ServerRequestChannels.CONNECT_TO_LINE,
(req: UserBroadcastingPush) => { (req: ConnectToLineRequest) => {
// add this user to the room
console.log(`${socket.id} user joined room for line ${req.lineId}`);
const roomName = `connectedLine:${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( io.in(roomName).emit(
SocketChannels.USER_BROADCAST_PUSH_PULL, ServerResponseChannels.SOMEONE_CONNECTED_TO_LINE,
new UserBroadcastPull(req.lineId, userInfo.userId, req.isTurningOn) new SomeoneConnectedResponse(
req.lineId,
userInfo.userId,
clientUserIdsInRoom
)
); );
} }
); );
socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => { /** TUNE | User tunes into the line either temporarily or toggled in */
// TODO: only get the socket ids of the relevant rooms for this user socket.on(
// return all Socket instances ServerRequestChannels.TUNE_INTO_LINE,
const allConnectedSockets = Array.from(await io.of("/").sockets.keys()); 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, { const roomName = `tunedLine:${req.lineId}`;
socketIds: allConnectedSockets, socket.join(roomName);
} as GetAllSocketClients);
});
socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => { console.log(`${socket.id} now in rooms ${socket.rooms}`);
console.log(payload);
const sendingBackData: ReceiveSignal = { // persist tuning in if user is toggle tuning in
simplePeerSignal: payload.simplePeerSignal, if (req.keepTunedIn) {
senderUserSocketId: socket.id, await LineService.updateLineMemberState(
isGoingBackToInitiator: payload.isAnswerer ? true : false, req.lineId,
}; userInfo.userId,
LineMemberState.TUNED
);
} else {
// just updates the
await LineService.updateLineMemberVisitDate(
req.lineId,
userInfo.userId
);
}
io.to(payload.userSocketIdToSignal).emit( const clientUserIdsInRoom = [
SocketChannels.RECEIVE_SIGNAL, ...io.sockets.adapter.rooms.get(roomName),
sendingBackData ].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 ==== // ==== DISCONNECT ====
socket.on("disconnect", () => { socket.on("disconnect", () => {
+14 -7
View File
@@ -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 // 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 // repeatedly and trace data back and forth
export default class MasterLineData { export default class MasterLineData {
// if someone else is buzzing on the line // NOTE: these properties should be kept optional cuzz default values won't show up for
isOtherBroadcasting?: boolean = false; // all clients who are casting response objects
// if I am buzzing in the line
isUserBroadcasting?: boolean = false; // 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 // list of user Ids of everyone who is buzzing in this line
currentBroadcasters: string[] = []; // -> all connected line members be able to show this in the right activity section of the lineRow
// ?current people tuned into the line...not sure if this is a product decision but can support it currentBroadcastersUserIds?: string[];
tunedInMemberIds: string[] = [];
constructor( constructor(
// full line object // full line object
+50 -14
View File
@@ -23,15 +23,42 @@ enum SocketChannels {
TUNE_TO_LINE = "TUNE_TO_LINE", TUNE_TO_LINE = "TUNE_TO_LINE",
SOMEONE_TUNED_TO_LINE = "SOMEONE_TUNED_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", 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 default SocketChannels;
export class ConnectToLine { export class ConnectToLineRequest {
constructor(public lineId: string) {} constructor(public lineId: string) {}
} }
export class SomeoneConnected { export class SomeoneConnectedResponse {
constructor( constructor(
public lineId: string, public lineId: string,
public userId: 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) {} constructor(public lineId: string, public keepTunedIn: boolean = false) {}
} }
export class SomeoneTuned { export class SomeoneTunedResponse {
constructor( constructor(
public lineId: string, public lineId: string,
public userId: string, public userId: string,
public allTunedIntoUserIds: string[] public allTunedIntoUserIds: string[]
) {} ) {}
} }
export class UntuneFromLineRequest {
export class UserBroadcastingPush { constructor(public lineId: string) {}
constructor(public lineId: string, public isTurningOn: boolean = true) {}
} }
export class UserBroadcastPull { export class SomeoneUntunedFromLineResponse {
// is the user turning their broadcasting on or off for a specific line? constructor(public lineId: string, public userId: string) {}
constructor(
public lineId: string,
public userId: string,
public isTurningOn: boolean = true
) {}
} }
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<T> { export class SocketEmitter<T> {
constructor(public channel: SocketChannels, data: T) {} constructor(public channel: SocketChannels, data: T) {}
} }
@@ -1,18 +1,21 @@
import { $jwtToken, $selectedLineId } from "./recoil"; import { $jwtToken, $selectedLineId } from "./recoil";
import { import {
ConnectToLine, ConnectToLineRequest,
SomeoneConnected, ServerRequestChannels,
SomeoneTuned, ServerResponseChannels,
TuneToLine, SomeoneConnectedResponse,
UserBroadcastPull, SomeoneTunedResponse,
UserBroadcastingPush, StartBroadcastingRequest,
StopBroadcastingRequest,
TuneToLineRequest,
UserStartedBroadcastingResponse,
} from "@nirvana/core/sockets/channels"; } from "@nirvana/core/sockets/channels";
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import { Socket, io } from "socket.io-client"; import { Socket, io } from "socket.io-client";
import { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import { LineMemberState } from "@nirvana/core/models/line.model";
import MasterLineData from "@nirvana/core/models/masterLineData.model"; import MasterLineData from "@nirvana/core/models/masterLineData.model";
import SocketChannels from "@nirvana/core/sockets/channels";
import { User } from "@nirvana/core/models"; import { User } from "@nirvana/core/models";
import { queryClient } from "../pages/nirvanaApp"; import { queryClient } from "../pages/nirvanaApp";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
@@ -26,32 +29,9 @@ function useSocketHandler(linesData: MasterLineData[]) {
const [linesMap, setLinesMap] = useState<LineIdToMasterLine>({}); const [linesMap, setLinesMap] = useState<LineIdToMasterLine>({});
useEffect(() => { /**
console.log(linesData); * handle ws connection
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]);
useEffect(() => { useEffect(() => {
$ws = io("http://localhost:5000", { $ws = io("http://localhost:5000", {
query: { token: jwtToken }, 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 // this should overall remount this component currently which is what we want for new data
queryClient.invalidateQueries("SERVER_CHECK"); 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 * 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 * @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 * TODO: have loading state for this particular part of context value
*/ */
const handleTuneToLine = (lineId: string, turnToggleOn: boolean = false) => { const handleTuneToLine = useCallback(
// they already are in the socket room for updates including media connections and disconnections (lineId: string, turnToggleOn: boolean = false) => {
// but set the flag so that the line row can know whether or not to start the webrtc process // they already are in the socket room for updates including media connections and disconnections
// and know when to get out or disconnect from the webrtc when the flag turns off // 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 * 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 * @param lineId the line that the current user is talking into
*/ */
const handleUserBroadcast = useCallback( const handleStartBroadcast = useCallback(
(lineId: string, isTurningOn: boolean = true) => { (lineId: string) => {
// emit telling people // emit telling people
$ws.emit( $ws.emit(
SocketChannels.USER_BROADCAST_PUSH_PULL, ServerRequestChannels.BROADCAST_TO_LINE,
new UserBroadcastingPush(lineId, isTurningOn) 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? // ?handle recording here as well? or record the incoming stream instead?
@@ -170,10 +245,15 @@ function useSocketHandler(linesData: MasterLineData[]) {
return { return {
linesMap, linesMap,
handleConnectToLine, emitters: $ws
handleTuneToLine, ? {
handleUserBroadcast, handleConnectToLine,
handleFetchMoreAudioBlocks, handleTuneToLine,
handleStartBroadcast,
handleStopBroadcast,
handleFetchMoreAudioBlocks,
}
: {},
}; };
} }
@@ -93,6 +93,14 @@ export default function Overlay() {
// socket.emit(SocketChannels.JOIN_LIVE_ROOM); // 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( // socket.on(
// SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, // SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS,
// (data: GetAllSocketClients) => { // (data: GetAllSocketClients) => {
@@ -7,6 +7,7 @@ import LineIcon from "../../../components/lines/lineIcon/index";
import { LineMemberState } from "@nirvana/core/models/line.model"; import { LineMemberState } from "@nirvana/core/models/line.model";
import MasterLineData from "@nirvana/core/models/masterLineData.model"; import MasterLineData from "@nirvana/core/models/masterLineData.model";
import { Tooltip } from "antd"; import { Tooltip } from "antd";
import { useGetUserDetails } from "../../../controller";
import { useLineDataProvider } from "../../../controller/lineDataProvider"; import { useLineDataProvider } from "../../../controller/lineDataProvider";
import { useRecoilState } from "recoil"; import { useRecoilState } from "recoil";
@@ -15,11 +16,22 @@ export default function LineDetailsTerminal({
}: { }: {
selectedLine: MasterLineData; selectedLine: MasterLineData;
}) { }) {
const { data: userDetails } = useGetUserDetails();
const isUserToggleTuned = useMemo( const isUserToggleTuned = useMemo(
() => selectedLine?.currentUserMember?.state === LineMemberState.TUNED, () => selectedLine?.currentUserMember?.state === LineMemberState.TUNED,
[selectedLine] [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 ( return (
<> <>
<div className="flex flex-col flex-1 bg-gray-100 items-stretch justify-start relative border-l border-l-gray-100"> <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" /> <FiSettings className="text-gray-400 text-md" />
</button> </button>
{/* TODO: move to on hover of line row */}
<Tooltip <Tooltip
title={`${ title={`${
isUserToggleTuned ? "toggle tuned" : "temporarily tuned" isUserToggleTuned ? "click to untoggle" : "click to stay tuned in"
}`} }`}
> >
<button <button
@@ -69,11 +82,10 @@ export default function LineDetailsTerminal({
</button> </button>
</Tooltip> </Tooltip>
{/* TODO: change to border and inset color for when inactive button */}
<button <button
className={`p-3 flex justify-center items-center shadow-lg className={`p-3 flex justify-center items-center shadow-lg
hover:scale-105 transition-all ${ hover:scale-105 transition-all ${
selectedLine.isUserBroadcasting || selectedLine.isOtherBroadcasting isUserBroadcasting
? "bg-teal-800 text-white" ? "bg-teal-800 text-white"
: "text-teal-800 border-teal-800 border" : "text-teal-800 border-teal-800 border"
}`} }`}
+8
View File
@@ -27,6 +27,14 @@ body {
cursor: pointer; cursor: pointer;
} }
/* TODO: temporary...remove? later? */
body {
-webkit-user-select: none;
-webkit-app-region: drag;
cursor: pointer;
}
.titlebar-button { .titlebar-button {
-webkit-app-region: no-drag; -webkit-app-region: no-drag;
} }