Compare commits
3 Commits
6eec1cff6b
...
2a13d11e9d
Author | SHA1 | Date |
---|---|---|
Juan Di Toro | 2a13d11e9d | |
Juan Di Toro | 2b5fbc8b36 | |
Derrick Hammer | 9836b5de26 |
|
@ -36,29 +36,36 @@ const App: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Navigator />
|
<Navigator />
|
||||||
{true || ethStatus?.syncState === "syncing" ||
|
{ethStatus?.syncState === "syncing" ||
|
||||||
handshakeStatus?.syncState === "syncing" ? (
|
handshakeStatus?.syncState === "syncing" ? (
|
||||||
<div className="py-4 -mb-4 flex flex-row gap-x-3">
|
<div className="py-4 -mb-4 flex flex-row gap-x-3">
|
||||||
{ethStatus?.syncState === "syncing" ? (
|
{ethStatus?.syncState === "syncing" ? (
|
||||||
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
||||||
<CircleProgressBar radius={5} strokeWidth={3} percentage={Math.floors(ethStatus.sync)} />
|
<CircleProgressBar radius={5} strokeWidth={3} percentage={Math.floor(ethStatus.sync)} />
|
||||||
<span className="font-bold font-mono text-orange-400 mr-2">{ethStatus.sync.toFixed(1)}%</span> Syncing Ethereum Network
|
<span className="font-bold font-mono text-orange-400 mr-2">{ethStatus.sync.toFixed(1)}%</span> Syncing Ethereum Network
|
||||||
</span>
|
</span>
|
||||||
) : ethStatus?.syncState === "done" ? (
|
) : ethStatus?.syncState === "done" ? (
|
||||||
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
||||||
<CircleProgressBar radius={5} strokeWidth={3} percentage={100} />
|
<CircleProgressBar radius={5} strokeWidth={3} percentage={100} />{" "}
|
||||||
{" "} Ethereum Synced
|
Ethereum Synced
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
{handshakeStatus?.syncState === "syncing" ? (
|
{handshakeStatus?.syncState === "syncing" ? (
|
||||||
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
||||||
<CircleProgressBar radius={5} strokeWidth={3} percentage={Math.floor(handshakeStatus.sync)} />
|
<CircleProgressBar
|
||||||
<span className="font-bold font-mono text-orange-400 mr-2">{handshakeStatus.sync.toFixed(1)}%</span> Syncing Handshake Network
|
radius={5}
|
||||||
|
strokeWidth={3}
|
||||||
|
percentage={Math.floor(handshakeStatus.sync)}
|
||||||
|
/>
|
||||||
|
<span className="font-bold font-mono text-orange-400 mr-2">
|
||||||
|
{handshakeStatus.sync.toFixed(1)}%
|
||||||
|
</span>{" "}
|
||||||
|
Syncing Handshake Network
|
||||||
</span>
|
</span>
|
||||||
) : handshakeStatus?.syncState === "done" ? (
|
) : handshakeStatus?.syncState === "done" ? (
|
||||||
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
<span className="flex items-center gap-x-2 rounded-full bg-neutral-800 text-white p-1 px-4 bg">
|
||||||
<CircleProgressBar radius={5} strokeWidth={3} percentage={100} />
|
<CircleProgressBar radius={5} strokeWidth={3} percentage={100} />{" "}
|
||||||
{" "} Handshake Synced
|
Handshake Synced
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,11 +74,21 @@ const App: React.FC = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CircleProgressBar = ({ radius, strokeWidth, textSize, percentage } : {radius: number, strokeWidth: number, textSize?: number, percentage: number}) => {
|
const CircleProgressBar = ({
|
||||||
|
radius,
|
||||||
|
strokeWidth,
|
||||||
|
textSize,
|
||||||
|
percentage,
|
||||||
|
}: {
|
||||||
|
radius: number;
|
||||||
|
strokeWidth: number;
|
||||||
|
textSize?: number;
|
||||||
|
percentage: number;
|
||||||
|
}) => {
|
||||||
const circumference = 2 * Math.PI * radius;
|
const circumference = 2 * Math.PI * radius;
|
||||||
const offset = circumference - (percentage / 100) * circumference;
|
const offset = circumference - (percentage / 100) * circumference;
|
||||||
const color = Math.ceil(percentage) >= 100 ? "green-500" : "orange-400"
|
const color = Math.ceil(percentage) >= 100 ? "green-500" : "orange-400";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg width={radius * 2 + strokeWidth} height={radius * 2 + strokeWidth}>
|
<svg width={radius * 2 + strokeWidth} height={radius * 2 + strokeWidth}>
|
||||||
<circle
|
<circle
|
||||||
|
@ -93,16 +110,18 @@ const CircleProgressBar = ({ radius, strokeWidth, textSize, percentage } : {radi
|
||||||
strokeDashoffset={offset}
|
strokeDashoffset={offset}
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
/>
|
/>
|
||||||
{textSize ? <text
|
{textSize ? (
|
||||||
x="50%"
|
<text
|
||||||
className={`fill-${color}`}
|
x="50%"
|
||||||
y="50%"
|
className={`fill-${color}`}
|
||||||
textAnchor="middle"
|
y="50%"
|
||||||
dy=".3em"
|
textAnchor="middle"
|
||||||
fontSize={textSize}
|
dy=".3em"
|
||||||
>
|
fontSize={textSize}
|
||||||
{`${percentage}%`}
|
>
|
||||||
</text> : null }
|
{`${percentage}%`}
|
||||||
|
</text>
|
||||||
|
) : null}
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,8 @@ interface BrowserContextType {
|
||||||
setUrl: React.Dispatch<React.SetStateAction<string>>;
|
setUrl: React.Dispatch<React.SetStateAction<string>>;
|
||||||
isLoadingPage: boolean;
|
isLoadingPage: boolean;
|
||||||
setIsLoadingPage: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsLoadingPage: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
authStatus: LumeAuthStatus;
|
||||||
|
setAuthStatus: React.Dispatch<React.SetStateAction<LumeAuthStatus>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BrowserStateContext = createContext<BrowserContextType | undefined>(
|
const BrowserStateContext = createContext<BrowserContextType | undefined>(
|
||||||
|
@ -51,10 +53,18 @@ export function BrowserStateProvider({
|
||||||
}) {
|
}) {
|
||||||
const [url, setUrl] = useState("");
|
const [url, setUrl] = useState("");
|
||||||
const [isLoadingPage, setIsLoadingPage] = useState<boolean>(false);
|
const [isLoadingPage, setIsLoadingPage] = useState<boolean>(false);
|
||||||
|
const [authStatus, setAuthStatus] = useState<LumeAuthStatus>("idle");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BrowserStateContext.Provider
|
<BrowserStateContext.Provider
|
||||||
value={{ url, setUrl, isLoadingPage, setIsLoadingPage }}
|
value={{
|
||||||
|
url,
|
||||||
|
setUrl,
|
||||||
|
isLoadingPage,
|
||||||
|
setIsLoadingPage,
|
||||||
|
authStatus,
|
||||||
|
setAuthStatus,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</BrowserStateContext.Provider>
|
</BrowserStateContext.Provider>
|
||||||
|
@ -71,15 +81,18 @@ export function useBrowserState() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LumeAuthStatus = "idle" | "done" | "syncing";
|
||||||
|
|
||||||
async function boot({
|
async function boot({
|
||||||
onInit,
|
onInit,
|
||||||
onAuth,
|
onAuth,
|
||||||
onBoot,
|
onBoot,
|
||||||
}: {
|
}: {
|
||||||
onInit: (inited: boolean) => Promise<void> | void;
|
onInit: (inited: boolean) => Promise<void> | void;
|
||||||
onAuth: (authed: boolean) => Promise<void> | void;
|
onAuth: (authed: LumeAuthStatus) => Promise<void> | void;
|
||||||
onBoot: (booted: boolean) => Promise<void> | void;
|
onBoot: (booted: boolean) => Promise<void> | void;
|
||||||
}) {
|
}) {
|
||||||
|
await onAuth("idle");
|
||||||
let err = false;
|
let err = false;
|
||||||
const reg = await navigator.serviceWorker.register("/sw.js");
|
const reg = await navigator.serviceWorker.register("/sw.js");
|
||||||
await reg.update();
|
await reg.update();
|
||||||
|
@ -91,7 +104,8 @@ async function boot({
|
||||||
});
|
});
|
||||||
await onInit(true);
|
await onInit(true);
|
||||||
await kernelLoaded()
|
await kernelLoaded()
|
||||||
.then((result) => {
|
.then(async (result) => {
|
||||||
|
await onAuth("syncing");
|
||||||
if ("indexeddb_error" === (result as string)) {
|
if ("indexeddb_error" === (result as string)) {
|
||||||
alert(
|
alert(
|
||||||
"Error: Please ensure 3rd party cookies are enabled, and any security like brave shield is off, then reload the app",
|
"Error: Please ensure 3rd party cookies are enabled, and any security like brave shield is off, then reload the app",
|
||||||
|
@ -105,7 +119,7 @@ async function boot({
|
||||||
if (err) {
|
if (err) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await onAuth(true);
|
await onAuth("done");
|
||||||
|
|
||||||
BOOT_FUNCTIONS.push(
|
BOOT_FUNCTIONS.push(
|
||||||
async () =>
|
async () =>
|
||||||
|
@ -140,10 +154,11 @@ async function boot({
|
||||||
for (const resolver of resolvers) {
|
for (const resolver of resolvers) {
|
||||||
BOOT_FUNCTIONS.push(async () => dnsClient.registerResolver(resolver));
|
BOOT_FUNCTIONS.push(async () => dnsClient.registerResolver(resolver));
|
||||||
}
|
}
|
||||||
BOOT_FUNCTIONS.push(async () => onBoot(true));
|
|
||||||
|
|
||||||
await bootup();
|
await bootup();
|
||||||
|
|
||||||
|
await onBoot(true);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
ethClient.ready(),
|
ethClient.ready(),
|
||||||
handshakeClient.ready(),
|
handshakeClient.ready(),
|
||||||
|
@ -152,7 +167,7 @@ async function boot({
|
||||||
}
|
}
|
||||||
|
|
||||||
async function bootup() {
|
async function bootup() {
|
||||||
for (const entry of Object.entries(BOOT_FUNCTIONS)) {
|
for await (const entry of Object.entries(BOOT_FUNCTIONS)) {
|
||||||
console.log(entry[1].toString());
|
console.log(entry[1].toString());
|
||||||
await entry[1]();
|
await entry[1]();
|
||||||
}
|
}
|
||||||
|
@ -182,8 +197,8 @@ export function Navigator() {
|
||||||
|
|
||||||
const browse = (inputValue: string) => {
|
const browse = (inputValue: string) => {
|
||||||
try {
|
try {
|
||||||
if(inputValue === "") {
|
if (inputValue === "") {
|
||||||
setUrl("about:blank")
|
setUrl("about:blank");
|
||||||
}
|
}
|
||||||
// Try to parse it as a URL
|
// Try to parse it as a URL
|
||||||
const url = parseUrl(inputValue);
|
const url = parseUrl(inputValue);
|
||||||
|
@ -235,7 +250,8 @@ export function Navigator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Browser() {
|
export function Browser() {
|
||||||
const { url, setUrl, isLoadingPage, setIsLoadingPage } = useBrowserState();
|
const { url, setUrl, isLoadingPage, setIsLoadingPage, setAuthStatus } =
|
||||||
|
useBrowserState();
|
||||||
const status = useLumeStatus();
|
const status = useLumeStatus();
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||||
|
@ -243,7 +259,11 @@ export function Browser() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
boot({
|
boot({
|
||||||
onAuth(authed) {
|
onAuth(authed) {
|
||||||
auth.setIsLoggedIn(authed);
|
console.log({authed})
|
||||||
|
setAuthStatus(authed);
|
||||||
|
if (authed === "done") {
|
||||||
|
auth.setIsLoggedIn(true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onBoot(booted) {
|
onBoot(booted) {
|
||||||
status.setReady(booted);
|
status.setReady(booted);
|
||||||
|
@ -256,7 +276,9 @@ export function Browser() {
|
||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleIframeLoad = (event: React.SyntheticEvent<HTMLIFrameElement, Event>) => {
|
const handleIframeLoad = (
|
||||||
|
event: React.SyntheticEvent<HTMLIFrameElement, Event>,
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const newUrl = iframeRef?.current?.contentWindow?.location.href as string;
|
const newUrl = iframeRef?.current?.contentWindow?.location.href as string;
|
||||||
const urlObj = new URL(newUrl);
|
const urlObj = new URL(newUrl);
|
||||||
|
@ -267,8 +289,8 @@ export function Browser() {
|
||||||
setUrl(realUrl);
|
setUrl(realUrl);
|
||||||
}
|
}
|
||||||
const readyState = event.currentTarget.contentDocument?.readyState;
|
const readyState = event.currentTarget.contentDocument?.readyState;
|
||||||
console.log("[debug]",{readyState});
|
console.log("[debug]", { readyState });
|
||||||
if(readyState === 'interactive') {
|
if (readyState === "interactive") {
|
||||||
setIsLoadingPage(false);
|
setIsLoadingPage(false);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -285,7 +307,7 @@ export function Browser() {
|
||||||
if (iframe) {
|
if (iframe) {
|
||||||
const observer = new MutationObserver((mutationsList, observer) => {
|
const observer = new MutationObserver((mutationsList, observer) => {
|
||||||
for (let mutation of mutationsList) {
|
for (let mutation of mutationsList) {
|
||||||
console.log("[debug] Mutated ", {mutation})
|
console.log("[debug] Mutated ", { mutation });
|
||||||
if (
|
if (
|
||||||
mutation.type === "attributes" &&
|
mutation.type === "attributes" &&
|
||||||
mutation.attributeName === "src"
|
mutation.attributeName === "src"
|
||||||
|
@ -318,14 +340,14 @@ export function Browser() {
|
||||||
setUrl(_url.toString() || "about:blank");
|
setUrl(_url.toString() || "about:blank");
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<iframe
|
<iframe
|
||||||
ref={iframeRef}
|
ref={iframeRef}
|
||||||
onLoad={handleIframeLoad}
|
onLoad={handleIframeLoad}
|
||||||
src={url ? `/browse/${url}` : "about:blank"}
|
src={url ? `/browse/${url}` : "about:blank"}
|
||||||
className={`${shouldRenderStartPage ? "hidden": ""} w-full h-full`}
|
className={`${shouldRenderStartPage ? "hidden" : ""} w-full h-full`}
|
||||||
></iframe>
|
></iframe>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,13 @@ import {
|
||||||
LumeIdentityTrigger,
|
LumeIdentityTrigger,
|
||||||
useAuth,
|
useAuth,
|
||||||
useLumeStatus,
|
useLumeStatus,
|
||||||
|
useNetworks,
|
||||||
} from "@lumeweb/sdk";
|
} from "@lumeweb/sdk";
|
||||||
|
import { useBrowserState } from "./Browser";
|
||||||
|
|
||||||
const Lume: React.FC = () => {
|
const Lume: React.FC = () => {
|
||||||
const { isLoggedIn } = useAuth();
|
const { isLoggedIn } = useAuth();
|
||||||
|
const { authStatus } = useBrowserState();
|
||||||
const { ready, inited } = useLumeStatus();
|
const { ready, inited } = useLumeStatus();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -17,14 +20,14 @@ const Lume: React.FC = () => {
|
||||||
<LumeIdentityTrigger asChild>
|
<LumeIdentityTrigger asChild>
|
||||||
<button
|
<button
|
||||||
className="ml-2 w-full rounded-full bg-[hsl(113,49%,55%)] text-black disabled:pointer-events-none disabled:opacity-50"
|
className="ml-2 w-full rounded-full bg-[hsl(113,49%,55%)] text-black disabled:pointer-events-none disabled:opacity-50"
|
||||||
disabled={!inited}
|
disabled={!inited || authStatus === 'syncing'}
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
</button>
|
</button>
|
||||||
</LumeIdentityTrigger>
|
</LumeIdentityTrigger>
|
||||||
</LumeIdentity>
|
</LumeIdentity>
|
||||||
)}
|
)}
|
||||||
{isLoggedIn && <LumeDashboard disabled={!ready} />}
|
{isLoggedIn && <LumeDashboard disabled={!inited} />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,8 +26,6 @@ const StartPage = ({ setUrl }: Props) => {
|
||||||
from the Ethereum Name Service (ENS) and Handshake protocol, providing a
|
from the Ethereum Name Service (ENS) and Handshake protocol, providing a
|
||||||
secure and decentralized browsing experience.
|
secure and decentralized browsing experience.
|
||||||
</p>
|
</p>
|
||||||
{/* TODO: Add the lume loading indicators for the networks. */}
|
|
||||||
{/* <CircleProgressBar radius={20} strokeWidth={4} textSize={12} percentage={75} /> */}
|
|
||||||
{inited && ready ? (
|
{inited && ready ? (
|
||||||
<div>
|
<div>
|
||||||
<hr className="my-3 border-neutral-700" />
|
<hr className="my-3 border-neutral-700" />
|
||||||
|
@ -63,11 +61,11 @@ const StartPage = ({ setUrl }: Props) => {
|
||||||
) : null}
|
) : null}
|
||||||
{inited && !ready && isLoggedIn ? (
|
{inited && !ready && isLoggedIn ? (
|
||||||
<div
|
<div
|
||||||
className="bg-yellow-800/40 rounded-md border border-yellow-500 text-yellow-500 p-4"
|
className="bg-green-800/40 rounded-md border border-green-500 text-green-500 p-4"
|
||||||
role="alert"
|
role="alert"
|
||||||
>
|
>
|
||||||
<p className="font-bold">Be patient</p>
|
<p className="font-bold">You are logged in.</p>
|
||||||
<p>We are starting the engines.</p>
|
<p>We are now starting to sync the networks.</p>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{!isLoggedIn ? (
|
{!isLoggedIn ? (
|
||||||
|
|
Loading…
Reference in New Issue