Skip to content

Commit

Permalink
Don't check mic permission on Firefox (#3298)
Browse files Browse the repository at this point in the history
Avoids uncatchable TypeError introduced in #3247
  • Loading branch information
imnasnainaec authored Aug 8, 2024
1 parent 92050a5 commit 8c51260
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
21 changes: 11 additions & 10 deletions src/components/Pronunciations/Recorder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import RecordRTC from "recordrtc";

import { getFileNameForWord } from "components/Pronunciations/utilities";
import {
checkMicPermission,
getFileNameForWord,
} from "components/Pronunciations/utilities";

export default class Recorder {
private toast: (textId: string) => void;
Expand Down Expand Up @@ -63,14 +66,12 @@ export default class Recorder {

private onError(err: Error): void {
console.error(err);
navigator.permissions
.query({ name: "microphone" as PermissionName })
.then((result) => {
this.toast(
result.state === "granted"
? "pronunciations.audioStreamError"
: "pronunciations.noMicAccess"
);
});
checkMicPermission().then((hasPermission: boolean) =>
this.toast(
hasPermission
? "pronunciations.audioStreamError"
: "pronunciations.noMicAccess"
)
);
}
}
5 changes: 2 additions & 3 deletions src/components/Pronunciations/RecorderIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
resetPronunciations,
} from "components/Pronunciations/Redux/PronunciationsActions";
import { PronunciationsStatus } from "components/Pronunciations/Redux/PronunciationsReduxTypes";
import { checkMicPermission } from "components/Pronunciations/utilities";
import { useAppDispatch, useAppSelector } from "rootRedux/hooks";
import { type StoreState } from "rootRedux/types";
import { themeColors } from "types/theme";
Expand Down Expand Up @@ -37,9 +38,7 @@ export default function RecorderIcon(props: RecorderIconProps): ReactElement {
const { t } = useTranslation();

useEffect(() => {
navigator.permissions
.query({ name: "microphone" as PermissionName })
.then((result) => setHasMic(result.state === "granted"));
checkMicPermission().then(setHasMic);
}, []);

function toggleIsRecordingToTrue(): void {
Expand Down
23 changes: 23 additions & 0 deletions src/components/Pronunciations/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,26 @@ export async function uploadFileFromPronunciation(
URL.revokeObjectURL(fileName);
return newId;
}

/** Names of Firefox browsers in user-agent strings, all lowercase.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox */
const firefoxBrowsers = ["firefox", "focus", "fxios"];

/** Check if a user-agent string is of a Firefox browser. */
function isUserAgentFirefox(userAgent: string): boolean {
const uaLower = userAgent.toLocaleLowerCase();
return firefoxBrowsers.some((browser) => uaLower.includes(browser));
}

/** Checks if the user has granted mic permission to The Combine,
* except on Firefox assumes permission is granted. */
export async function checkMicPermission(): Promise<boolean> {
if (!isUserAgentFirefox(navigator.userAgent)) {
const result = await navigator.permissions.query({
name: "microphone" as PermissionName, // This causes a TypeError on Firefox.
});
return result.state === "granted";
}
return true;
}

0 comments on commit 8c51260

Please sign in to comment.