From 24ab250c8aa3edd8d452c232c24e2ac123b9d350 Mon Sep 17 00:00:00 2001 From: Jacob John Jeevan <40040905+Jacobjeevan@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:16:49 +0530 Subject: [PATCH 1/2] Consultation Form Enhancement: No home facility docs (#7914) * Added custom no results label for AutocompleteFormField - Added "no home facility doctors" as text for no results in User autocomplete field in Consultation Form. * Added notification for autocomplete - Display extra notification when there are no results for Assigned docs field (Consultation Form) - Only applicable to ConsultationForm * improve how no user error notification is dispatched * use translations * Show error and disable field instead of notification * Skip showing error instead validate on submit * add translations for field_required * remove duplicate i18n key from auth.json * update cypress --------- Co-authored-by: rithviknishad --- .../e2e/facility_spec/facility_creation.cy.ts | 11 ++++++---- cypress/e2e/users_spec/user_creation.cy.ts | 4 ++-- cypress/pageobject/Asset/AssetCreation.ts | 2 +- src/Common/hooks/useAsyncOptions.ts | 2 +- .../Common/UserAutocompleteFormField.tsx | 20 ++++++++++++++++--- .../ExternalResult/ResultUpdate.tsx | 4 +++- src/Components/Facility/AssetCreate.tsx | 7 ++++--- src/Components/Facility/BedCapacity.tsx | 4 +++- src/Components/Facility/ConsultationForm.tsx | 13 ++++++------ src/Components/Facility/DischargeModal.tsx | 2 +- src/Components/Facility/StaffCapacity.tsx | 4 +++- .../Facility/TransferPatientDialog.tsx | 4 +++- src/Components/Facility/TriageForm.tsx | 4 +++- src/Components/Form/FieldValidators.tsx | 4 +++- src/Components/Medicine/validators.ts | 3 ++- src/Components/Users/UserAdd.tsx | 6 ++++-- src/Components/Users/UserProfile.tsx | 10 ++++++---- src/Locale/en/Auth.json | 3 +-- src/Locale/en/Common.json | 3 ++- src/Locale/en/Consultation.json | 1 + 20 files changed, 74 insertions(+), 37 deletions(-) diff --git a/cypress/e2e/facility_spec/facility_creation.cy.ts b/cypress/e2e/facility_spec/facility_creation.cy.ts index 83f666995ff..6401ba7bbbe 100644 --- a/cypress/e2e/facility_spec/facility_creation.cy.ts +++ b/cypress/e2e/facility_spec/facility_creation.cy.ts @@ -58,12 +58,15 @@ describe("Facility Creation", () => { "Invalid Phone Number", ]; const bedErrorMessage = [ - "Field is required", + "This field is required", "Total capacity cannot be 0", - "Field is required", + "This field is required", ]; - const doctorErrorMessage = ["Field is required", "Field is required"]; - const triageErrorMessage = ["Field is required"]; + const doctorErrorMessage = [ + "This field is required", + "This field is required", + ]; + const triageErrorMessage = ["This field is required"]; before(() => { loginPage.loginAsDisctrictAdmin(); diff --git a/cypress/e2e/users_spec/user_creation.cy.ts b/cypress/e2e/users_spec/user_creation.cy.ts index 572b0cb95c4..91efb3aee31 100644 --- a/cypress/e2e/users_spec/user_creation.cy.ts +++ b/cypress/e2e/users_spec/user_creation.cy.ts @@ -50,8 +50,8 @@ describe("User Creation", () => { ]; const EXPECTED_PROFILE_ERROR_MESSAGES = [ - "Field is required", - "Field is required", + "This field is required", + "This field is required", "Please enter valid phone number", ]; diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index 9232c5966c1..331a4588c6f 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -200,7 +200,7 @@ export class AssetPage { verifyEmptyStatusError() { cy.get("[data-testid=asset-working-status-input] span").should( "contain", - "Field is required", + "This field is required", ); } diff --git a/src/Common/hooks/useAsyncOptions.ts b/src/Common/hooks/useAsyncOptions.ts index 1a632dc366e..a81209f34f0 100644 --- a/src/Common/hooks/useAsyncOptions.ts +++ b/src/Common/hooks/useAsyncOptions.ts @@ -38,7 +38,7 @@ export function useAsyncOptions>( ) { const dispatch = useDispatch(); const [queryOptions, setQueryOptions] = useState([]); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const fetchOptions = useMemo( () => diff --git a/src/Components/Common/UserAutocompleteFormField.tsx b/src/Components/Common/UserAutocompleteFormField.tsx index c7694b74e4e..442eb0ae4fe 100644 --- a/src/Components/Common/UserAutocompleteFormField.tsx +++ b/src/Components/Common/UserAutocompleteFormField.tsx @@ -9,6 +9,7 @@ import { import { UserModel } from "../Users/models"; import { isUserOnline } from "../../Utils/utils"; import { UserRole } from "../../Common/constants"; +import { useEffect } from "react"; type Props = FormFieldBaseProps & { placeholder?: string; @@ -16,6 +17,7 @@ type Props = FormFieldBaseProps & { homeFacility?: string; userType?: UserRole; showActiveStatus?: boolean; + noResultsError?: string; }; export default function UserAutocompleteFormField(props: Props) { @@ -59,18 +61,30 @@ export default function UserAutocompleteFormField(props: Props) { ); }; + const items = options(field.value && [field.value]); + + useEffect(() => { + if (props.required && !isLoading && !items.length && props.noResultsError) { + field.handleChange(undefined as unknown as UserModel); + } + }, [isLoading, items, props.required]); + + const noResultError = + (props.required && !isLoading && !items.length && props.noResultsError) || + undefined; + return (
`${option.user_type}`} diff --git a/src/Components/ExternalResult/ResultUpdate.tsx b/src/Components/ExternalResult/ResultUpdate.tsx index 09dc41aaca7..482c320457e 100644 --- a/src/Components/ExternalResult/ResultUpdate.tsx +++ b/src/Components/ExternalResult/ResultUpdate.tsx @@ -12,6 +12,7 @@ import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; import { compareBy } from "../../Utils/utils.js"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -57,6 +58,7 @@ const initialWard = [{ id: 0, name: "Choose Ward", number: 0 }]; export default function UpdateResult(props: any) { const { id } = props; const { goBack } = useAppHistory(); + const { t } = useTranslation(); const [state, dispatch] = useReducer(FormReducer, initialState); const [isLoading, setIsLoading] = useState(true); @@ -132,7 +134,7 @@ export default function UpdateResult(props: any) { switch (field) { case "address": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Components/Facility/AssetCreate.tsx b/src/Components/Facility/AssetCreate.tsx index 6867857c5c6..5b1493de242 100644 --- a/src/Components/Facility/AssetCreate.tsx +++ b/src/Components/Facility/AssetCreate.tsx @@ -32,10 +32,10 @@ import { validateEmailAddress } from "../../Common/validation"; import { dateQueryString, parsePhoneNumber } from "../../Utils/utils.js"; import dayjs from "../../Utils/dayjs"; import DateFormField from "../Form/FormFields/DateFormField.js"; -import { t } from "i18next"; import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -101,6 +101,7 @@ type AssetFormSection = const AssetCreate = (props: AssetProps) => { const { goBack } = useAppHistory(); + const { t } = useTranslation(); const { facilityId, assetId } = props; let assetClassInitial: AssetClass; @@ -212,7 +213,7 @@ const AssetCreate = (props: AssetProps) => { return; case "is_working": if (is_working === undefined) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; @@ -224,7 +225,7 @@ const AssetCreate = (props: AssetProps) => { return; case "support_phone": { if (!support_phone) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } // eslint-disable-next-line no-case-declarations diff --git a/src/Components/Facility/BedCapacity.tsx b/src/Components/Facility/BedCapacity.tsx index ff0ec111496..c0f239203d5 100644 --- a/src/Components/Facility/BedCapacity.tsx +++ b/src/Components/Facility/BedCapacity.tsx @@ -9,6 +9,7 @@ import useConfig from "../../Common/hooks/useConfig"; import { getBedTypes } from "../../Common/constants"; import routes from "../../Redux/api"; import request from "../../Utils/request/request"; +import { useTranslation } from "react-i18next"; interface BedCapacityProps extends CapacityModal { facilityId: string; @@ -49,6 +50,7 @@ const bedCountReducer = (state = initialState, action: any) => { }; export const BedCapacity = (props: BedCapacityProps) => { + const { t } = useTranslation(); const config = useConfig(); const { facilityId, handleClose, handleUpdate, className, id } = props; const [state, dispatch] = useReducer(bedCountReducer, initialState); @@ -127,7 +129,7 @@ export const BedCapacity = (props: BedCapacityProps) => { let invalidForm = false; Object.keys(state.form).forEach((field) => { if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if ( field === "currentOccupancy" && diff --git a/src/Components/Facility/ConsultationForm.tsx b/src/Components/Facility/ConsultationForm.tsx index bfcc80d88fd..dc496d599f7 100644 --- a/src/Components/Facility/ConsultationForm.tsx +++ b/src/Components/Facility/ConsultationForm.tsx @@ -386,8 +386,8 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { admitted: data.admitted ? String(data.admitted) : "false", admitted_to: data.admitted_to ? data.admitted_to : "", category: data.category - ? PATIENT_CATEGORIES.find((i) => i.text === data.category)?.id ?? - "" + ? (PATIENT_CATEGORIES.find((i) => i.text === data.category)?.id ?? + "") : "", patient_no: data.patient_no ?? "", OPconsultation: data.consultation_notes, @@ -453,7 +453,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { return; case "route_to_facility": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; @@ -469,7 +469,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { return; case "encounter_date": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } if ( @@ -540,7 +540,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { return; case "consultation_notes": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if (!state.form[field].replace(/\s/g, "").length) { errors[field] = "Consultation notes can not be empty"; @@ -608,7 +608,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { case "treating_physician": { if (state.form.suggestion !== "DD" && !state.form[field]) { - errors[field] = "Please fill treating physician"; + errors[field] = t("field_required"); invalidForm = true; break; } @@ -1437,6 +1437,7 @@ export const ConsultationForm = ({ facilityId, patientId, id }: Props) => { userType={"Doctor"} homeFacility={facilityId} error={state.errors.treating_physician} + noResultsError={t("no_treating_physicians_available")} />
diff --git a/src/Components/Facility/DischargeModal.tsx b/src/Components/Facility/DischargeModal.tsx index 567c21dfbb6..fe99b4ddd53 100644 --- a/src/Components/Facility/DischargeModal.tsx +++ b/src/Components/Facility/DischargeModal.tsx @@ -151,7 +151,7 @@ const DischargeModal = ({ newErrors["discharge_notes"] = "Please enter the cause of death"; } if (!preDischargeForm.death_confirmed_doctor?.trim()) { - newErrors["death_confirmed_doctor"] = "Field is required"; + newErrors["death_confirmed_doctor"] = t("field_required"); } if (Object.entries(newErrors).length) { diff --git a/src/Components/Facility/StaffCapacity.tsx b/src/Components/Facility/StaffCapacity.tsx index fc54dfcbb2d..8326ed6a323 100644 --- a/src/Components/Facility/StaffCapacity.tsx +++ b/src/Components/Facility/StaffCapacity.tsx @@ -10,6 +10,7 @@ import { DoctorModal } from "./models.js"; import useQuery from "../../Utils/request/useQuery.js"; import routes from "../../Redux/api.js"; import request from "../../Utils/request/request.js"; +import { useTranslation } from "react-i18next"; interface DoctorCapacityProps extends DoctorModal { facilityId: string; @@ -58,6 +59,7 @@ const getAllowedDoctorTypes = (existing?: DoctorModal[]) => { }; export const StaffCapacity = (props: DoctorCapacityProps) => { + const { t } = useTranslation(); const { facilityId, handleClose, handleUpdate, className, id } = props; const [state, dispatch] = useReducer(doctorCapacityReducer, initialState); const [isLoading, setIsLoading] = useState(false); @@ -94,7 +96,7 @@ export const StaffCapacity = (props: DoctorCapacityProps) => { let invalidForm = false; Object.keys(state.form).forEach((field) => { if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } if (field === "count" && state.form[field] < 0) { diff --git a/src/Components/Facility/TransferPatientDialog.tsx b/src/Components/Facility/TransferPatientDialog.tsx index 3ead082c610..0c4af6c5d0c 100644 --- a/src/Components/Facility/TransferPatientDialog.tsx +++ b/src/Components/Facility/TransferPatientDialog.tsx @@ -9,6 +9,7 @@ import request from "../../Utils/request/request.js"; import routes from "../../Redux/api.js"; import TextFormField from "../Form/FormFields/TextFormField.js"; import { FieldChangeEvent } from "../Form/FormFields/Utils.js"; +import { useTranslation } from "react-i18next"; interface Props { patientList: Array; @@ -53,6 +54,7 @@ const patientFormReducer = (state = initialState, action: any) => { const TransferPatientDialog = (props: Props) => { const { patientList, handleOk, handleCancel, facilityId } = props; + const { t } = useTranslation(); const [isLoading, setIsLoading] = useState(false); const [state, dispatch] = useReducer(patientFormReducer, initialState); const patientOptions: Array = patientList.map((patient) => { @@ -102,7 +104,7 @@ const TransferPatientDialog = (props: Props) => { return; case "year_of_birth": if (!state.form[field]) { - errors[field] = "This field is required"; + errors[field] = t("field_required"); invalidForm = true; } diff --git a/src/Components/Facility/TriageForm.tsx b/src/Components/Facility/TriageForm.tsx index 6ad9fdd0e08..1aa0537b53c 100644 --- a/src/Components/Facility/TriageForm.tsx +++ b/src/Components/Facility/TriageForm.tsx @@ -17,6 +17,7 @@ import { dateQueryString, scrollTo } from "../../Utils/utils"; import useQuery from "../../Utils/request/useQuery"; import routes from "../../Redux/api"; import request from "../../Utils/request/request"; +import { useTranslation } from "react-i18next"; interface Props extends PatientStatsModel { facilityId: string; @@ -57,6 +58,7 @@ const triageFormReducer = (state = initialState, action: any) => { }; export const TriageForm = ({ facilityId, id }: Props) => { + const { t } = useTranslation(); const { goBack } = useAppHistory(); const [state, dispatch] = useReducer(triageFormReducer, initialState); const [isLoading, setIsLoading] = useState(false); @@ -98,7 +100,7 @@ export const TriageForm = ({ facilityId, id }: Props) => { switch (field) { case "entry_date": if (!state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Components/Form/FieldValidators.tsx b/src/Components/Form/FieldValidators.tsx index 4933b685171..3159c6814f1 100644 --- a/src/Components/Form/FieldValidators.tsx +++ b/src/Components/Form/FieldValidators.tsx @@ -1,3 +1,5 @@ +import { t } from "i18next"; + export type FieldError = string | undefined; export type FieldValidator = (value: T, ...args: any) => FieldError; @@ -42,7 +44,7 @@ export const AnyValidator = ( return validator; }; -export const RequiredFieldValidator = (message = "Field is required") => { +export const RequiredFieldValidator = (message = t("field_required")) => { return (value: T): FieldError => { if (!value) return message; if (Array.isArray(value) && value.length === 0) return message; diff --git a/src/Components/Medicine/validators.ts b/src/Components/Medicine/validators.ts index 13460230737..a0103d11241 100644 --- a/src/Components/Medicine/validators.ts +++ b/src/Components/Medicine/validators.ts @@ -1,3 +1,4 @@ +import { t } from "i18next"; import { FieldError, RequiredFieldValidator } from "../Form/FieldValidators"; import { FormErrors } from "../Form/Utils"; import { Prescription } from "./models"; @@ -73,7 +74,7 @@ export const AdministrationDosageValidator = ( const baseDosage = getDosageValue(base_dosage); const targetDosage = getDosageValue(target_dosage); - if (!valueDosage) return "This field is required"; + if (!valueDosage) return t("field_required"); if (value?.split(" ")[1] !== base_dosage?.split(" ")[1]) return "Unit must be the same as start and target dosage's unit"; diff --git a/src/Components/Users/UserAdd.tsx b/src/Components/Users/UserAdd.tsx index ba218226490..8d33533f67a 100644 --- a/src/Components/Users/UserAdd.tsx +++ b/src/Components/Users/UserAdd.tsx @@ -41,6 +41,7 @@ import routes from "../../Redux/api"; import request from "../../Utils/request/request"; import useQuery from "../../Utils/request/useQuery"; import CareIcon from "../../CAREUI/icons/CareIcon"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); @@ -163,6 +164,7 @@ export const validateRule = ( }; export const UserAdd = (props: UserProps) => { + const { t } = useTranslation(); const { goBack } = useAppHistory(); const { userId } = props; @@ -355,7 +357,7 @@ export const UserAdd = (props: UserProps) => { return; case "doctor_experience_commenced_on": if (state.form.user_type === "Doctor" && !state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if ( state.form.user_type === "Doctor" && @@ -368,7 +370,7 @@ export const UserAdd = (props: UserProps) => { case "doctor_qualification": case "doctor_medical_council_registration": if (state.form.user_type === "Doctor" && !state.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Components/Users/UserProfile.tsx b/src/Components/Users/UserProfile.tsx index 8a456be9bcd..dd8dadf2fb7 100644 --- a/src/Components/Users/UserProfile.tsx +++ b/src/Components/Users/UserProfile.tsx @@ -26,6 +26,7 @@ import routes from "../../Redux/api"; import request from "../../Utils/request/request"; import DateFormField from "../Form/FormFields/DateFormField"; import { validateRule } from "./UserAdd"; +import { useTranslation } from "react-i18next"; const Loading = lazy(() => import("../Common/Loading")); type EditForm = { @@ -110,6 +111,7 @@ const editFormReducer = (state: State, action: Action) => { }; export default function UserProfile() { + const { t } = useTranslation(); const { signOut } = useAuthContext(); const [states, dispatch] = useReducer(editFormReducer, initialState); const [updateStatus, setUpdateStatus] = useState({ @@ -201,7 +203,7 @@ export default function UserProfile() { case "lastName": case "gender": if (!states.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; @@ -254,7 +256,7 @@ export default function UserProfile() { return; case "email": if (!states.form[field]) { - errors[field] = "This field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if (!validateEmailAddress(states.form[field])) { errors[field] = "Enter a valid email address"; @@ -263,7 +265,7 @@ export default function UserProfile() { return; case "doctor_experience_commenced_on": if (states.form.user_type === "Doctor" && !states.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } else if ( (states.form.user_type === "Doctor" && @@ -278,7 +280,7 @@ export default function UserProfile() { case "doctor_qualification": case "doctor_medical_council_registration": if (states.form.user_type === "Doctor" && !states.form[field]) { - errors[field] = "Field is required"; + errors[field] = t("field_required"); invalidForm = true; } return; diff --git a/src/Locale/en/Auth.json b/src/Locale/en/Auth.json index 8075ca839cd..58fdef42612 100644 --- a/src/Locale/en/Auth.json +++ b/src/Locale/en/Auth.json @@ -11,7 +11,6 @@ "gender": "Gender", "age": "Age", "login": "Login", - "field_required": "This field is required", "password_mismatch": "Password and confirm password must be same.", "enter_valid_age": "Please Enter Valid Age", "invalid_username": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", @@ -37,4 +36,4 @@ "req_atleast_one_uppercase": "Require at least one upper case", "req_atleast_one_lowercase": "Require at least one lower case letter", "req_atleast_one_symbol": "Require at least one symbol" -} +} \ No newline at end of file diff --git a/src/Locale/en/Common.json b/src/Locale/en/Common.json index 89faf842586..0bd26305b86 100644 --- a/src/Locale/en/Common.json +++ b/src/Locale/en/Common.json @@ -110,6 +110,7 @@ "features": "Features", "pincode": "Pincode", "required": "Required", + "field_required": "This field is required", "litres": "Litres", "litres_per_day": "Litres/day", "invalid_pincode": "Invalid Pincode", @@ -177,4 +178,4 @@ "feed_optimal_experience_for_phones": "For optimal viewing experience, consider rotating your device.", "feed_optimal_experience_for_apple_phones": "For optimal viewing experience, consider rotating your device. Ensure auto-rotate is enabled in your device settings.", "action_irreversible": "This action is irreversible" -} +} \ No newline at end of file diff --git a/src/Locale/en/Consultation.json b/src/Locale/en/Consultation.json index 2fdb2406d28..6e3846fb983 100644 --- a/src/Locale/en/Consultation.json +++ b/src/Locale/en/Consultation.json @@ -36,6 +36,7 @@ "prev_sessions": "Prev Sessions", "next_sessions": "Next Sessions", "no_changes": "No changes", + "no_treating_physicians_available": "This facility does not have any home facility doctors. Please contact your admin.", "encounter_suggestion_edit_disallowed": "Not allowed to switch to this option in edit consultation", "encounter_date_field_label__A": "Date & Time of Admission to the Facility", "encounter_date_field_label__DC": "Date & Time of Domiciliary Care commencement", From f4e2e390e117cc4b21d68237ef1643d5a24d8930 Mon Sep 17 00:00:00 2001 From: Aakash Singh Date: Thu, 1 Aug 2024 11:17:26 +0530 Subject: [PATCH 2/2] Handle exceptions raised by the addSourceBuffer method (#8199) * Handle exceptions raised by the addSourceBuffer method * Update src/Common/hooks/useMSEplayer.ts --------- Co-authored-by: Rithvik Nishad --- src/Common/hooks/useMSEplayer.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Common/hooks/useMSEplayer.ts b/src/Common/hooks/useMSEplayer.ts index 127fe94b9a0..5271c08fd56 100644 --- a/src/Common/hooks/useMSEplayer.ts +++ b/src/Common/hooks/useMSEplayer.ts @@ -171,9 +171,14 @@ export const useMSEMediaPlayer = ({ } else { mimeCodec = Utf8ArrayToStr(decoded_arr); } - mseSourceBuffer = mse.addSourceBuffer( - `video/mp4; codecs="${mimeCodec}"`, - ); + try { + mseSourceBuffer = mse.addSourceBuffer( + `video/mp4; codecs="${mimeCodec}"`, + ); + } catch (error) { + onError?.(error); + return; + } mseSourceBuffer.mode = "segments"; if (mseQueue.length > 0 && !mseSourceBuffer.updating) { mseSourceBuffer.addEventListener("updateend", pushPacket);