good progress on socket mesh
This commit is contained in:
+143
-86
@@ -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", () => {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
}`}
|
}`}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user