Files
2022-02-07 22:07:29 -08:00

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>
</>
);
}