mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
fix: daily auto refresh fix (#755)
* daily auto refresh fix * Update www/app/lib/AuthProvider.tsx Co-authored-by: pr-agent-monadical[bot] <198624643+pr-agent-monadical[bot]@users.noreply.github.com> * Update www/app/[roomName]/components/DailyRoom.tsx Co-authored-by: pr-agent-monadical[bot] <198624643+pr-agent-monadical[bot]@users.noreply.github.com> * fix bot lint --------- Co-authored-by: Igor Loskutov <igor.loskutoff@gmail.com> Co-authored-by: pr-agent-monadical[bot] <198624643+pr-agent-monadical[bot]@users.noreply.github.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
|||||||
recordingTypeRequiresConsent,
|
recordingTypeRequiresConsent,
|
||||||
} from "../../lib/consent";
|
} from "../../lib/consent";
|
||||||
import { useRoomJoinMeeting } from "../../lib/apiHooks";
|
import { useRoomJoinMeeting } from "../../lib/apiHooks";
|
||||||
|
import { assertExists } from "../../lib/utils";
|
||||||
|
|
||||||
type Meeting = components["schemas"]["Meeting"];
|
type Meeting = components["schemas"]["Meeting"];
|
||||||
|
|
||||||
@@ -22,16 +23,16 @@ export default function DailyRoom({ meeting }: DailyRoomProps) {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const status = auth.status;
|
const authStatus = auth.status;
|
||||||
|
const authLastUserId = auth.lastUserId;
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const joinMutation = useRoomJoinMeeting();
|
const joinMutation = useRoomJoinMeeting();
|
||||||
const [joinedMeeting, setJoinedMeeting] = useState<Meeting | null>(null);
|
const [joinedMeeting, setJoinedMeeting] = useState<Meeting | null>(null);
|
||||||
|
|
||||||
const roomName = params?.roomName as string;
|
const roomName = params?.roomName as string;
|
||||||
|
|
||||||
// Always call /join to get a fresh token with user_id
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === "loading" || !meeting?.id || !roomName) return;
|
if (authLastUserId === null || !meeting?.id || !roomName) return;
|
||||||
|
|
||||||
const join = async () => {
|
const join = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -50,18 +51,16 @@ export default function DailyRoom({ meeting }: DailyRoomProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
join();
|
join();
|
||||||
}, [meeting?.id, roomName, status]);
|
}, [meeting?.id, roomName, authLastUserId]);
|
||||||
|
|
||||||
const roomUrl = joinedMeeting?.host_room_url || joinedMeeting?.room_url;
|
const roomUrl = joinedMeeting?.host_room_url || joinedMeeting?.room_url;
|
||||||
const isLoading =
|
|
||||||
status === "loading" || joinMutation.isPending || !joinedMeeting;
|
|
||||||
|
|
||||||
const handleLeave = useCallback(() => {
|
const handleLeave = useCallback(() => {
|
||||||
router.push("/browse");
|
router.push("/browse");
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoading || !roomUrl || !containerRef.current) return;
|
if (!authLastUserId || !roomUrl || !containerRef.current) return;
|
||||||
|
|
||||||
let frame: DailyCall | null = null;
|
let frame: DailyCall | null = null;
|
||||||
let destroyed = false;
|
let destroyed = false;
|
||||||
@@ -90,9 +89,14 @@ export default function DailyRoom({ meeting }: DailyRoomProps) {
|
|||||||
|
|
||||||
frame.on("left-meeting", handleLeave);
|
frame.on("left-meeting", handleLeave);
|
||||||
|
|
||||||
|
// TODO this method must not ignore no-recording option
|
||||||
|
// TODO this method is here to make dev environments work in some cases (not examined which)
|
||||||
frame.on("joined-meeting", async () => {
|
frame.on("joined-meeting", async () => {
|
||||||
try {
|
try {
|
||||||
await frame.startRecording({ type: "raw-tracks" });
|
assertExists(
|
||||||
|
frame,
|
||||||
|
"frame object got lost somewhere after frame.on was called",
|
||||||
|
).startRecording({ type: "raw-tracks" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to start recording:", error);
|
console.error("Failed to start recording:", error);
|
||||||
}
|
}
|
||||||
@@ -104,7 +108,9 @@ export default function DailyRoom({ meeting }: DailyRoomProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
createAndJoin();
|
createAndJoin().catch((error) => {
|
||||||
|
console.error("Failed to create and join meeting:", error);
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
destroyed = true;
|
destroyed = true;
|
||||||
@@ -114,9 +120,9 @@ export default function DailyRoom({ meeting }: DailyRoomProps) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [roomUrl, isLoading, handleLeave]);
|
}, [roomUrl, authLastUserId, handleLeave]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (!authLastUserId) {
|
||||||
return (
|
return (
|
||||||
<Center width="100vw" height="100vh">
|
<Center width="100vw" height="100vh">
|
||||||
<Spinner size="xl" />
|
<Spinner size="xl" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { createContext, useContext } from "react";
|
import { createContext, useContext, useRef } from "react";
|
||||||
import { useSession as useNextAuthSession } from "next-auth/react";
|
import { useSession as useNextAuthSession } from "next-auth/react";
|
||||||
import { signOut, signIn } from "next-auth/react";
|
import { signOut, signIn } from "next-auth/react";
|
||||||
import { configureApiAuth } from "./apiClient";
|
import { configureApiAuth } from "./apiClient";
|
||||||
@@ -25,6 +25,8 @@ type AuthContextType = (
|
|||||||
update: () => Promise<Session | null>;
|
update: () => Promise<Session | null>;
|
||||||
signIn: typeof signIn;
|
signIn: typeof signIn;
|
||||||
signOut: typeof signOut;
|
signOut: typeof signOut;
|
||||||
|
// TODO probably rename isLoading to isReloading and make THIS field "isLoading"
|
||||||
|
lastUserId: CustomSession["user"]["id"] | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||||
@@ -41,10 +43,13 @@ const noopAuthContext: AuthContextType = {
|
|||||||
signOut: async () => {
|
signOut: async () => {
|
||||||
throw new Error("signOut not supposed to be called");
|
throw new Error("signOut not supposed to be called");
|
||||||
},
|
},
|
||||||
|
lastUserId: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||||
const { data: session, status, update } = useNextAuthSession();
|
const { data: session, status, update } = useNextAuthSession();
|
||||||
|
// referential comparison done in component, must be primitive /or cached
|
||||||
|
const lastUserId = useRef<CustomSession["user"]["id"] | null>(null);
|
||||||
|
|
||||||
const contextValue: AuthContextType = isAuthEnabled
|
const contextValue: AuthContextType = isAuthEnabled
|
||||||
? {
|
? {
|
||||||
@@ -78,6 +83,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|||||||
status: "unauthenticated" as const,
|
status: "unauthenticated" as const,
|
||||||
};
|
};
|
||||||
} else if (customSession?.accessToken) {
|
} else if (customSession?.accessToken) {
|
||||||
|
// updates anyways with updated properties below
|
||||||
|
// warning! execution order conscience, must be ran before reading lastUserId.current below
|
||||||
|
lastUserId.current = customSession.user.id;
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
accessToken: customSession.accessToken,
|
accessToken: customSession.accessToken,
|
||||||
@@ -103,6 +111,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|||||||
update,
|
update,
|
||||||
signIn,
|
signIn,
|
||||||
signOut,
|
signOut,
|
||||||
|
// for optimistic cases when we assume "loading" doesn't immediately invalidate the user
|
||||||
|
lastUserId: lastUserId.current,
|
||||||
}
|
}
|
||||||
: noopAuthContext;
|
: noopAuthContext;
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export const authOptions = (): AuthOptions =>
|
|||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }) {
|
||||||
const extendedToken = token as JWTWithAccessToken;
|
const extendedToken = token as JWTWithAccessToken;
|
||||||
|
console.log("extendedToken", extendedToken);
|
||||||
const userId = await getUserId(extendedToken.accessToken);
|
const userId = await getUserId(extendedToken.accessToken);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user