reogranized with a simple socket extension to data provider
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { Line, LineMember } from "@nirvana/core/models/line.model";
|
||||
import {
|
||||
Line,
|
||||
LineMember,
|
||||
LineMemberState,
|
||||
} from "@nirvana/core/models/line.model";
|
||||
import { client, collections } from "./database.service";
|
||||
|
||||
import NirvanaResponse from "@nirvana/core/responses/nirvanaResponse";
|
||||
import { ObjectId } from "mongodb";
|
||||
|
||||
export class LineService {
|
||||
@@ -109,4 +114,32 @@ export class LineService {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async updateLineMemberState(
|
||||
lineId: string,
|
||||
userId: string,
|
||||
newState: LineMemberState
|
||||
) {
|
||||
const query = { lineId, userId: new ObjectId(userId) };
|
||||
const updateSet = { $set: { state: newState, lastVisitDate: new Date() } };
|
||||
|
||||
const updateRes = await collections.lineMembers?.findOneAndUpdate(
|
||||
query,
|
||||
updateSet
|
||||
);
|
||||
|
||||
return updateRes;
|
||||
}
|
||||
|
||||
static async updateLineMemberVisitDate(lineId: string, userId: string) {
|
||||
const query = { lineId, userId: new ObjectId(userId) };
|
||||
const updateSet = { $set: { lastVisitDate: new Date() } };
|
||||
|
||||
const updateRes = await collections.lineMembers?.findOneAndUpdate(
|
||||
query,
|
||||
updateSet
|
||||
);
|
||||
|
||||
return updateRes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import SocketChannels, {
|
||||
|
||||
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
|
||||
import { JwtClaims } from "../middleware/auth";
|
||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
||||
import { LineService } from "../services/line.service";
|
||||
import ReceiveSignal from "@nirvana/core/sockets/receiveSignal";
|
||||
import SendSignal from "@nirvana/core/sockets/sendSignal";
|
||||
import { UserService } from "../services/user.service";
|
||||
@@ -79,7 +81,7 @@ export default function InitializeWs(io: any) {
|
||||
});
|
||||
|
||||
/** TUNE | User tunes into the line either temporarily or toggled in */
|
||||
socket.on(SocketChannels.TUNE_TO_LINE, (req: TuneToLine) => {
|
||||
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}`;
|
||||
@@ -87,11 +89,29 @@ export default function InitializeWs(io: any) {
|
||||
|
||||
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]);
|
||||
|
||||
io.in(roomName).emit(
|
||||
// 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)
|
||||
);
|
||||
|
||||
@@ -61,3 +61,7 @@ export class UserBroadcastPull {
|
||||
public isTurningOn: boolean = true
|
||||
) {}
|
||||
}
|
||||
|
||||
export class SocketEmitter<T> {
|
||||
constructor(public channel: SocketChannels, data: T) {}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@ import {
|
||||
ConnectToLine,
|
||||
SomeoneConnected,
|
||||
SomeoneTuned,
|
||||
TuneToLine,
|
||||
UserBroadcastPull,
|
||||
UserBroadcastingPush,
|
||||
} from "@nirvana/core/sockets/channels";
|
||||
import React, { useContext } from "react";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { Socket, io } from "socket.io-client";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
|
||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
||||
import SocketChannels from "@nirvana/core/sockets/channels";
|
||||
@@ -18,35 +19,39 @@ import toast from "react-hot-toast";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { useUserLines } from "./index";
|
||||
|
||||
type LineIdToMasterLine = {
|
||||
[lineId: string]: MasterLineData;
|
||||
};
|
||||
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<ILineDataContext>({
|
||||
linesMap: {},
|
||||
relevantUsers: [],
|
||||
handleUserBroadcast: (lineId: string, isTurningOn: boolean = true) => {},
|
||||
});
|
||||
|
||||
let $ws: Socket;
|
||||
|
||||
export function LineDataProvider({ children }) {
|
||||
// TODO: have internal loading to prevent showing even router and all if something is not ready
|
||||
// or have it within each property within the context value
|
||||
|
||||
// persistent store of lines
|
||||
// ?just do simple synchronous axios/fetch in useEffect and manage isLoading ourselves?
|
||||
const { data: basicUserLinesData } = useUserLines();
|
||||
export function useSocketHandler(linesData: MasterLineData[]) {
|
||||
const jwtToken = useRecoilValue($jwtToken);
|
||||
|
||||
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]);
|
||||
|
||||
useEffect(() => {
|
||||
$ws = io("http://localhost:5000", {
|
||||
query: { token: jwtToken },
|
||||
@@ -99,53 +104,15 @@ export function LineDataProvider({ children }) {
|
||||
`someone or myself buzz on or off in line ${pull.lineId}`
|
||||
);
|
||||
|
||||
setLinesMap((prevLinesMap) => {
|
||||
const newMap = { ...prevLinesMap };
|
||||
const newMap = {};
|
||||
|
||||
// todo: check if it's the user or someone else broadcasting
|
||||
// todo: check if it's the user or someone else broadcasting
|
||||
|
||||
if (newMap[pull.lineId])
|
||||
newMap[pull.lineId].isUserBroadcasting = pull.isTurningOn;
|
||||
|
||||
return newMap;
|
||||
});
|
||||
if (newMap[pull.lineId])
|
||||
newMap[pull.lineId].isUserBroadcasting = pull.isTurningOn;
|
||||
}
|
||||
);
|
||||
}, [setLinesMap]);
|
||||
|
||||
// connect through ws to enrich basic lines data
|
||||
useEffect(() => {
|
||||
console.log("got basic user lines data!!!");
|
||||
|
||||
// ?need to calculate diff and only do stuff then?
|
||||
|
||||
// $ws.on(SocketChannels.CONNECT, console.log());
|
||||
|
||||
$ws.on("test", () => console.log("test"));
|
||||
|
||||
if (basicUserLinesData?.data?.masterLines.length > 0) {
|
||||
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 };
|
||||
|
||||
basicUserLinesData.data.masterLines.map((masterLine) => {
|
||||
newMap[masterLine.lineDetails._id.toString()] = masterLine;
|
||||
|
||||
handleConnectToLine(masterLine.lineDetails._id.toString());
|
||||
|
||||
// tune into lines
|
||||
});
|
||||
|
||||
return newMap;
|
||||
});
|
||||
}
|
||||
}, [basicUserLinesData]);
|
||||
}, []);
|
||||
|
||||
const handleConnectToLine = (lineId: string) => {
|
||||
$ws.emit(SocketChannels.CONNECT_TO_LINE, new ConnectToLine(lineId));
|
||||
@@ -160,7 +127,8 @@ export function LineDataProvider({ children }) {
|
||||
// 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));
|
||||
|
||||
$ws.emit(SocketChannels.TUNE_TO_LINE, new TuneToLine(lineId, turnToggleOn));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -197,13 +165,45 @@ export function LineDataProvider({ children }) {
|
||||
// update the specific line in lines map
|
||||
// set the state to trigger the re-renders in the tree
|
||||
},
|
||||
[setLinesMap]
|
||||
[$ws]
|
||||
);
|
||||
|
||||
return {
|
||||
linesMap,
|
||||
handleConnectToLine,
|
||||
handleTuneToLine,
|
||||
handleUserBroadcast,
|
||||
handleFetchMoreAudioBlocks,
|
||||
};
|
||||
}
|
||||
|
||||
export type LineIdToMasterLine = {
|
||||
[lineId: string]: MasterLineData;
|
||||
};
|
||||
interface ILineDataContext {
|
||||
// represents the modified and up to date lines data with availability from session
|
||||
linesMap: LineIdToMasterLine;
|
||||
relevantUsers: User[];
|
||||
}
|
||||
|
||||
const LineDataContext = React.createContext<ILineDataContext>({
|
||||
linesMap: {},
|
||||
relevantUsers: [],
|
||||
});
|
||||
|
||||
export function LineDataProvider({ children }) {
|
||||
// TODO: have internal loading to prevent showing even router and all if something is not ready
|
||||
// or have it within each property within the context value
|
||||
|
||||
// persistent store of lines
|
||||
// ?just do simple synchronous axios/fetch in useEffect and manage isLoading ourselves?
|
||||
const { data: basicUserLinesData } = useUserLines();
|
||||
|
||||
const { linesMap } = useSocketHandler(basicUserLinesData?.data?.masterLines);
|
||||
|
||||
const value: ILineDataContext = {
|
||||
linesMap, // TODO send the updated map instead of this array
|
||||
relevantUsers: [],
|
||||
handleUserBroadcast,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import SocketChannels from "@nirvana/core/sockets/channels";
|
||||
import { io } from "socket.io-client";
|
||||
|
||||
const $ws = io("http://localhost:5000");
|
||||
|
||||
export default $ws;
|
||||
|
||||
@@ -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, handleUserBroadcast } = useLineDataProvider();
|
||||
const { linesMap } = useLineDataProvider();
|
||||
|
||||
const allLines: MasterLineData[] = useMemo(() => {
|
||||
const masterLines: MasterLineData[] = Object.values(linesMap);
|
||||
@@ -59,7 +59,7 @@ export default function NirvanaTerminal() {
|
||||
|
||||
// todo: enable stream in this tuned in channel
|
||||
|
||||
if (lineId) handleUserBroadcast(lineId, true);
|
||||
// if (lineId) handleUserBroadcast(lineId, true);
|
||||
},
|
||||
[]
|
||||
);
|
||||
@@ -70,7 +70,7 @@ export default function NirvanaTerminal() {
|
||||
|
||||
// todo: disable stream in this tuned in channel
|
||||
|
||||
if (lineId) handleUserBroadcast(lineId, false);
|
||||
// if (lineId) handleUserBroadcast(lineId, false);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user