Skip to content

Commit c711ffc

Browse files
authored
Display error message on failed WebView page load (wavetermdev#1072)
closes wavetermdev#1023
1 parent d167eb5 commit c711ffc

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

frontend/app/view/webview/webview.less

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,32 @@
99
overflow: hidden;
1010
padding: 0;
1111
margin: 0;
12+
user-select: none;
1213

1314
// try to force pixel alignment to prevent
1415
// subpixel rendering artifacts
1516
transform: translate3d(0, 0, 0);
1617
will-change: transform;
1718
}
1819

20+
.webview-error {
21+
display: flex;
22+
position: absolute;
23+
background-color: black;
24+
top: 0;
25+
left: 0;
26+
height: 100%;
27+
width: 100%;
28+
z-index: 100;
29+
div {
30+
font-size: x-large;
31+
color: red;
32+
display: flex;
33+
margin: auto;
34+
padding: 30px;
35+
}
36+
}
37+
1938
.block-frame-div-url {
2039
background: rgba(255, 255, 255, 0.1);
2140

frontend/app/view/webview/webview.tsx

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { fireAndForget } from "@/util/util";
1313
import clsx from "clsx";
1414
import { WebviewTag } from "electron";
1515
import { Atom, PrimitiveAtom, atom, useAtomValue } from "jotai";
16-
import React, { memo, useEffect, useState } from "react";
16+
import { Fragment, createRef, memo, useEffect, useRef, useState } from "react";
1717
import "./webview.less";
1818

1919
let webviewPreloadUrl = null;
@@ -68,8 +68,8 @@ export class WebViewModel implements ViewModel {
6868
this.refreshIcon = atom("rotate-right");
6969
this.viewIcon = atom("globe");
7070
this.viewName = atom("Web");
71-
this.urlInputRef = React.createRef<HTMLInputElement>();
72-
this.webviewRef = React.createRef<WebviewTag>();
71+
this.urlInputRef = createRef<HTMLInputElement>();
72+
this.webviewRef = createRef<WebviewTag>();
7373

7474
this.mediaPlaying = atom(false);
7575
this.mediaMuted = atom(false);
@@ -477,14 +477,16 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
477477
const defaultSearch = useAtomValue(defaultSearchAtom);
478478
let metaUrl = blockData?.meta?.url || defaultUrl;
479479
metaUrl = model.ensureUrlScheme(metaUrl, defaultSearch);
480-
const metaUrlRef = React.useRef(metaUrl);
480+
const metaUrlRef = useRef(metaUrl);
481481

482482
// The initial value of the block metadata URL when the component first renders. Used to set the starting src value for the webview.
483483
const [metaUrlInitial] = useState(metaUrl);
484484

485485
const [webContentsId, setWebContentsId] = useState(null);
486486
const [domReady, setDomReady] = useState(false);
487487

488+
const [errorText, setErrorText] = useState("");
489+
488490
function setBgColor() {
489491
const webview = model.webviewRef.current;
490492
if (!webview) {
@@ -532,6 +534,7 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
532534
return;
533535
}
534536
const navigateListener = (e: any) => {
537+
setErrorText("");
535538
model.handleNavigate(e.url);
536539
};
537540
const newWindowHandler = (e: any) => {
@@ -554,7 +557,9 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
554557
if (e.errorCode === -3) {
555558
console.warn("Suppressed ERR_ABORTED error", e);
556559
} else {
557-
console.error(`Failed to load ${e.validatedURL}: ${e.errorDescription}`);
560+
const errorMessage = `Failed to load ${e.validatedURL}: ${e.errorDescription}`;
561+
console.error(errorMessage);
562+
setErrorText(errorMessage);
558563
if (onFailLoad) {
559564
const curUrl = model.webviewRef?.current.getURL();
560565
onFailLoad(curUrl);
@@ -608,17 +613,24 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
608613
}, []);
609614

610615
return (
611-
<webview
612-
id="webview"
613-
className="webview"
614-
ref={model.webviewRef}
615-
src={metaUrlInitial}
616-
data-blockid={model.blockId}
617-
data-webcontentsid={webContentsId} // needed for emain
618-
preload={getWebviewPreloadUrl()}
619-
// @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.
620-
allowpopups="true"
621-
></webview>
616+
<Fragment>
617+
<webview
618+
id="webview"
619+
className="webview"
620+
ref={model.webviewRef}
621+
src={metaUrlInitial}
622+
data-blockid={model.blockId}
623+
data-webcontentsid={webContentsId} // needed for emain
624+
preload={getWebviewPreloadUrl()}
625+
// @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.
626+
allowpopups="true"
627+
/>
628+
{errorText && (
629+
<div className="webview-error">
630+
<div>{errorText}</div>
631+
</div>
632+
)}
633+
</Fragment>
622634
);
623635
});
624636

0 commit comments

Comments
 (0)