Display error message on failed WebView page load (#1072)

closes #1023
This commit is contained in:
Evan Simkowitz 2024-10-22 18:17:42 -07:00 committed by GitHub
parent 81a8a7f3eb
commit ec70ce8c91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 16 deletions

View File

@ -9,6 +9,7 @@
overflow: hidden;
padding: 0;
margin: 0;
user-select: none;
// try to force pixel alignment to prevent
// subpixel rendering artifacts
@ -16,6 +17,24 @@
will-change: transform;
}
.webview-error {
display: flex;
position: absolute;
background-color: black;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 100;
div {
font-size: x-large;
color: red;
display: flex;
margin: auto;
padding: 30px;
}
}
.block-frame-div-url {
background: rgba(255, 255, 255, 0.1);

View File

@ -13,7 +13,7 @@ import { fireAndForget } from "@/util/util";
import clsx from "clsx";
import { WebviewTag } from "electron";
import { Atom, PrimitiveAtom, atom, useAtomValue } from "jotai";
import React, { memo, useEffect, useState } from "react";
import { Fragment, createRef, memo, useEffect, useRef, useState } from "react";
import "./webview.less";
let webviewPreloadUrl = null;
@ -68,8 +68,8 @@ export class WebViewModel implements ViewModel {
this.refreshIcon = atom("rotate-right");
this.viewIcon = atom("globe");
this.viewName = atom("Web");
this.urlInputRef = React.createRef<HTMLInputElement>();
this.webviewRef = React.createRef<WebviewTag>();
this.urlInputRef = createRef<HTMLInputElement>();
this.webviewRef = createRef<WebviewTag>();
this.mediaPlaying = atom(false);
this.mediaMuted = atom(false);
@ -477,7 +477,7 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
const defaultSearch = useAtomValue(defaultSearchAtom);
let metaUrl = blockData?.meta?.url || defaultUrl;
metaUrl = model.ensureUrlScheme(metaUrl, defaultSearch);
const metaUrlRef = React.useRef(metaUrl);
const metaUrlRef = useRef(metaUrl);
// The initial value of the block metadata URL when the component first renders. Used to set the starting src value for the webview.
const [metaUrlInitial] = useState(metaUrl);
@ -485,6 +485,8 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
const [webContentsId, setWebContentsId] = useState(null);
const [domReady, setDomReady] = useState(false);
const [errorText, setErrorText] = useState("");
function setBgColor() {
const webview = model.webviewRef.current;
if (!webview) {
@ -532,6 +534,7 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
return;
}
const navigateListener = (e: any) => {
setErrorText("");
model.handleNavigate(e.url);
};
const newWindowHandler = (e: any) => {
@ -554,7 +557,9 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
if (e.errorCode === -3) {
console.warn("Suppressed ERR_ABORTED error", e);
} else {
console.error(`Failed to load ${e.validatedURL}: ${e.errorDescription}`);
const errorMessage = `Failed to load ${e.validatedURL}: ${e.errorDescription}`;
console.error(errorMessage);
setErrorText(errorMessage);
if (onFailLoad) {
const curUrl = model.webviewRef?.current.getURL();
onFailLoad(curUrl);
@ -608,17 +613,24 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
}, []);
return (
<webview
id="webview"
className="webview"
ref={model.webviewRef}
src={metaUrlInitial}
data-blockid={model.blockId}
data-webcontentsid={webContentsId} // needed for emain
preload={getWebviewPreloadUrl()}
// @ts-ignore This is a discrepancy between the React typing and the Chromium impl for webviewTag. Chrome webviewTag expects a string, while React expects a boolean.
allowpopups="true"
></webview>
<Fragment>
<webview
id="webview"
className="webview"
ref={model.webviewRef}
src={metaUrlInitial}
data-blockid={model.blockId}
data-webcontentsid={webContentsId} // needed for emain
preload={getWebviewPreloadUrl()}
// @ts-ignore This is a discrepancy between the React typing and the Chromium impl for webviewTag. Chrome webviewTag expects a string, while React expects a boolean.
allowpopups="true"
/>
{errorText && (
<div className="webview-error">
<div>{errorText}</div>
</div>
)}
</Fragment>
);
});