192 lines
6.1 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
}
|