Files
nirvana-v3/packages/desktop/src/pages/Home/selectedConversation/index.tsx
T

192 lines
6.1 KiB
TypeScript

import {
Querytypes,
useConversationDetails,
useGetUserDetails,
useSendContactRequest,
useUpdateRelationshipState,
} from "../../../controller";
import { $selectedConversation } from "../../../controller/recoil";
import { Dimensions } from "../../../electron/constants";
import { FaWindowClose } from "react-icons/fa";
import { GlobalHotKeys } from "react-hotkeys";
import { RelationshipState } from "@nirvana/core/models/relationship.model";
import SocketChannels from "@nirvana/core/sockets/channels";
import UpdateRelationshipStateRequest from "@nirvana/core/requests/updateRelationshipState.request";
import UserStatusText from "../../../components/User/userStatusText";
import moment from "moment";
import { queryClient } from "../../../nirvanaApp";
import { socket } from "../../../nirvanaApp";
import { useEffect } from "react";
import { useRecoilState } from "recoil";
export default function SelectedConversation() {
const [selectedConvo, setSelectedConvo] = useRecoilState(
$selectedConversation
);
const { data: userDetailsData } = useGetUserDetails();
const { data: convoDetailsResponse, isFetching } =
useConversationDetails(selectedConvo);
const { mutate: sendContactRequest } = useSendContactRequest();
const { mutate: updateRelationshipState } = useUpdateRelationshipState();
useEffect(() => {
// if selected, then change the bounds of this window as well
if (selectedConvo) {
window.electronAPI.window.resizeWindow(Dimensions.selectedConvo);
} else {
// change bounds back
window.electronAPI.window.resizeWindow(Dimensions.default);
}
}, [selectedConvo]);
// if no convo selected, don't show this
if (!selectedConvo) {
return <></>;
}
if (isFetching) {
return <span className="text-slate-200">Loading conversation details</span>;
}
// todo: add cancel request option
const sendRequest = () => {
const otherUserGoogleId = convoDetailsResponse.contactUser.googleId;
// todo mutation to create a user
sendContactRequest(otherUserGoogleId, {
onSettled: (data, error) => {
return queryClient.invalidateQueries(
Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId
);
},
});
};
const acceptRequest = () => {
const otherUserGoogleId = convoDetailsResponse.contactUser.googleId;
updateRelationshipState(
new UpdateRelationshipStateRequest(
convoDetailsResponse.ourRelationship._id,
RelationshipState.ACTIVE
),
{
onSettled: (data, error) => {
return queryClient.invalidateQueries(
Querytypes.GET_CONVERSATION_DETAILS + "/" + otherUserGoogleId
);
},
}
);
};
if (isFetching) return <span>Please wait</span>;
const renderMainContent = () => {
// if there's no relationship, then don't show messages, show "send request" button
if (!convoDetailsResponse?.ourRelationship) {
return <button onClick={sendRequest}>Send Request</button>;
}
// if the relationship is pending and I am the receiver, then I should see an accept or deny button
if (
convoDetailsResponse.ourRelationship.state ===
RelationshipState.PENDING &&
userDetailsData.googleId ===
convoDetailsResponse.ourRelationship.receiverUserId
) {
return (
<span>
please accept this request by clicking here:{" "}
<button onClick={acceptRequest}>accept</button>
</span>
);
}
// when i sent a request to this person, just tell me that I have to wait
if (
convoDetailsResponse.ourRelationship.state ===
RelationshipState.PENDING &&
userDetailsData.googleId ===
convoDetailsResponse.ourRelationship.senderUserId
) {
return <span>Waiting on request to be accepted</span>;
}
if (
convoDetailsResponse.ourRelationship.state === RelationshipState.ACTIVE
) {
return <span>this is all of the content</span>;
}
if (
convoDetailsResponse.ourRelationship.state === RelationshipState.DENIED
) {
return <span>this request was denied</span>;
}
};
// emit to room/conversation that someone started speaking
const socketStartedSpeaking = () => {
// send the room name and the update type
socket.emit(SocketChannels.SEND_STARTED_SPEAKING_TO_SERVER, selectedConvo);
};
const socketStopSpeaking = () => {
// send the room name and the update type
socket.emit(SocketChannels.SEND_STOPPED_SPEAKING_TO_SERVER, selectedConvo);
};
// hot keys for closing this window
const handleClose = () => {
setSelectedConvo(null);
};
const keyMap = { CLOSE_SELECTED_CONVO: "esc" };
const handlers = { CLOSE_SELECTED_CONVO: handleClose };
return (
<>
<GlobalHotKeys handlers={handlers} keyMap={keyMap}></GlobalHotKeys>
<div className="bg-slate-800 flex-1 flex flex-col relative">
{/* close marker */}
<FaWindowClose
onClick={handleClose}
className="text-slate-400 text-xl hover:text-slate-200 hover:scale-110 absolute top-0 right-0 m-1 cursor-pointer"
/>
{/* top header/profile information */}
<span className="flex flex-row justify-start items-center p-2">
<img
className="rounded"
src={convoDetailsResponse.contactUser.picture}
/>
<span className="flex flex-col items-start pl-2">
<span className="flex flex-row space-x-2 items-center">
<span className="text-white font-semibold text-lg">
{convoDetailsResponse.contactUser.name}
</span>
<UserStatusText
status={convoDetailsResponse.contactUser.status}
/>
</span>
<span className="text-slate-300 text-sm">{`joined ${moment(
convoDetailsResponse.contactUser.createdDate
).fromNow()}`}</span>
</span>
</span>
{renderMainContent()}
<button onClick={socketStartedSpeaking}>start speaking</button>
<button onClick={socketStopSpeaking}>stop speaking</button>
</div>
</>
);
}