Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions frontend/app/view/webview/webview.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,32 @@
overflow: hidden;
padding: 0;
margin: 0;
user-select: none;

// try to force pixel alignment to prevent
// subpixel rendering artifacts
transform: translate3d(0, 0, 0);
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);

Expand Down
44 changes: 28 additions & 16 deletions frontend/app/view/webview/webview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -477,14 +477,16 @@ 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);

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

const [errorText, setErrorText] = useState("");

function setBgColor() {
const webview = model.webviewRef.current;
if (!webview) {
Expand Down Expand Up @@ -532,6 +534,7 @@ const WebView = memo(({ model, onFailLoad }: WebViewProps) => {
return;
}
const navigateListener = (e: any) => {
setErrorText("");
model.handleNavigate(e.url);
};
const newWindowHandler = (e: any) => {
Expand All @@ -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);
Expand Down Expand Up @@ -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>
);
});

Expand Down