mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-22 05:09:05 +00:00
consent skip feature
This commit is contained in:
@@ -5,6 +5,7 @@ import { useError } from "../(errors)/errorContext";
|
||||
import { QueryClient, useQueryClient } from "@tanstack/react-query";
|
||||
import type { components } from "../reflector-api";
|
||||
import { useAuth } from "./AuthProvider";
|
||||
import { MeetingId } from "./types";
|
||||
|
||||
/*
|
||||
* XXX error types returned from the hooks are not always correct; declared types are ValidationError but real type could be string or any other
|
||||
@@ -718,7 +719,7 @@ export function useRoomActiveMeetings(roomName: string | null) {
|
||||
|
||||
export function useRoomGetMeeting(
|
||||
roomName: string | null,
|
||||
meetingId: string | null,
|
||||
meetingId: MeetingId | null,
|
||||
) {
|
||||
return $api.useQuery(
|
||||
"get",
|
||||
|
||||
@@ -9,16 +9,26 @@ import {
|
||||
CONSENT_BUTTON_Z_INDEX,
|
||||
CONSENT_DIALOG_TEXT,
|
||||
} from "./constants";
|
||||
import { MeetingId } from "../types";
|
||||
import type { components } from "../../reflector-api";
|
||||
|
||||
interface ConsentDialogButtonProps {
|
||||
meetingId: string;
|
||||
}
|
||||
type Meeting = components["schemas"]["Meeting"];
|
||||
|
||||
export function ConsentDialogButton({ meetingId }: ConsentDialogButtonProps) {
|
||||
const { showConsentModal, consentState, hasAnswered, consentLoading } =
|
||||
useConsentDialog(meetingId);
|
||||
type ConsentDialogButtonProps = {
|
||||
meetingId: MeetingId;
|
||||
recordingType: Meeting["recording_type"];
|
||||
skipConsent: boolean;
|
||||
};
|
||||
|
||||
if (!consentState.ready || hasAnswered(meetingId) || consentLoading) {
|
||||
export function ConsentDialogButton({
|
||||
meetingId,
|
||||
recordingType,
|
||||
skipConsent,
|
||||
}: ConsentDialogButtonProps) {
|
||||
const { showConsentModal, consentState, showConsentButton, consentLoading } =
|
||||
useConsentDialog({ meetingId, recordingType, skipConsent });
|
||||
|
||||
if (!consentState.ready || !showConsentButton || consentLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
export interface ConsentDialogResult {
|
||||
import { MeetingId } from "../types";
|
||||
|
||||
export type ConsentDialogResult = {
|
||||
showConsentModal: () => void;
|
||||
consentState: {
|
||||
ready: boolean;
|
||||
consentForMeetings?: Map<string, boolean>;
|
||||
consentForMeetings?: Map<MeetingId, boolean>;
|
||||
};
|
||||
hasAnswered: (meetingId: string) => boolean;
|
||||
hasAccepted: (meetingId: string) => boolean;
|
||||
hasAnswered: (meetingId: MeetingId) => boolean;
|
||||
hasAccepted: (meetingId: MeetingId) => boolean;
|
||||
consentLoading: boolean;
|
||||
}
|
||||
showRecordingIndicator: boolean;
|
||||
showConsentButton: boolean;
|
||||
};
|
||||
|
||||
@@ -7,8 +7,23 @@ import { useMeetingAudioConsent } from "../apiHooks";
|
||||
import { ConsentDialog } from "./ConsentDialog";
|
||||
import { TOAST_CHECK_INTERVAL_MS } from "./constants";
|
||||
import type { ConsentDialogResult } from "./types";
|
||||
import { MeetingId } from "../types";
|
||||
import { recordingTypeRequiresConsent } from "./utils";
|
||||
import type { components } from "../../reflector-api";
|
||||
|
||||
export function useConsentDialog(meetingId: string): ConsentDialogResult {
|
||||
type Meeting = components["schemas"]["Meeting"];
|
||||
|
||||
type UseConsentDialogParams = {
|
||||
meetingId: MeetingId;
|
||||
recordingType: Meeting["recording_type"];
|
||||
skipConsent: boolean;
|
||||
};
|
||||
|
||||
export function useConsentDialog({
|
||||
meetingId,
|
||||
recordingType,
|
||||
skipConsent,
|
||||
}: UseConsentDialogParams): ConsentDialogResult {
|
||||
const {
|
||||
state: consentState,
|
||||
touch,
|
||||
@@ -105,11 +120,23 @@ export function useConsentDialog(meetingId: string): ConsentDialogResult {
|
||||
});
|
||||
}, [handleConsent, modalOpen]);
|
||||
|
||||
const requiresConsent = Boolean(
|
||||
recordingType && recordingTypeRequiresConsent(recordingType),
|
||||
);
|
||||
|
||||
const showRecordingIndicator =
|
||||
requiresConsent && (skipConsent || hasAccepted(meetingId));
|
||||
|
||||
const showConsentButton =
|
||||
requiresConsent && !skipConsent && !hasAnswered(meetingId);
|
||||
|
||||
return {
|
||||
showConsentModal,
|
||||
consentState,
|
||||
hasAnswered,
|
||||
hasAccepted,
|
||||
consentLoading: audioConsentMutation.isPending,
|
||||
showRecordingIndicator,
|
||||
showConsentButton,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import type { Session } from "next-auth";
|
||||
import type { JWT } from "next-auth/jwt";
|
||||
import { parseMaybeNonEmptyString } from "./utils";
|
||||
import {
|
||||
assertExistsAndNonEmptyString,
|
||||
NonEmptyString,
|
||||
parseMaybeNonEmptyString,
|
||||
} from "./utils";
|
||||
|
||||
export interface JWTWithAccessToken extends JWT {
|
||||
accessToken: string;
|
||||
@@ -78,3 +82,10 @@ export const assertCustomSession = <T extends Session>(
|
||||
export type Mutable<T> = {
|
||||
-readonly [P in keyof T]: T[P];
|
||||
};
|
||||
|
||||
export type MeetingId = NonEmptyString & { __type: "MeetingId" };
|
||||
export const assertMeetingId = (s: string): MeetingId => {
|
||||
const nes = assertExistsAndNonEmptyString(s);
|
||||
// just cast for now
|
||||
return nes as MeetingId;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user