319 lines
9.2 KiB
TypeScript
319 lines
9.2 KiB
TypeScript
import { Avatar, Badge } from "antd";
|
|
import { useRouter } from "next/router";
|
|
import {
|
|
FaDotCircle,
|
|
FaWalking,
|
|
FaRocket,
|
|
FaCheckDouble,
|
|
FaCircle,
|
|
FaUser,
|
|
FaRegClock,
|
|
FaCheck,
|
|
FaAngleRight,
|
|
FaGithub,
|
|
FaAtlassian,
|
|
} from "react-icons/fa";
|
|
import { Routes } from "@nirvana/common/helpers/routes";
|
|
import LiveRoom from "../Conversations/LiveRoom";
|
|
import Conversation from "@nirvana/common/models/conversation";
|
|
import { useRecoilValue } from "recoil";
|
|
import {
|
|
countNavigationContentSelector,
|
|
liveRoomsSelector,
|
|
RelativeTimeConvosSections,
|
|
RelativeTimeSeparatedConvosSelector,
|
|
} from "../../recoil/main";
|
|
import ConversationFullRow from "../Conversations/ConversationFullRow";
|
|
import LiveRooms from "../LiveRooms/LiveRoomsHandler";
|
|
import LiveRoomsHandler from "../LiveRooms/LiveRoomsHandler";
|
|
import {
|
|
ClientConfig,
|
|
IAgoraRTC,
|
|
IAgoraRTCClient,
|
|
IMicrophoneAudioTrack,
|
|
} from "agora-rtc-sdk-ng";
|
|
import { useEffect, useState } from "react";
|
|
import { config, appId } from "@nirvana/common/services/agoraService";
|
|
import toast from "react-hot-toast";
|
|
import { agoraService, conversationService } from "@nirvana/common/services";
|
|
import { useAuth } from "../../contexts/authContext";
|
|
|
|
export default function Conversations() {
|
|
const router = useRouter();
|
|
|
|
const { currUser } = useAuth();
|
|
|
|
const liveRooms = useRecoilValue(liveRoomsSelector);
|
|
|
|
const [agoraRtc, setAgoraRtc] = useState<IAgoraRTC>();
|
|
const [agoraRtcClient, setAgoraRtcClient] = useState<IAgoraRTCClient>();
|
|
const [localAudioTrack, setLocalAudioTrack] =
|
|
useState<IMicrophoneAudioTrack>();
|
|
|
|
// set up agora stuff
|
|
useEffect(() => {
|
|
(async function () {
|
|
// dynamic import as the server side import doesn't work
|
|
const AgoraRTC = (await import("agora-rtc-sdk-ng")).default;
|
|
const agoraClient = AgoraRTC.createClient(config);
|
|
|
|
setAgoraRtcClient(agoraClient);
|
|
setAgoraRtc(AgoraRTC);
|
|
})();
|
|
}, []);
|
|
|
|
async function handleJoinChannel(channelName: string, agoraToken: string) {
|
|
const localTrack: IMicrophoneAudioTrack =
|
|
await agoraRtc!.createMicrophoneAudioTrack();
|
|
|
|
setLocalAudioTrack(localTrack);
|
|
|
|
const init = async (chanName: string) => {
|
|
agoraRtcClient!.on("user-published", async (user, mediaType) => {
|
|
await agoraRtcClient!.subscribe(user, mediaType);
|
|
console.log("subscribe success");
|
|
|
|
if (mediaType === "audio") {
|
|
user.audioTrack?.play();
|
|
}
|
|
});
|
|
|
|
agoraRtcClient!.on("user-unpublished", async (user, type) => {
|
|
console.log("unpublished", user, type);
|
|
if (type === "audio") {
|
|
user.audioTrack?.stop();
|
|
}
|
|
|
|
await agoraRtcClient!.unsubscribe(user);
|
|
});
|
|
|
|
agoraRtcClient!.on("user-left", (user) => {
|
|
console.log("user left", user);
|
|
});
|
|
|
|
await agoraRtcClient!.join(appId, chanName, agoraToken, null);
|
|
if (localTrack) await agoraRtcClient!.publish(localTrack);
|
|
};
|
|
|
|
if (localTrack) {
|
|
console.log("init ready");
|
|
init(channelName);
|
|
} else {
|
|
toast.error("Not ready for joining call");
|
|
return;
|
|
}
|
|
}
|
|
|
|
async function handleLeaveChannel() {
|
|
// destroy local track
|
|
localAudioTrack?.close();
|
|
|
|
// leave all channels
|
|
await agoraRtcClient!.leave();
|
|
}
|
|
|
|
// click on join
|
|
// add me to the active list of people in the call
|
|
// update the conversation lastActivityDate as well
|
|
|
|
const handleJoinLive = async (conversationId: string) => {
|
|
const connectingToast = toast.loading("connecting");
|
|
|
|
try {
|
|
// agora token from CF
|
|
const agoraToken = await agoraService.getAgoraToken(conversationId);
|
|
|
|
// agora join/init
|
|
await handleJoinChannel(conversationId, agoraToken);
|
|
|
|
await conversationService.joinLiveConversation(
|
|
conversationId,
|
|
currUser!.uid
|
|
);
|
|
} catch {
|
|
toast.error("problem in joining");
|
|
}
|
|
|
|
toast.remove(connectingToast);
|
|
toast.success("joined room");
|
|
};
|
|
|
|
const handleLeaveLive = async (conversationId: string) => {
|
|
const leavingToast = toast.loading("leaving");
|
|
|
|
try {
|
|
// agora leave channel
|
|
await handleLeaveChannel();
|
|
|
|
await conversationService.leaveLiveConversation(
|
|
conversationId,
|
|
currUser!.uid
|
|
);
|
|
} catch {
|
|
toast.error("problem in joining");
|
|
}
|
|
|
|
toast.remove(leavingToast);
|
|
toast.success("left room");
|
|
};
|
|
|
|
// agora start the call stream
|
|
|
|
// leave the call on before unload if in a call
|
|
|
|
// update the database to remove my userId from the list of people in the room
|
|
|
|
const relativeConvoSections = useRecoilValue(
|
|
RelativeTimeSeparatedConvosSelector
|
|
);
|
|
|
|
const todayConvos = relativeConvoSections.get(
|
|
RelativeTimeConvosSections.today
|
|
);
|
|
const last7DaysConvos = relativeConvoSections.get(
|
|
RelativeTimeConvosSections.last7Days
|
|
);
|
|
const earlierMonthConvos = relativeConvoSections.get(
|
|
RelativeTimeConvosSections.earlierThisMonth
|
|
);
|
|
const oldJunkConvos = relativeConvoSections.get(
|
|
RelativeTimeConvosSections.oldJunk
|
|
);
|
|
|
|
const navConvoCounts = useRecoilValue(countNavigationContentSelector);
|
|
const isStaleState =
|
|
navConvoCounts.liveCount == 0 && navConvoCounts.defaultCount == 0;
|
|
|
|
if (isStaleState) {
|
|
return (
|
|
<div className="mx-auto my-auto flex flex-col">
|
|
<img
|
|
src="/illustrations/undraw_meditation_re_gll0.svg"
|
|
className="h-[15rem] mx-auto my-auto"
|
|
/>
|
|
|
|
<span></span>
|
|
<span className="text-slate-400 text-center mt-5">
|
|
{"Oh the sound of silence..."}
|
|
</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{/* live rooms */}
|
|
{liveRooms?.length > 0 && (
|
|
<>
|
|
<span className="flex flex-row items-center mb-5 px-5 w-full">
|
|
<FaDotCircle className="text-orange-500 text-lg mr-1" />
|
|
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase">
|
|
Live
|
|
</span>
|
|
</span>
|
|
|
|
{/* row of live room cards */}
|
|
<span className="flex flex-col w-full items-stretch">
|
|
{liveRooms.map((lRoom) => (
|
|
<LiveRoom
|
|
key={lRoom.id}
|
|
conversation={lRoom}
|
|
handleJoinLive={handleJoinLive}
|
|
handleLeaveLive={handleLeaveLive}
|
|
/>
|
|
))}
|
|
</span>
|
|
</>
|
|
)}
|
|
|
|
{/* Today */}
|
|
{todayConvos && todayConvos?.length > 0 && (
|
|
<>
|
|
<span className="flex flex-row items-center mb-5 px-5 w-full mt-10">
|
|
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase">
|
|
Today
|
|
</span>
|
|
</span>
|
|
<span className="flex flex-col w-full items-stretch">
|
|
{todayConvos.map((tRoom) => (
|
|
<ConversationFullRow
|
|
key={tRoom.id}
|
|
conversation={tRoom}
|
|
handleJoinLive={handleJoinLive}
|
|
handleLeaveLive={handleLeaveLive}
|
|
/>
|
|
))}
|
|
</span>
|
|
</>
|
|
)}
|
|
|
|
{/* last 7 days */}
|
|
{last7DaysConvos && last7DaysConvos?.length > 0 && (
|
|
<>
|
|
<span className="flex flex-row items-center mb-5 px-5 w-full mt-10">
|
|
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase">
|
|
Last 7 Days
|
|
</span>
|
|
</span>
|
|
<span className="flex flex-col w-full items-stretch">
|
|
{last7DaysConvos.map((tRoom) => (
|
|
<ConversationFullRow
|
|
key={tRoom.id}
|
|
conversation={tRoom}
|
|
handleJoinLive={handleJoinLive}
|
|
handleLeaveLive={handleLeaveLive}
|
|
/>
|
|
))}
|
|
</span>
|
|
</>
|
|
)}
|
|
|
|
{/* earlier this month */}
|
|
{earlierMonthConvos && earlierMonthConvos?.length > 0 && (
|
|
<>
|
|
<span className="flex flex-row items-center mb-5 px-5 w-full mt-10">
|
|
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase">
|
|
Earlier This Month
|
|
</span>
|
|
</span>
|
|
<span className="flex flex-col w-full items-stretch">
|
|
{earlierMonthConvos.map((tRoom) => (
|
|
<ConversationFullRow
|
|
key={tRoom.id}
|
|
conversation={tRoom}
|
|
handleJoinLive={handleJoinLive}
|
|
handleLeaveLive={handleLeaveLive}
|
|
/>
|
|
))}
|
|
</span>
|
|
</>
|
|
)}
|
|
|
|
{/* old junk */}
|
|
{oldJunkConvos && oldJunkConvos?.length > 0 && (
|
|
<>
|
|
<span className="flex flex-row items-center mb-5 px-5 w-full mt-10">
|
|
<span className="text-md tracking-widest font-semibold text-slate-300 uppercase">
|
|
Older Junk
|
|
</span>
|
|
</span>
|
|
<span className="flex flex-col w-full items-stretch">
|
|
{oldJunkConvos.map((tRoom) => (
|
|
<ConversationFullRow
|
|
key={tRoom.id}
|
|
conversation={tRoom}
|
|
handleJoinLive={handleJoinLive}
|
|
handleLeaveLive={handleLeaveLive}
|
|
/>
|
|
))}
|
|
</span>
|
|
</>
|
|
)}
|
|
|
|
<span className="mx-auto mt-5 text-slate-300 flex flex-col">
|
|
<span className="">{"That's all"}</span>
|
|
</span>
|
|
</>
|
|
);
|
|
}
|