forked from Rosetta/landing
Фикс ошибок
This commit is contained in:
@@ -13,6 +13,7 @@ server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
add_header Cache-Control "no-cache" always;
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
src/App.tsx
73
src/App.tsx
@@ -1,7 +1,7 @@
|
|||||||
import '@mantine/core/styles.css';
|
import '@mantine/core/styles.css';
|
||||||
|
|
||||||
import { Center, createTheme, Loader, MantineProvider } from '@mantine/core';
|
import { Button, Center, createTheme, Loader, MantineProvider, Stack, Text, Title } from '@mantine/core';
|
||||||
import { lazy, Suspense } from 'react';
|
import { Component, lazy, Suspense, type ReactNode } from 'react';
|
||||||
import { Route, Routes } from 'react-router-dom';
|
import { Route, Routes } from 'react-router-dom';
|
||||||
import { ScrollToTop } from './components/ScrollToTop/ScrollToTop';
|
import { ScrollToTop } from './components/ScrollToTop/ScrollToTop';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
@@ -39,27 +39,60 @@ const theme = createTheme({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
class PageErrorBoundary extends Component<
|
||||||
|
{ children: ReactNode },
|
||||||
|
{ hasError: boolean }
|
||||||
|
> {
|
||||||
|
state = { hasError: false };
|
||||||
|
|
||||||
|
static getDerivedStateFromError() {
|
||||||
|
return { hasError: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return (
|
||||||
|
<Center mih="100vh" p="xl">
|
||||||
|
<Stack align="center" gap="md" maw={460}>
|
||||||
|
<Title order={2} ta="center">
|
||||||
|
This page could not be loaded
|
||||||
|
</Title>
|
||||||
|
<Text c="dimmed" ta="center">
|
||||||
|
Rosetta may have been updated while this tab was open. Reload the page to continue.
|
||||||
|
</Text>
|
||||||
|
<Button onClick={() => window.location.reload()}>Reload page</Button>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<MantineProvider theme={theme}>
|
<MantineProvider theme={theme}>
|
||||||
<ScrollToTop />
|
<PageErrorBoundary>
|
||||||
<Suspense
|
<ScrollToTop />
|
||||||
fallback={
|
<Suspense
|
||||||
<Center mih="100vh">
|
fallback={
|
||||||
<Loader aria-label="Loading page" />
|
<Center mih="100vh">
|
||||||
</Center>
|
<Loader aria-label="Loading page" />
|
||||||
}
|
</Center>
|
||||||
>
|
}
|
||||||
<Routes>
|
>
|
||||||
<Route path="/" element={<LandingPage />} />
|
<Routes>
|
||||||
<Route path="/encryption" element={<EncryptionPage />} />
|
<Route path="/" element={<LandingPage />} />
|
||||||
<Route path="/proto" element={<ProtoPage />} />
|
<Route path="/encryption" element={<EncryptionPage />} />
|
||||||
<Route path="/proto/docs" element={<ProtoDocsPage />} />
|
<Route path="/proto" element={<ProtoPage />} />
|
||||||
<Route path="/support" element={<SupportPage />} />
|
<Route path="/proto/docs" element={<ProtoDocsPage />} />
|
||||||
<Route path="/privacy" element={<PrivacyPage />} />
|
<Route path="/support" element={<SupportPage />} />
|
||||||
<Route path="/terms" element={<TermsPage />} />
|
<Route path="/privacy" element={<PrivacyPage />} />
|
||||||
</Routes>
|
<Route path="/terms" element={<TermsPage />} />
|
||||||
</Suspense>
|
</Routes>
|
||||||
|
</Suspense>
|
||||||
|
</PageErrorBoundary>
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
.page {
|
.page {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-9));
|
background: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-9));
|
||||||
}
|
}
|
||||||
|
|
||||||
.shell {
|
.shell {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
padding-top: 72px;
|
padding-top: 72px;
|
||||||
padding-bottom: 96px;
|
padding-bottom: 96px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
padding: clamp(30px, 5vw, 60px);
|
padding: clamp(30px, 5vw, 60px);
|
||||||
@@ -21,6 +25,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.intro {
|
.intro {
|
||||||
|
min-width: 0;
|
||||||
max-width: 760px;
|
max-width: 760px;
|
||||||
padding-bottom: 36px;
|
padding-bottom: 36px;
|
||||||
border-bottom: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5));
|
border-bottom: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5));
|
||||||
@@ -69,6 +74,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
|
min-width: 0;
|
||||||
margin-top: 44px;
|
margin-top: 44px;
|
||||||
padding-top: 36px;
|
padding-top: 36px;
|
||||||
border-top: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5));
|
border-top: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5));
|
||||||
|
|||||||
36
src/main.tsx
36
src/main.tsx
@@ -2,6 +2,42 @@ import { createRoot } from 'react-dom/client'
|
|||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
|
|
||||||
|
const PRELOAD_RELOAD_KEY = 'rosetta:preload-reload-at'
|
||||||
|
const PRELOAD_RELOAD_COOLDOWN = 10_000
|
||||||
|
|
||||||
|
if (import.meta.env.PROD) {
|
||||||
|
window.addEventListener('vite:preloadError', (event) => {
|
||||||
|
let lastReload = 0
|
||||||
|
|
||||||
|
try {
|
||||||
|
lastReload = Number(window.sessionStorage.getItem(PRELOAD_RELOAD_KEY) || 0)
|
||||||
|
} catch {
|
||||||
|
// Storage can be unavailable in restricted browser modes.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Date.now() - lastReload < PRELOAD_RELOAD_COOLDOWN) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
try {
|
||||||
|
window.sessionStorage.setItem(PRELOAD_RELOAD_KEY, String(Date.now()))
|
||||||
|
} catch {
|
||||||
|
// Reload recovery still works when storage is unavailable.
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
try {
|
||||||
|
window.sessionStorage.removeItem(PRELOAD_RELOAD_KEY)
|
||||||
|
} catch {
|
||||||
|
// Nothing to clear when storage is unavailable.
|
||||||
|
}
|
||||||
|
}, PRELOAD_RELOAD_COOLDOWN)
|
||||||
|
}
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
function withFreshHtml(response) {
|
||||||
|
if (!response.headers.get('content-type')?.includes('text/html')) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = new Headers(response.headers);
|
||||||
|
headers.set('Cache-Control', 'no-cache');
|
||||||
|
|
||||||
|
return new Response(response.body, {
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const worker = {
|
const worker = {
|
||||||
async fetch(request, env) {
|
async fetch(request, env) {
|
||||||
const response = await env.ASSETS.fetch(request);
|
const response = await env.ASSETS.fetch(request);
|
||||||
@@ -7,11 +22,12 @@ const worker = {
|
|||||||
request.method !== 'GET' ||
|
request.method !== 'GET' ||
|
||||||
!request.headers.get('accept')?.includes('text/html')
|
!request.headers.get('accept')?.includes('text/html')
|
||||||
) {
|
) {
|
||||||
return response;
|
return withFreshHtml(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
const indexUrl = new URL('/index.html', request.url);
|
const indexUrl = new URL('/index.html', request.url);
|
||||||
return env.ASSETS.fetch(new Request(indexUrl, request));
|
const indexResponse = await env.ASSETS.fetch(new Request(indexUrl, request));
|
||||||
|
return withFreshHtml(indexResponse);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user