diff --git a/packages/wallet-webui/src/ui/Shell.tsx b/packages/wallet-webui/src/ui/Shell.tsx index e13a98baa..51d048224 100644 --- a/packages/wallet-webui/src/ui/Shell.tsx +++ b/packages/wallet-webui/src/ui/Shell.tsx @@ -1,4 +1,5 @@ import type { ComponentChildren } from "preact"; +import { useEffect, useState } from "preact/hooks"; import { Link, useLocation } from "wouter-preact"; import { WalletBrand } from "./WalletBrand.js"; import { WalletIcon, type WalletIconName } from "./WalletIcon.js"; @@ -17,6 +18,7 @@ export function Shell(props: { }; }) { const [location] = useLocation(); + const online = useBrowserOnline(); const route = location.split("?", 1)[0]; const selected = (href: string) => href === "/" @@ -38,6 +40,14 @@ export function Shell(props: { const balancesLabel = i18n.str`Balances`; return (
+ {!online && ( +

{ + /* Translators: Shown while the browser reports that the device has no network connection. */ i18n.str`No internet connection. The wallet will continue when you are back online.` + }

+ )}
@@ -211,3 +221,21 @@ function MobileNav(props: { ); } + +/** The browser's own idea of network connectivity (navigator.onLine). */ +function useBrowserOnline(): boolean { + const [online, setOnline] = useState( + typeof navigator === "undefined" ? true : navigator.onLine, + ); + useEffect(() => { + const update = () => setOnline(navigator.onLine); + window.addEventListener("online", update); + window.addEventListener("offline", update); + update(); + return () => { + window.removeEventListener("online", update); + window.removeEventListener("offline", update); + }; + }, []); + return online; +}