on master help sign in
add browser warning recommending chromium-based browser
b4af090~sarlev-sarsen
src/Bridge.tsx+12−5
@@ -20,6 +20,9 @@ import light from '@tlon/indigo-light';
20
20
21import WithErrorBoundary from 'components/WithErrorBoundary';
21import WithErrorBoundary from 'components/WithErrorBoundary';
22import GlobalErrorBoundary from 'components/GlobalErrorBoundary';
22import GlobalErrorBoundary from 'components/GlobalErrorBoundary';
23+import { useBrowser } from 'lib/useBrowser';
24+import { BrowserWarning } from 'components/BrowserWarning';
25+
23import Modal from 'components/L2/Modal';
26import Modal from 'components/L2/Modal';
24import { useRollerStore } from 'store/rollerStore';
27import { useRollerStore } from 'store/rollerStore';
25import { Box } from '@tlon/indigo-react';
28import { Box } from '@tlon/indigo-react';
@@ -29,8 +32,8 @@ import { useRollerPoller } from 'lib/useRollerPoller';
29const INITIAL_NETWORK_TYPE = isGoerli
32const INITIAL_NETWORK_TYPE = isGoerli
30 ? NETWORK_TYPES.GOERLI
33 ? NETWORK_TYPES.GOERLI
31 : isDevelopment && !isMainnet
34 : isDevelopment && !isMainnet
32− ? NETWORK_TYPES.LOCAL
35+ ? NETWORK_TYPES.LOCAL
33− : NETWORK_TYPES.MAINNET;
36+ : NETWORK_TYPES.MAINNET;
34
37
35// NB(shrugs): modify these variables to change the default local state.
38// NB(shrugs): modify these variables to change the default local state.
36const SHOULD_STUB_LOCAL = import.meta.env.VITE_STUB_LOCAL === 'true';
39const SHOULD_STUB_LOCAL = import.meta.env.VITE_STUB_LOCAL === 'true';
@@ -38,9 +41,9 @@ const IS_STUBBED = isDevelopment && SHOULD_STUB_LOCAL;
38
41
39const INITIAL_WALLET = IS_STUBBED
42const INITIAL_WALLET = IS_STUBBED
40 ? walletFromMnemonic(
43 ? walletFromMnemonic(
41− import.meta.env.VITE_DEV_MNEMONIC as string,
44+ import.meta.env.VITE_DEV_MNEMONIC as string,
42− import.meta.env.VITE_HD_PATH as string
45+ import.meta.env.VITE_HD_PATH as string
43− )
46+ )
44 : undefined;
47 : undefined;
45const INITIAL_MNEMONIC = IS_STUBBED
48const INITIAL_MNEMONIC = IS_STUBBED
46 ? Just(import.meta.env.VITE_DEV_MNEMONIC)
49 ? Just(import.meta.env.VITE_DEV_MNEMONIC)
@@ -82,6 +85,9 @@ function Bridge() {
82 const initialRoutes = useInitialRoutes();
85 const initialRoutes = useInitialRoutes();
83 const { loading, modalText, setModalText } = useRollerStore();
86 const { loading, modalText, setModalText } = useRollerStore();
84
87
88+ const browser = useBrowser();
89+ const showBrowserWarning = browser && !browser.isChromium;
90+
85 // full reload if the user changes their selected network in Metamask
91 // full reload if the user changes their selected network in Metamask
86 //
92 //
87 useEffect(() => {
93 useEffect(() => {
@@ -103,6 +109,7 @@ function Bridge() {
103 initialWallet={INITIAL_WALLET}
109 initialWallet={INITIAL_WALLET}
104 initialMnemonic={INITIAL_MNEMONIC}
110 initialMnemonic={INITIAL_MNEMONIC}
105 initialPointCursor={INITIAL_POINT_CURSOR}>
111 initialPointCursor={INITIAL_POINT_CURSOR}>
112+ <BrowserWarning show={!!showBrowserWarning} />
106 <IndigoApp>
113 <IndigoApp>
107 <ThemeProvider theme={light}>
114 <ThemeProvider theme={light}>
108 <Router />
115 <Router />
src/components/BrowserWarning.tsxnew file+27
@@ -0,0 +1,27 @@
1+import React from 'react';
2+import { Box } from '@tlon/indigo-react';
3+import styled from 'styled-components';
4+
5+const WarningBox = styled(Box)`
6+ background: #fff4e5;
7+ color: #663c00;
8+ border: 1px solid #ffb74d;
9+ padding: 0.75rem 1rem;
10+ text-align: center;
11+ font-weight: 600;
12+ margin-bottom: 1rem;
13+`;
14+
15+interface Props {
16+ show: boolean;
17+}
18+export const BrowserWarning: React.FC<Props> = ({ show }) => {
19+ if (!show) return null;
20+ return (
21+ <WarningBox role="alert">
22+ For the best experience we recommend using a Chromium‑based browser
23+ (Chrome, Brave, etc.).
24+ </WarningBox>
25+ );
26+};
27+
src/lib/useBrowser.tsnew file+32
@@ -0,0 +1,32 @@
1+import { useEffect, useState } from 'react';
2+
3+export function useBrowser() {
4+ const [browser, setBrowser] = useState<{
5+ name: 'chrome' | 'brave' | 'safari' | 'firefox' | 'edge' | 'other';
6+ isChromium: boolean;
7+ } | null>(null);
8+
9+ useEffect(() => {
10+ const ua = navigator.userAgent;
11+ const vendor = navigator.vendor ?? '';
12+
13+ const isChromium = !!(window as any).chrome;
14+ const isBrave = !!(navigator as any).brave;
15+ const isSafari = /Safari/.test(ua) && !/Chrome/.test(ua);
16+ const isFirefox = /Firefox/.test(ua);
17+ const isEdge = /Edg/.test(ua);
18+ const isChrome = isChromium && !isBrave && !isEdge && /Chrome/.test(ua);
19+
20+ let name: typeof browser['name'] = 'other';
21+ if (isBrave) name = 'brave';
22+ else if (isChrome) name = 'chrome';
23+ else if (isSafari) name = 'safari';
24+ else if (isFirefox) name = 'firefox';
25+ else if (isEdge) name = 'edge';
26+
27+ setBrowser({ name, isChromium });
28+ }, []);
29+
30+ return browser;
31+}
32+