feat: browser router and SPA 404.html
This commit is contained in:
parent
76478ad572
commit
99ce338502
31
index.html
31
index.html
@ -9,6 +9,37 @@
|
||||
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css" />
|
||||
|
||||
<title>DEG Mods - Liberating Game Mods</title>
|
||||
|
||||
<!-- Start Single Page Apps for GitHub Pages -->
|
||||
<script type="text/javascript">
|
||||
// Single Page Apps for GitHub Pages
|
||||
// MIT License
|
||||
// https://github.com/rafgraph/spa-github-pages
|
||||
// This script checks to see if a redirect is present in the query string,
|
||||
// converts it back into the correct url and adds it to the
|
||||
// browser's history using window.history.replaceState(...),
|
||||
// which won't cause the browser to attempt to load the new url.
|
||||
// When the single page app is loaded further down in this file,
|
||||
// the correct url will be waiting in the browser's history for
|
||||
// the single page app to route accordingly.
|
||||
;(function (l) {
|
||||
if (l.search[1] === '/') {
|
||||
var decoded = l.search
|
||||
.slice(1)
|
||||
.split('&')
|
||||
.map(function (s) {
|
||||
return s.replace(/~and~/g, '&')
|
||||
})
|
||||
.join('?')
|
||||
window.history.replaceState(
|
||||
null,
|
||||
null,
|
||||
l.pathname.slice(0, -1) + decoded + l.hash
|
||||
)
|
||||
}
|
||||
})(window.location)
|
||||
</script>
|
||||
<!-- End Single Page Apps for GitHub Pages -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
51
public/404.html
Normal file
51
public/404.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Single Page Apps for GitHub Pages</title>
|
||||
<script type="text/javascript">
|
||||
// Single Page Apps for GitHub Pages
|
||||
// MIT License
|
||||
// https://github.com/rafgraph/spa-github-pages
|
||||
// This script takes the current url and converts the path and query
|
||||
// string into just a query string, and then redirects the browser
|
||||
// to the new url with only a query string and hash fragment,
|
||||
// e.g. https://www.foo.tld/one/two?a=b&c=d#qwe, becomes
|
||||
// https://www.foo.tld/?/one/two&a=b~and~c=d#qwe
|
||||
// Note: this 404.html file must be at least 512 bytes for it to work
|
||||
// with Internet Explorer (it is currently > 512 bytes)
|
||||
|
||||
// If you're creating a Project Pages site and NOT using a custom domain,
|
||||
// then set pathSegmentsToKeep to 1 (enterprise users may need to set it to > 1).
|
||||
// This way the code will only replace the route part of the path, and not
|
||||
// the real directory in which the app resides, for example:
|
||||
// https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
|
||||
// https://username.github.io/repo-name/?/one/two&a=b~and~c=d#qwe
|
||||
// Otherwise, leave pathSegmentsToKeep as 0.
|
||||
var pathSegmentsToKeep = 0
|
||||
|
||||
var l = window.location
|
||||
l.replace(
|
||||
l.protocol +
|
||||
'//' +
|
||||
l.hostname +
|
||||
(l.port ? ':' + l.port : '') +
|
||||
l.pathname
|
||||
.split('/')
|
||||
.slice(0, 1 + pathSegmentsToKeep)
|
||||
.join('/') +
|
||||
'/?/' +
|
||||
l.pathname
|
||||
.slice(1)
|
||||
.split('/')
|
||||
.slice(pathSegmentsToKeep)
|
||||
.join('/')
|
||||
.replace(/&/g, '~and~') +
|
||||
(l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
|
||||
l.hash
|
||||
)
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
19
src/App.tsx
19
src/App.tsx
@ -1,7 +1,6 @@
|
||||
import { Route, Routes } from 'react-router-dom'
|
||||
import { Layout } from './layout'
|
||||
import { routes } from './routes'
|
||||
import { RouterProvider } from 'react-router-dom'
|
||||
import { useEffect } from 'react'
|
||||
import { router } from 'routes'
|
||||
import './styles/styles.css'
|
||||
|
||||
function App() {
|
||||
@ -22,19 +21,7 @@ function App() {
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<Layout />}>
|
||||
{routes.map((route, index) => (
|
||||
<Route
|
||||
key={route.path + index}
|
||||
path={route.path}
|
||||
element={route.element}
|
||||
/>
|
||||
))}
|
||||
</Route>
|
||||
</Routes>
|
||||
)
|
||||
return <RouterProvider router={router} />
|
||||
}
|
||||
|
||||
export default App
|
||||
|
@ -29,11 +29,11 @@ export const SocialNav = () => {
|
||||
svgPath='M511.8 287.6L512.5 447.7C512.5 450.5 512.3 453.1 512 455.8V472C512 494.1 494.1 512 472 512H456C454.9 512 453.8 511.1 452.7 511.9C451.3 511.1 449.9 512 448.5 512H392C369.9 512 352 494.1 352 472V384C352 366.3 337.7 352 320 352H256C238.3 352 224 366.3 224 384V472C224 494.1 206.1 512 184 512H128.1C126.6 512 125.1 511.9 123.6 511.8C122.4 511.9 121.2 512 120 512H104C81.91 512 64 494.1 64 472V360C64 359.1 64.03 358.1 64.09 357.2V287.6H32.05C14.02 287.6 0 273.5 0 255.5C0 246.5 3.004 238.5 10.01 231.5L266.4 8.016C273.4 1.002 281.4 0 288.4 0C295.4 0 303.4 2.004 309.5 7.014L416 100.7V64C416 46.33 430.3 32 448 32H480C497.7 32 512 46.33 512 64V185L564.8 231.5C572.8 238.5 576.9 246.5 575.8 255.5C575.8 273.5 560.8 287.6 543.8 287.6L511.8 287.6z'
|
||||
/>
|
||||
<NavButton
|
||||
to={appRoutes.home}
|
||||
to={appRoutes.feed}
|
||||
svgPath='M88 48C101.3 48 112 58.75 112 72V120C112 133.3 101.3 144 88 144H40C26.75 144 16 133.3 16 120V72C16 58.75 26.75 48 40 48H88zM480 64C497.7 64 512 78.33 512 96C512 113.7 497.7 128 480 128H192C174.3 128 160 113.7 160 96C160 78.33 174.3 64 192 64H480zM480 224C497.7 224 512 238.3 512 256C512 273.7 497.7 288 480 288H192C174.3 288 160 273.7 160 256C160 238.3 174.3 224 192 224H480zM480 384C497.7 384 512 398.3 512 416C512 433.7 497.7 448 480 448H192C174.3 448 160 433.7 160 416C160 398.3 174.3 384 192 384H480zM16 232C16 218.7 26.75 208 40 208H88C101.3 208 112 218.7 112 232V280C112 293.3 101.3 304 88 304H40C26.75 304 16 293.3 16 280V232zM88 368C101.3 368 112 378.7 112 392V440C112 453.3 101.3 464 88 464H40C26.75 464 16 453.3 16 440V392C16 378.7 26.75 368 40 368H88z'
|
||||
/>
|
||||
<NavButton
|
||||
to={appRoutes.home}
|
||||
to={appRoutes.notifications}
|
||||
svgPath='M256 32V51.2C329 66.03 384 130.6 384 208V226.8C384 273.9 401.3 319.2 432.5 354.4L439.9 362.7C448.3 372.2 450.4 385.6 445.2 397.1C440 408.6 428.6 416 416 416H32C19.4 416 7.971 408.6 2.809 397.1C-2.353 385.6-.2883 372.2 8.084 362.7L15.5 354.4C46.74 319.2 64 273.9 64 226.8V208C64 130.6 118.1 66.03 192 51.2V32C192 14.33 206.3 0 224 0C241.7 0 256 14.33 256 32H256zM224 512C207 512 190.7 505.3 178.7 493.3C166.7 481.3 160 464.1 160 448H288C288 464.1 281.3 481.3 269.3 493.3C257.3 505.3 240.1 512 224 512z'
|
||||
/>
|
||||
<NavButton
|
||||
|
11
src/main.tsx
11
src/main.tsx
@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import { Provider } from 'react-redux'
|
||||
import { HashRouter } from 'react-router-dom'
|
||||
import { ToastContainer } from 'react-toastify'
|
||||
import 'react-toastify/dist/ReactToastify.css'
|
||||
import App from './App.tsx'
|
||||
@ -12,12 +11,10 @@ import { NDKContextProvider } from 'contexts/NDKContext.tsx'
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<HashRouter>
|
||||
<NDKContextProvider>
|
||||
<App />
|
||||
</NDKContextProvider>
|
||||
<ToastContainer />
|
||||
</HashRouter>
|
||||
<NDKContextProvider>
|
||||
<App />
|
||||
</NDKContextProvider>
|
||||
<ToastContainer />
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
)
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { createBrowserRouter } from 'react-router-dom'
|
||||
import { Layout } from 'layout'
|
||||
import { SearchPage } from 'pages/search'
|
||||
import { AboutPage } from '../pages/about'
|
||||
import { BlogsPage } from '../pages/blogs'
|
||||
@ -10,6 +12,10 @@ import { SettingsPage } from '../pages/settings'
|
||||
import { SubmitModPage } from '../pages/submitMod'
|
||||
import { WritePage } from '../pages/write'
|
||||
import { GamePage } from 'pages/game'
|
||||
import { NotFoundPage } from 'pages/404'
|
||||
import { FeedLayout } from 'layout/feed'
|
||||
import { FeedPage } from 'pages/feed'
|
||||
import { NotificationsPage } from 'pages/notifications'
|
||||
|
||||
export const appRoutes = {
|
||||
index: '/',
|
||||
@ -28,7 +34,9 @@ export const appRoutes = {
|
||||
settingsRelays: '/settings-relays',
|
||||
settingsPreferences: '/settings-preferences',
|
||||
settingsAdmin: '/settings-admin',
|
||||
profile: '/profile/:nprofile?'
|
||||
profile: '/profile/:nprofile?',
|
||||
feed: '/feed',
|
||||
notifications: '/notifications'
|
||||
}
|
||||
|
||||
export const getGamePageRoute = (name: string) =>
|
||||
@ -43,73 +51,91 @@ export const getModsEditPageRoute = (eventId: string) =>
|
||||
export const getProfilePageRoute = (nprofile: string) =>
|
||||
appRoutes.profile.replace(':nprofile', nprofile)
|
||||
|
||||
export const routes = [
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
path: appRoutes.index,
|
||||
element: <HomePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.home,
|
||||
element: <HomePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.games,
|
||||
element: <GamesPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.game,
|
||||
element: <GamePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.mods,
|
||||
element: <ModsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.mod,
|
||||
element: <ModPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.about,
|
||||
element: <AboutPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.blog,
|
||||
element: <BlogsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.submitMod,
|
||||
element: <SubmitModPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.editMod,
|
||||
element: <SubmitModPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.write,
|
||||
element: <WritePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.search,
|
||||
element: <SearchPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsProfile,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsRelays,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsPreferences,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsAdmin,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.profile,
|
||||
element: <ProfilePage />
|
||||
element: <Layout />,
|
||||
children: [
|
||||
{
|
||||
path: appRoutes.index,
|
||||
element: <HomePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.games,
|
||||
element: <GamesPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.game,
|
||||
element: <GamePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.mods,
|
||||
element: <ModsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.mod,
|
||||
element: <ModPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.about,
|
||||
element: <AboutPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.blog,
|
||||
element: <BlogsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.submitMod,
|
||||
element: <SubmitModPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.editMod,
|
||||
element: <SubmitModPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.write,
|
||||
element: <WritePage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.search,
|
||||
element: <SearchPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsProfile,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsRelays,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsPreferences,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.settingsAdmin,
|
||||
element: <SettingsPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.profile,
|
||||
element: <ProfilePage />
|
||||
},
|
||||
{
|
||||
element: <FeedLayout />,
|
||||
children: [
|
||||
{
|
||||
path: appRoutes.feed,
|
||||
element: <FeedPage />
|
||||
},
|
||||
{
|
||||
path: appRoutes.notifications,
|
||||
element: <NotificationsPage />
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
element: <NotFoundPage />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user