(feat): replace toast with popup for call invites
(qol): update todo
This commit is contained in:
parent
25e47604b3
commit
6fda7f1c71
4 changed files with 113 additions and 27 deletions
|
|
@ -24,7 +24,6 @@ import {
|
|||
getLogger,
|
||||
} from "livekit-client";
|
||||
import z from "zod";
|
||||
import { toast as sonnerToast } from "sonner";
|
||||
import {
|
||||
createScreenShareController,
|
||||
type ScreenShareSession,
|
||||
|
|
@ -33,6 +32,7 @@ import {
|
|||
getSpeakingDetector,
|
||||
disposeSpeakingDetector,
|
||||
} from "./speakingIndicator";
|
||||
import InvitePopup from "./components/invitePopup";
|
||||
|
||||
// logging
|
||||
setLogExtension(
|
||||
|
|
@ -45,6 +45,11 @@ setLogExtension(
|
|||
|
||||
type CallState = "closed" | "closing" | "connecting" | "open" | "encrypting";
|
||||
type CallView = "preview" | "focused" | "grid";
|
||||
type IncomingCallInvite = {
|
||||
callId: string;
|
||||
callSecret: string;
|
||||
senderId: number;
|
||||
};
|
||||
type CurrentCallData =
|
||||
| (z.infer<typeof ttp.call_data.response> & { exists: boolean })
|
||||
| null;
|
||||
|
|
@ -83,6 +88,7 @@ type CallStore = {
|
|||
view: CallView;
|
||||
invitedUserId: number | null;
|
||||
callId: string | null;
|
||||
incomingCallInvite: IncomingCallInvite | null;
|
||||
callSecret: string | null;
|
||||
livekitToken: string | null;
|
||||
currentCallData: CurrentCallData;
|
||||
|
|
@ -837,6 +843,7 @@ export async function disconnect() {
|
|||
state: "closing",
|
||||
invitedUserId: null,
|
||||
callId: null,
|
||||
incomingCallInvite: null,
|
||||
callSecret: null,
|
||||
livekitToken: null,
|
||||
currentCallData: null,
|
||||
|
|
@ -999,6 +1006,7 @@ export function resetCallState() {
|
|||
view: "preview",
|
||||
invitedUserId: null,
|
||||
callId: null,
|
||||
incomingCallInvite: null,
|
||||
callSecret: null,
|
||||
livekitToken: null,
|
||||
currentCallData: null,
|
||||
|
|
@ -1050,6 +1058,7 @@ export const useCall = create<CallStore>(() => ({
|
|||
view: "preview",
|
||||
invitedUserId: null,
|
||||
callId: null,
|
||||
incomingCallInvite: null,
|
||||
callSecret: null,
|
||||
livekitToken: null,
|
||||
currentCallData: null,
|
||||
|
|
@ -1084,6 +1093,7 @@ export function useInitializeCall() {
|
|||
|
||||
const callId = useCall((state) => state.callId);
|
||||
const view = useCall((state) => state.view);
|
||||
const incomingCallInvite = useCall((state) => state.incomingCallInvite);
|
||||
|
||||
const listenersRegistered = useRef(false);
|
||||
const noiseFilter = useMemo(
|
||||
|
|
@ -1113,32 +1123,44 @@ export function useInitializeCall() {
|
|||
}, [decryptText, encryptText, get, getSharedSecret, load, navigate, send]);
|
||||
|
||||
const showCallingScreen = useCallback(
|
||||
async (callId: string, callSecret: string, senderId: number) => {
|
||||
const senderName = await get(senderId).then((data) => data.display);
|
||||
|
||||
sonnerToast(`Incoming call from ${senderName}`, {
|
||||
action: {
|
||||
label: "Accept",
|
||||
onClick: () => {
|
||||
joinCall(senderId, callSecret, callId, false).catch((err) => {
|
||||
log(1, "call", "red", "Failed to join call", err);
|
||||
});
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
label: "Decline",
|
||||
onClick: () => {
|
||||
log(2, "call", "purple", "Declined call invite", {
|
||||
callId,
|
||||
senderId,
|
||||
});
|
||||
},
|
||||
},
|
||||
(callId: string, callSecret: string, senderId: number) => {
|
||||
useCall.setState({
|
||||
incomingCallInvite: { callId, callSecret, senderId },
|
||||
});
|
||||
},
|
||||
[get],
|
||||
[],
|
||||
);
|
||||
|
||||
const setInvitePopupOpen = useCallback((open: boolean) => {
|
||||
if (!open) {
|
||||
useCall.setState({ incomingCallInvite: null });
|
||||
}
|
||||
}, []);
|
||||
|
||||
const respondToInvite = useCallback((accepted: boolean) => {
|
||||
const invite = useCall.getState().incomingCallInvite;
|
||||
|
||||
useCall.setState({ incomingCallInvite: null });
|
||||
|
||||
if (!invite) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (accepted) {
|
||||
joinCall(invite.senderId, invite.callSecret, invite.callId, false).catch(
|
||||
(err) => {
|
||||
log(1, "call", "red", "Failed to join call", err);
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
log(2, "call", "purple", "Declined call invite", {
|
||||
callId: invite.callId,
|
||||
senderId: invite.senderId,
|
||||
});
|
||||
}, []);
|
||||
|
||||
// listen to call invites
|
||||
useEffect(() => {
|
||||
subscribePush(async (message) => {
|
||||
|
|
@ -1482,4 +1504,13 @@ export function useInitializeCall() {
|
|||
});
|
||||
});
|
||||
}, [callId, send, view]);
|
||||
|
||||
return incomingCallInvite ? (
|
||||
<InvitePopup
|
||||
open
|
||||
setOpen={setInvitePopupOpen}
|
||||
onAccept={respondToInvite}
|
||||
user={incomingCallInvite.senderId}
|
||||
/>
|
||||
) : null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue