graciously handle call errors

This commit is contained in:
m5r 2021-09-04 00:19:32 +08:00
parent b4ca27ca87
commit 55a705d3d7
2 changed files with 59 additions and 8 deletions

View File

@ -40,17 +40,24 @@ export default function useMakeCall({ recipient, onHangUp }: Params) {
// @ts-ignore // @ts-ignore
window.ddd = outgoingConnection; window.ddd = outgoingConnection;
// TODO: remove event listeners outgoingConnection.on("error", (error) => {
outgoingConnection.off("cancel", endCall);
outgoingConnection.off("disconnect", endCall);
setState(() => {
// hack to trigger the error boundary
throw error;
});
});
outgoingConnection.once("accept", (call: Call) => setState("call_in_progress")); outgoingConnection.once("accept", (call: Call) => setState("call_in_progress"));
outgoingConnection.on("cancel", endCall); outgoingConnection.on("cancel", endCall);
outgoingConnection.on("disconnect", endCall); outgoingConnection.on("disconnect", endCall);
outgoingConnection.on("error", (error) => {
console.error("call error", error);
alert(error);
});
} }
function endCall() { function endCall() {
outgoingConnection?.off("cancel", endCall);
outgoingConnection?.off("disconnect", endCall);
outgoingConnection?.disconnect();
setState("call_ending"); setState("call_ending");
setTimeout(() => { setTimeout(() => {
setState("call_ended"); setState("call_ended");

View File

@ -1,6 +1,7 @@
import type { BlitzPage } from "blitz"; import type { BlitzPage, ErrorFallbackProps, WithRouterProps } from "blitz";
import { Routes, useRouter } from "blitz"; import { ErrorBoundary, Routes, useRouter, withRouter } from "blitz";
import { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import type { TwilioError } from "@twilio/voice-sdk";
import { atom, useAtom } from "jotai"; import { atom, useAtom } from "jotai";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPhoneAlt as faPhone } from "@fortawesome/pro-solid-svg-icons"; import { faPhoneAlt as faPhone } from "@fortawesome/pro-solid-svg-icons";
@ -67,7 +68,7 @@ const OutgoingCall: BlitzPage = () => {
case "calling": case "calling":
return "Calling..."; return "Calling...";
case "call_in_progress": case "call_in_progress":
return ""; // TODO display time elapsed return "In call"; // TODO display time elapsed
case "call_ending": case "call_ending":
return "Call ending..."; return "Call ending...";
case "call_ended": case "call_ended":
@ -86,5 +87,48 @@ const pressDigitAtom = atom(null, (get, set, digit: string) => {
}); });
OutgoingCall.authenticate = { redirectTo: Routes.SignIn() }; OutgoingCall.authenticate = { redirectTo: Routes.SignIn() };
OutgoingCall.getLayout = (page) => <ErrorBoundary FallbackComponent={ErrorFallback}>{page}</ErrorBoundary>;
const ErrorFallback = withRouter(function WrappedErrorFallback({
error,
router,
}: ErrorFallbackProps & WithRouterProps) {
console.log("error", JSON.parse(JSON.stringify(error)));
return (
<div className="w-screen h-screen flex">
<div className="max-w-md m-auto p-4">
<h2 className="text-lg py-3 leading-relaxed font-medium text-gray-900">
Sorry, an error has occurred during your call
</h2>
{isTwilioError(error) ? (
<pre className="break-normal whitespace-normal mt-2 text-sm rounded py-3 px-5 bg-[#111] text-gray-300">
<div>
{error.description} ({error.code})
</div>
<div>{error.explanation}</div>
</pre>
) : null}
<p className="mt-2 text-sm text-gray-500">
We have been automatically notified and we&#39;re doing our best to make sure this does not happen
again!
</p>
<div className="mt-5 md:mt-4 md:flex md:flex-row-reverse">
<button
type="button"
className="transition-colors duration-150 mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 md:mt-0 md:w-auto md:text-sm"
onClick={() => router.replace(Routes.KeypadPage())}
>
Take me back to the app
</button>
</div>
</div>
</div>
);
});
function isTwilioError(error: any): error is typeof TwilioError {
return error.hasOwnProperty("explanation");
}
export default OutgoingCall; export default OutgoingCall;