(fix): joining a call while already being in a call wouldn't reset the call state
(qol): format
This commit is contained in:
parent
be26e486d4
commit
4dbf48b3f9
8 changed files with 85 additions and 50 deletions
|
|
@ -1,10 +1,5 @@
|
|||
import { useTTP } from "@tensamin/ttp";
|
||||
import {
|
||||
Button,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@tensamin/ui";
|
||||
import { Button, Popover, PopoverContent, PopoverTrigger } from "@tensamin/ui";
|
||||
import Wrapper from "@tensamin/user/wrapper";
|
||||
import { Mail } from "lucide-react";
|
||||
import { sendCallInvite } from "../../store";
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ export default function Base({
|
|||
{/* Detect video / user and place here */}
|
||||
|
||||
{type === "stream" &&
|
||||
(screenSharePublication?.isSubscribed && screenSharePublication.track ? (
|
||||
(screenSharePublication?.isSubscribed &&
|
||||
screenSharePublication.track ? (
|
||||
<VideoViewer
|
||||
flush={flush}
|
||||
participantId={participant.identity}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,15 @@ export default function TopBar() {
|
|||
const room = useCall((state) => state.room);
|
||||
const view = useCall((state) => state.view);
|
||||
|
||||
const userIds = Array.from(room.remoteParticipants.values(), (participant) => {
|
||||
const participantId = Number(participant.identity);
|
||||
return Number.isInteger(participantId) && participantId > 0
|
||||
? participantId
|
||||
: null;
|
||||
}).filter((participantId): participantId is number => participantId != null);
|
||||
const userIds = Array.from(
|
||||
room.remoteParticipants.values(),
|
||||
(participant) => {
|
||||
const participantId = Number(participant.identity);
|
||||
return Number.isInteger(participantId) && participantId > 0
|
||||
? participantId
|
||||
: null;
|
||||
},
|
||||
).filter((participantId): participantId is number => participantId != null);
|
||||
const userIdsKey = userIds.join(",");
|
||||
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,13 @@ export function createScreenShareController({
|
|||
await Promise.all(
|
||||
screenShareSession.tracks.map((track) =>
|
||||
room.localParticipant.unpublishTrack(track, true).catch((error) => {
|
||||
log(1, "call", "red", "Failed to unpublish screen share track", error);
|
||||
log(
|
||||
1,
|
||||
"call",
|
||||
"red",
|
||||
"Failed to unpublish screen share track",
|
||||
error,
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
|
@ -194,15 +200,12 @@ export function createScreenShareController({
|
|||
});
|
||||
}, 125);
|
||||
|
||||
await publishScreenShareTracks(
|
||||
[videoTrack],
|
||||
() => {
|
||||
stopped = true;
|
||||
window.clearInterval(interval);
|
||||
stream.getTracks().forEach((track) => track.stop());
|
||||
canvas.remove();
|
||||
},
|
||||
);
|
||||
await publishScreenShareTracks([videoTrack], () => {
|
||||
stopped = true;
|
||||
window.clearInterval(interval);
|
||||
stream.getTracks().forEach((track) => track.stop());
|
||||
canvas.remove();
|
||||
});
|
||||
}
|
||||
|
||||
async function stopScreenShare() {
|
||||
|
|
|
|||
|
|
@ -157,7 +157,8 @@ function getActiveScreenShareParticipantIds(): number[] {
|
|||
.map((participant) => ({
|
||||
participantId: getParticipantId(participant.identity),
|
||||
hasScreenShare:
|
||||
participant.getTrackPublication(Track.Source.ScreenShare)?.track != null,
|
||||
participant.getTrackPublication(Track.Source.ScreenShare)?.track !=
|
||||
null,
|
||||
}))
|
||||
.filter(
|
||||
(entry): entry is { participantId: number; hasScreenShare: true } =>
|
||||
|
|
@ -290,18 +291,21 @@ export async function sendCallInvite(userId: number) {
|
|||
|
||||
const ownUserId = (await runtime.load("user_id")) as number;
|
||||
const privateKey = await runtime.load("private_key");
|
||||
const ownPublicKey = await runtime.getUser(ownUserId).then(
|
||||
(data) => data.public_key,
|
||||
);
|
||||
const remotePublicKey = await runtime.getUser(userId).then(
|
||||
(data) => data.public_key,
|
||||
);
|
||||
const ownPublicKey = await runtime
|
||||
.getUser(ownUserId)
|
||||
.then((data) => data.public_key);
|
||||
const remotePublicKey = await runtime
|
||||
.getUser(userId)
|
||||
.then((data) => data.public_key);
|
||||
const sharedSecret = await runtime.getSharedSecret(
|
||||
privateKey,
|
||||
ownPublicKey,
|
||||
remotePublicKey,
|
||||
);
|
||||
const encryptedCallSecret = await runtime.encryptText(sharedSecret, callSecret);
|
||||
const encryptedCallSecret = await runtime.encryptText(
|
||||
sharedSecret,
|
||||
callSecret,
|
||||
);
|
||||
|
||||
await runtime.send("call_invite", {
|
||||
receiver_id: userId,
|
||||
|
|
@ -373,8 +377,9 @@ export function stopWatchingFocusedStream() {
|
|||
stopWatchingStream(focusedParticipantId);
|
||||
}
|
||||
|
||||
let screenShareController: ReturnType<typeof createScreenShareController> | null =
|
||||
null;
|
||||
let screenShareController: ReturnType<
|
||||
typeof createScreenShareController
|
||||
> | null = null;
|
||||
|
||||
function getScreenShareController() {
|
||||
if (!screenShareController) {
|
||||
|
|
@ -390,7 +395,8 @@ function getScreenShareController() {
|
|||
: updater,
|
||||
);
|
||||
},
|
||||
getLocalParticipantId: () => getParticipantId(room.localParticipant.identity),
|
||||
getLocalParticipantId: () =>
|
||||
getParticipantId(room.localParticipant.identity),
|
||||
startWatching: startWatchingStream,
|
||||
stopWatching: stopWatchingStream,
|
||||
syncParticipantState,
|
||||
|
|
@ -439,7 +445,13 @@ export async function disconnect() {
|
|||
try {
|
||||
await getScreenShareController().clearPublishedScreenShare();
|
||||
} catch (error) {
|
||||
log(1, "call", "red", "Failed to clear screen share during disconnect", error);
|
||||
log(
|
||||
1,
|
||||
"call",
|
||||
"red",
|
||||
"Failed to clear screen share during disconnect",
|
||||
error,
|
||||
);
|
||||
}
|
||||
|
||||
useCall.setState({
|
||||
|
|
@ -463,7 +475,7 @@ export async function disconnect() {
|
|||
});
|
||||
|
||||
try {
|
||||
room.disconnect();
|
||||
await room.disconnect();
|
||||
} catch (error) {
|
||||
log(1, "call", "red", "Failed to disconnect from room", error);
|
||||
} finally {
|
||||
|
|
@ -480,6 +492,11 @@ export async function joinCall(
|
|||
sendInvite = true,
|
||||
) {
|
||||
const runtime = requireRuntime(useCall.getState().runtime);
|
||||
const state = useCall.getState().state;
|
||||
|
||||
if (state !== "closed") {
|
||||
await disconnect();
|
||||
}
|
||||
|
||||
log(2, "call", "purple", "Call creation initialised");
|
||||
useCall.setState({
|
||||
|
|
@ -754,11 +771,10 @@ export function useInitializeCall() {
|
|||
|
||||
if (invitedUserId != null) {
|
||||
setTimeout(async () => {
|
||||
void sendCallInvite(invitedUserId)
|
||||
.catch((error) => {
|
||||
toast("error", "Failed to send call invite.");
|
||||
log(1, "call", "red", "Failed to send call invite", error);
|
||||
});
|
||||
void sendCallInvite(invitedUserId).catch((error) => {
|
||||
toast("error", "Failed to send call invite.");
|
||||
log(1, "call", "red", "Failed to send call invite", error);
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@ export default function View() {
|
|||
(state) => state.activeScreenShareParticipantIds,
|
||||
);
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [focusedTileSize, setFocusedTileSize] = useState({ width: 0, height: 0 });
|
||||
const [focusedTileSize, setFocusedTileSize] = useState({
|
||||
width: 0,
|
||||
height: 0,
|
||||
});
|
||||
const [isFocusedTileFlush, setIsFocusedTileFlush] = useState(false);
|
||||
const [participantVersion, setParticipantVersion] = useState(0);
|
||||
|
||||
|
|
@ -42,7 +45,7 @@ export default function View() {
|
|||
const participantId = Number(participant.identity);
|
||||
return Number.isInteger(participantId) && participantId > 0;
|
||||
});
|
||||
// eslint-disable-next-line
|
||||
// eslint-disable-next-line
|
||||
}, [participantVersion, room]);
|
||||
|
||||
const userIds = useMemo(
|
||||
|
|
@ -141,7 +144,10 @@ export default function View() {
|
|||
activeScreenShareParticipantIdSet.has(focusedParticipantId);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="flex h-full w-full items-center justify-center overflow-hidden">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="flex h-full w-full items-center justify-center overflow-hidden"
|
||||
>
|
||||
<div
|
||||
className="flex max-h-full w-full flex-col items-center overflow-hidden"
|
||||
style={{ gap: tiles.length > 0 ? STACK_GAP_PX : 0 }}
|
||||
|
|
|
|||
|
|
@ -129,13 +129,16 @@ export default function View() {
|
|||
}, [room]);
|
||||
|
||||
const users = useMemo(() => {
|
||||
const participants = [...room.remoteParticipants.values(), room.localParticipant];
|
||||
const participants = [
|
||||
...room.remoteParticipants.values(),
|
||||
room.localParticipant,
|
||||
];
|
||||
|
||||
return participants.filter((participant) => {
|
||||
const participantId = Number(participant.identity);
|
||||
return Number.isInteger(participantId) && participantId > 0;
|
||||
});
|
||||
// eslint-disable-next-line
|
||||
// eslint-disable-next-line
|
||||
}, [participantVersion, room]);
|
||||
|
||||
const userIds = useMemo(
|
||||
|
|
@ -195,9 +198,13 @@ export default function View() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div ref={containerRef} style={{
|
||||
height: "calc(100% - 2rem)"
|
||||
}} className="w-full overflow-hidden p-3">
|
||||
<div
|
||||
ref={containerRef}
|
||||
style={{
|
||||
height: "calc(100% - 2rem)",
|
||||
}}
|
||||
className="w-full overflow-hidden p-3"
|
||||
>
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-3">
|
||||
{rows.map((row) => (
|
||||
<div key={row.rowIndex} className="flex justify-center gap-3">
|
||||
|
|
@ -217,7 +224,10 @@ export default function View() {
|
|||
height: layout.tileHeight,
|
||||
}}
|
||||
>
|
||||
<Base type={tile.kind} participant={getParticipantById(tile.participantId)} />
|
||||
<Base
|
||||
type={tile.kind}
|
||||
participant={getParticipantById(tile.participantId)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@
|
|||
- Buttons
|
||||
- Preview image
|
||||
- Mobile
|
||||
- Deaf status is not synced
|
||||
|
|
|
|||
Loading…
Reference in a new issue