mirror of
https://github.com/aljazceru/mutiny-web.git
synced 2025-12-20 15:54:22 +01:00
check for browser features
This commit is contained in:
committed by
Tony Giorgio
parent
379f7e502a
commit
03f5ab667e
47
src/components/SetupErrorDisplay.tsx
Normal file
47
src/components/SetupErrorDisplay.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { Title } from "solid-start";
|
||||||
|
import { DefaultMain, LargeHeader, NiceP, SafeArea } from "~/components/layout";
|
||||||
|
import { ExternalLink } from "./layout/ExternalLink";
|
||||||
|
|
||||||
|
export default function SetupErrorDisplay(props: { error: Error }) {
|
||||||
|
return (
|
||||||
|
<SafeArea>
|
||||||
|
<Title>Incompatible browser</Title>
|
||||||
|
<DefaultMain>
|
||||||
|
<LargeHeader>Incompatible browser detected</LargeHeader>
|
||||||
|
<p class="bg-white/10 rounded-xl p-4 font-mono">
|
||||||
|
<span class="font-bold">{props.error.name}</span>:{" "}
|
||||||
|
{props.error.message}
|
||||||
|
</p>
|
||||||
|
<NiceP>
|
||||||
|
Mutiny requires a modern browser that supports WebAssembly,
|
||||||
|
LocalStorage, and IndexedDB. Some browsers disable these
|
||||||
|
features in private mode.
|
||||||
|
</NiceP>
|
||||||
|
<NiceP>
|
||||||
|
Please make sure your browser supports all these features,
|
||||||
|
or consider trying another browser. You might also try
|
||||||
|
disabling certain extensions or "shields" that block these
|
||||||
|
features.
|
||||||
|
</NiceP>
|
||||||
|
<NiceP>
|
||||||
|
(We'd love to support more private browsers, but we have to
|
||||||
|
save your wallet data to browser storage or else you will
|
||||||
|
lose funds.)
|
||||||
|
</NiceP>
|
||||||
|
<ExternalLink href="https://github.com/MutinyWallet/mutiny-web/wiki/Browser-Compatibility">
|
||||||
|
Supported Browsers
|
||||||
|
</ExternalLink>
|
||||||
|
|
||||||
|
<div class="h-full" />
|
||||||
|
<p class="self-center text-neutral-500 mt-4">
|
||||||
|
Bugs? Feedback?{" "}
|
||||||
|
<span class="text-neutral-400">
|
||||||
|
<ExternalLink href="https://github.com/MutinyWallet/mutiny-web/issues">
|
||||||
|
Create an issue
|
||||||
|
</ExternalLink>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</DefaultMain>
|
||||||
|
</SafeArea>
|
||||||
|
);
|
||||||
|
}
|
||||||
66
src/logic/browserCompatibility.ts
Normal file
66
src/logic/browserCompatibility.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
export async function checkBrowserCompatibility(): Promise<boolean> {
|
||||||
|
// Check if we can write to localstorage
|
||||||
|
console.debug("Checking localstorage");
|
||||||
|
try {
|
||||||
|
localStorage.setItem("test", "test");
|
||||||
|
localStorage.removeItem("test");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
throw new Error("LocalStorage is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the browser supports WebAssembly
|
||||||
|
console.debug("Checking WebAssembly");
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
typeof WebAssembly === "object" &&
|
||||||
|
typeof WebAssembly.instantiate === "function"
|
||||||
|
) {
|
||||||
|
const module = new WebAssembly.Module(
|
||||||
|
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
|
||||||
|
);
|
||||||
|
if (module instanceof WebAssembly.Module) {
|
||||||
|
// continue
|
||||||
|
} else {
|
||||||
|
throw new Error("WebAssembly is not supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
throw new Error("WebAssembly is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug("Checking indexedDB");
|
||||||
|
// Check if we can write to IndexedDB
|
||||||
|
try {
|
||||||
|
await openDatabase();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
throw new Error("IndexedDB is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDatabase(): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
console.debug("Checking IndexedDB is on the window object");
|
||||||
|
if (!("indexedDB" in window)) {
|
||||||
|
reject("IndexedDB not supported.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug("Opening IndexedDB");
|
||||||
|
const dbName = "compatibility-test-db";
|
||||||
|
const request = indexedDB.open(dbName, 1);
|
||||||
|
|
||||||
|
request.onsuccess = (_event) => {
|
||||||
|
indexedDB.deleteDatabase(dbName);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = (_event) => {
|
||||||
|
reject("Error opening database.");
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -4,24 +4,25 @@ import { WaitlistAlreadyIn } from "~/components/waitlist/WaitlistAlreadyIn";
|
|||||||
import WaitlistForm from "~/components/waitlist/WaitlistForm";
|
import WaitlistForm from "~/components/waitlist/WaitlistForm";
|
||||||
import { useMegaStore } from "~/state/megaStore";
|
import { useMegaStore } from "~/state/megaStore";
|
||||||
import { FullscreenLoader } from "~/components/layout";
|
import { FullscreenLoader } from "~/components/layout";
|
||||||
|
import SetupErrorDisplay from "~/components/SetupErrorDisplay";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [state, _] = useMegaStore();
|
const [state, _] = useMegaStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Switch fallback={<FullscreenLoader />}>
|
||||||
<Switch fallback={<FullscreenLoader />}>
|
<Match when={state.setup_error}>
|
||||||
{/* TODO: can you put a suspense around a match? */}
|
<SetupErrorDisplay error={state.setup_error!} />
|
||||||
<Match when={state.user_status === "approved"}>
|
</Match>
|
||||||
<App />
|
<Match when={state.user_status === "approved"}>
|
||||||
</Match>
|
<App />
|
||||||
<Match when={state.user_status === "waitlisted"}>
|
</Match>
|
||||||
<WaitlistAlreadyIn />
|
<Match when={state.user_status === "waitlisted"}>
|
||||||
</Match>
|
<WaitlistAlreadyIn />
|
||||||
<Match when={state.user_status === "new_here"}>
|
</Match>
|
||||||
<WaitlistForm />
|
<Match when={state.user_status === "new_here"}>
|
||||||
</Match>
|
<WaitlistForm />
|
||||||
</Switch>
|
</Match>
|
||||||
</>
|
</Switch>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import {
|
|||||||
} from "@mutinywallet/mutiny-wasm";
|
} from "@mutinywallet/mutiny-wasm";
|
||||||
import { ParsedParams } from "~/routes/Scanner";
|
import { ParsedParams } from "~/routes/Scanner";
|
||||||
import { MutinyTagItem } from "~/utils/tags";
|
import { MutinyTagItem } from "~/utils/tags";
|
||||||
|
import { checkBrowserCompatibility } from "~/logic/browserCompatibility";
|
||||||
|
import eify from "~/utils/eify";
|
||||||
|
|
||||||
const MegaStoreContext = createContext<MegaStore>();
|
const MegaStoreContext = createContext<MegaStore>();
|
||||||
|
|
||||||
@@ -43,6 +45,7 @@ export type MegaStore = [
|
|||||||
wallet_loading: boolean;
|
wallet_loading: boolean;
|
||||||
nwc_enabled: boolean;
|
nwc_enabled: boolean;
|
||||||
activity: MutinyActivity[];
|
activity: MutinyActivity[];
|
||||||
|
setup_error?: Error;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fetchUserStatus(): Promise<UserStatus>;
|
fetchUserStatus(): Promise<UserStatus>;
|
||||||
@@ -56,6 +59,7 @@ export type MegaStore = [
|
|||||||
listTags(): Promise<MutinyTagItem[]>;
|
listTags(): Promise<MutinyTagItem[]>;
|
||||||
setNwc(enabled: boolean): void;
|
setNwc(enabled: boolean): void;
|
||||||
syncActivity(): Promise<void>;
|
syncActivity(): Promise<void>;
|
||||||
|
checkBrowserCompat(): Promise<boolean>;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -78,7 +82,8 @@ export const Provider: ParentComponent = (props) => {
|
|||||||
localStorage.getItem("dismissed_restore_prompt") === "true",
|
localStorage.getItem("dismissed_restore_prompt") === "true",
|
||||||
wallet_loading: true,
|
wallet_loading: true,
|
||||||
nwc_enabled: localStorage.getItem("nwc_enabled") === "true",
|
nwc_enabled: localStorage.getItem("nwc_enabled") === "true",
|
||||||
activity: [] as MutinyActivity[]
|
activity: [] as MutinyActivity[],
|
||||||
|
setup_error: undefined as Error | undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
@@ -189,6 +194,14 @@ export const Provider: ParentComponent = (props) => {
|
|||||||
setNwc(enabled: boolean) {
|
setNwc(enabled: boolean) {
|
||||||
localStorage.setItem("nwc_enabled", enabled.toString());
|
localStorage.setItem("nwc_enabled", enabled.toString());
|
||||||
setState({ nwc_enabled: enabled });
|
setState({ nwc_enabled: enabled });
|
||||||
|
},
|
||||||
|
async checkBrowserCompat(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
return await checkBrowserCompatibility();
|
||||||
|
} catch (e) {
|
||||||
|
setState({ setup_error: eify(e) });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -204,17 +217,26 @@ export const Provider: ParentComponent = (props) => {
|
|||||||
!state.mutiny_wallet &&
|
!state.mutiny_wallet &&
|
||||||
!state.deleting
|
!state.deleting
|
||||||
) {
|
) {
|
||||||
console.log("running setup node manager...");
|
console.log("checking for browser compatibility...");
|
||||||
actions
|
actions.checkBrowserCompat().then((browserIsGood) => {
|
||||||
.setupMutinyWallet()
|
if (browserIsGood) {
|
||||||
.then(() => console.log("node manager setup done"));
|
console.log("running setup node manager...");
|
||||||
|
actions
|
||||||
|
.setupMutinyWallet()
|
||||||
|
.then(() => console.log("node manager setup done"))
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
setState({ setup_error: eify(e) });
|
||||||
|
});
|
||||||
|
|
||||||
// Setup an event listener to stop the mutiny wallet when the page unloads
|
// Setup an event listener to stop the mutiny wallet when the page unloads
|
||||||
window.onunload = async (_e) => {
|
window.onunload = async (_e) => {
|
||||||
console.log("stopping mutiny_wallet");
|
console.log("stopping mutiny_wallet");
|
||||||
await state.mutiny_wallet?.stop();
|
await state.mutiny_wallet?.stop();
|
||||||
console.log("mutiny_wallet stopped");
|
console.log("mutiny_wallet stopped");
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user