Skip to content

Commit

Permalink
Resolve permission handling Issues in microphone and camera capture d…
Browse files Browse the repository at this point in the history
…ialogs (#8830)

Co-authored-by: Bodhish Thomas <[email protected]>
  • Loading branch information
shauryag2002 and bodhish authored Oct 27, 2024
1 parent 9a0d27b commit b9aff5e
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/Locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@
"audio__allow_permission": "Please allow microphone permission in site settings",
"audio__allow_permission_button": "Click here to know how to allow",
"audio__allow_permission_helper": "You might have denied microphone access in the past.",
"audio__permission_message": "Please grant microphone permission to record audio.",
"audio__record": "Record Audio",
"audio__record_helper": "Click the button to start recording",
"audio__recorded": "Audio Recorded",
Expand Down Expand Up @@ -1161,6 +1162,7 @@
"summary": "Summary",
"support": "Support",
"switch": "Switch",
"switch_camera_is_not_available": "Switch camera is not available.",
"systolic": "Systolic",
"tachycardia": "Tachycardia",
"target_dosage": "Target Dosage",
Expand Down
5 changes: 3 additions & 2 deletions src/Utils/useRecorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import { useEffect, useState } from "react";
import { Error } from "./Notifications";
import { useTranslation } from "react-i18next";

const useRecorder = (handleMicPermission) => {
const [audioURL, setAudioURL] = useState("");
const [isRecording, setIsRecording] = useState(false);
const [recorder, setRecorder] = useState(null);
const [newBlob, setNewBlob] = useState(null);

const { t } = useTranslation();
useEffect(() => {
if (!isRecording && recorder && audioURL) {
setRecorder(null);
Expand All @@ -26,7 +27,7 @@ const useRecorder = (handleMicPermission) => {
},
() => {
Error({
msg: "Please grant microphone permission to record audio.",
msg: t("audio__permission_message"),
});
setIsRecording(false);
handleMicPermission(false);
Expand Down
4 changes: 3 additions & 1 deletion src/Utils/useSegmentedRecorder.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { useState, useEffect } from "react";
import * as Notify from "./Notifications";
import { useTranslation } from "react-i18next";

const useSegmentedRecording = () => {
const [isRecording, setIsRecording] = useState(false);
const [recorder, setRecorder] = useState<MediaRecorder | null>(null);
const [audioBlobs, setAudioBlobs] = useState<Blob[]>([]);
const [restart, setRestart] = useState(false);
const { t } = useTranslation();

const bufferInterval = 1 * 1000;
const splitSizeLimit = 20 * 1000000; // 20MB
Expand All @@ -28,7 +30,7 @@ const useSegmentedRecording = () => {
},
() => {
Notify.Error({
msg: "Please grant microphone permission to record audio.",
msg: t("audio__permission_message"),
});
setIsRecording(false);
},
Expand Down
23 changes: 17 additions & 6 deletions src/components/Files/AudioCaptureDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import useRecorder from "../../Utils/useRecorder";
import { Link } from "raviger";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { useTimer } from "../../Utils/useTimer";
import { t } from "i18next";
import { useTranslation } from "react-i18next";
import * as Notify from "../../Utils/Notifications";

export interface AudioCaptureDialogProps {
show: boolean;
Expand All @@ -20,8 +21,8 @@ export default function AudioCaptureDialog(props: AudioCaptureDialogProps) {
| "RECORDED";

const { show, onHide, onCapture, autoRecord = false } = props;

const [status, setStatus] = useState<Status | null>(null);
const { t } = useTranslation();

const [audioURL, , startRecording, stopRecording, , resetRecording] =
useRecorder((permission: boolean) => {
Expand All @@ -35,9 +36,19 @@ export default function AudioCaptureDialog(props: AudioCaptureDialogProps) {
const timer = useTimer();

const handleStartRecording = () => {
setStatus("RECORDING");
startRecording();
timer.start();
navigator.mediaDevices
.getUserMedia({ audio: true })
.then(() => {
setStatus("RECORDING");
startRecording();
timer.start();
})
.catch(() => {
Notify.Error({
msg: t("audio__permission_message"),
});
setStatus("PERMISSION_DENIED");
});
};

const handleStopRecording = () => {
Expand Down Expand Up @@ -87,7 +98,7 @@ export default function AudioCaptureDialog(props: AudioCaptureDialogProps) {
}, [show]);

useEffect(() => {
if (autoRecord && show && status === "WAITING_TO_RECORD") {
if (autoRecord && show && status === "RECORDING") {
handleStartRecording();
}
}, [autoRecord, status, show]);
Expand Down
27 changes: 24 additions & 3 deletions src/components/Files/CameraCaptureDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import CareIcon from "../../CAREUI/icons/CareIcon";
import DialogModal from "@/components/Common/Dialog";
import ButtonV2, { Submit } from "@/components/Common/components/ButtonV2";
import { t } from "i18next";
import { useCallback, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import useWindowDimensions from "@/common/hooks/useWindowDimensions";
import * as Notify from "../../Utils/Notifications";

export interface CameraCaptureDialogProps {
show: boolean;
Expand All @@ -24,9 +25,29 @@ export default function CameraCaptureDialog(props: CameraCaptureDialogProps) {
height: { ideal: 2160 },
facingMode: "user",
};

useEffect(() => {
if (!show) return;
navigator.mediaDevices.getUserMedia({ video: true }).catch(() => {
Notify.Warn({
msg: t("camera_permission_denied"),
});
onHide();
});
}, [show]);
const handleSwitchCamera = useCallback(() => {
setCameraFacingFront((prevState) => !prevState);
const supportedConstraints =
navigator.mediaDevices.getSupportedConstraints();
if (
!isLaptopScreen &&
typeof supportedConstraints.facingMode === "string" &&
(supportedConstraints.facingMode as string).includes("environment")
) {
setCameraFacingFront((prevState) => !prevState);
} else {
Notify.Warn({
msg: t("switch_camera_is_not_available"),
});
}
}, []);

const { width } = useWindowDimensions();
Expand Down

0 comments on commit b9aff5e

Please sign in to comment.