Skip to content

[Ref/Feat] Clean up our routing and make it faster #3540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 95 additions & 60 deletions src/frontend/App.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import React, { useContext } from 'react'

import './App.css'
import { HashRouter, Navigate, Route, Routes } from 'react-router-dom'
import Login from './screens/Login'
import WebView from './screens/WebView'
import { GamePage } from './screens/Game'
import Library from './screens/Library'
import WineManager from './screens/WineManager'
import {
createHashRouter,
Navigate,
Outlet,
RouterProvider
} from 'react-router-dom'
import Sidebar from './components/UI/Sidebar'
import Settings from './screens/Settings'
import Accessibility from './screens/Accessibility'
import ContextProvider from './state/ContextProvider'
import { ControllerHints, Help, OfflineMessage } from './components/UI'
import DownloadManager from './screens/DownloadManager'
import DialogHandler from './components/UI/DialogHandler'
import SettingsModal from './screens/Settings/components/SettingsModal'
import ExternalLinkDialog from './components/UI/ExternalLinkDialog'
import WindowControls from './components/UI/WindowControls'
import classNames from 'classnames'

function App() {
function Root() {
const {
isSettingsModalOpen,
isRTL,
Expand All @@ -44,57 +41,95 @@ function App() {
// disable dragging for all elements by default
onDragStart={(e) => e.preventDefault()}
>
<HashRouter>
<OfflineMessage />
<Sidebar />
<main className="content">
<DialogHandler />
{isSettingsModalOpen.gameInfo && (
<SettingsModal
gameInfo={isSettingsModalOpen.gameInfo}
type={isSettingsModalOpen.type}
/>
)}
<ExternalLinkDialog />
<Routes>
<Route path="/" element={<Navigate replace to="/library" />} />
<Route path="/library" element={<Library />} />
<Route path="login" element={<Login />} />
<Route path="epicstore" element={<WebView store="epic" />} />
<Route path="gogstore" element={<WebView store="gog" />} />
<Route path="amazonstore" element={<WebView store="amazon" />} />
<Route path="wiki" element={<WebView />} />
<Route path="/gamepage">
<Route path=":runner">
<Route path=":appName" element={<GamePage />} />
</Route>
</Route>
<Route path="/store-page" element={<WebView />} />
<Route path="/last-url" element={<WebView />} />
<Route path="loginweb">
<Route path=":runner" element={<WebView />} />
</Route>
<Route path="settings">
<Route path=":runner">
<Route path=":appName">
<Route path=":type" element={<Settings />} />
</Route>
</Route>
</Route>
<Route path="/wine-manager" element={<WineManager />} />
<Route path="/download-manager" element={<DownloadManager />} />
<Route path="/accessibility" element={<Accessibility />} />
</Routes>
</main>
<div className="controller">
<ControllerHints />
<div className="simple-keyboard"></div>
</div>
{showOverlayControls && <WindowControls />}
{experimentalFeatures.enableHelp && <Help items={help.items} />}
</HashRouter>
<OfflineMessage />
<Sidebar />
<main className="content">
<DialogHandler />
{isSettingsModalOpen.gameInfo && (
<SettingsModal
gameInfo={isSettingsModalOpen.gameInfo}
type={isSettingsModalOpen.type}
/>
)}
<ExternalLinkDialog />
<Outlet />
</main>
<div className="controller">
<ControllerHints />
<div className="simple-keyboard"></div>
</div>
{showOverlayControls && <WindowControls />}
{experimentalFeatures.enableHelp && <Help items={help.items} />}
</div>
)
}

export default App
function makeLazyFunc(
importedFile: Promise<Record<'default', React.ComponentType>>
) {
return async () => {
const component = await importedFile
return { Component: component.default }
}
}

const router = createHashRouter([
{
path: '/',
element: <Root />,
children: [
{
index: true,
lazy: makeLazyFunc(import('./screens/Library'))
},
{
path: 'login',
lazy: makeLazyFunc(import('./screens/Login'))
},
{
path: 'store/:store',
lazy: makeLazyFunc(import('./screens/WebView'))
},
{
path: 'wiki',
lazy: makeLazyFunc(import('./screens/WebView'))
},
{
path: 'gamepage/:runner/:appName',
lazy: makeLazyFunc(import('./screens/Game/GamePage'))
},
{
path: 'store-page',
lazy: makeLazyFunc(import('./screens/WebView'))
},
{
path: 'loginweb/:runner',
lazy: makeLazyFunc(import('./screens/WebView'))
},
{
path: 'settings/:runner/:appName/:type',
lazy: makeLazyFunc(import('./screens/Settings'))
},
{
path: 'wine-manager',
lazy: makeLazyFunc(import('./screens/WineManager'))
},
{
path: 'download-manager',
lazy: makeLazyFunc(import('./screens/DownloadManager'))
},
{
path: 'accessibility',
lazy: makeLazyFunc(import('./screens/Accessibility'))
},
{
path: '*',
element: <Navigate replace to="/" />
}
]
}
])

export default function App() {
return <RouterProvider router={router} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ export default function SidebarLinks() {
}

// By default, open Epic Store
let defaultStore = '/epicstore'
let defaultStore = 'epic'
if (!epic.username && !gog.username && amazon.user_id) {
// If only logged in to Amazon Games, open Amazon Gaming
defaultStore = '/amazonstore'
defaultStore = 'amazon'
} else if (!epic.username && gog.username) {
// Otherwise, if not logged in to Epic Games, open GOG Store
defaultStore = '/gogstore'
defaultStore = 'gog'
}

// if we have a stored last-url, default to the `/last-url` route
Expand Down Expand Up @@ -124,7 +124,7 @@ export default function SidebarLinks() {
active: isActive || location.pathname.includes('gamepage')
})
}
to={'/library'}
to={'/'}
onClick={async () => handleRefresh()}
>
<>
Expand All @@ -141,7 +141,7 @@ export default function SidebarLinks() {
active: isActive || location.pathname.includes('store')
})
}
to={defaultStore}
to={`/store/${defaultStore}`}
>
<>
<div className="Sidebar__itemIcon">
Expand All @@ -159,7 +159,7 @@ export default function SidebarLinks() {
active: isActive
})
}
to="/epicstore"
to="/store/epic"
>
<span>{t('store', 'Epic Store')}</span>
</NavLink>
Expand All @@ -170,7 +170,7 @@ export default function SidebarLinks() {
active: isActive
})
}
to="/gogstore"
to="/store/gog"
>
<span>{t('gog-store', 'GOG Store')}</span>
</NavLink>
Expand All @@ -181,7 +181,7 @@ export default function SidebarLinks() {
active: isActive
})
}
to="/amazonstore"
to="/store/amazon"
>
<span>{t('prime-gaming', 'Prime Gaming')}</span>
</NavLink>
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/screens/Game/GamePage/components/DotsMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useContext, useState } from 'react'
import GameContext from '../../GameContext'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { GameSubMenu } from '../..'
import GameSubMenu from '../../GameSubMenu'
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons'
import { GameInfo } from 'common/types'
import {
Expand Down
2 changes: 0 additions & 2 deletions src/frontend/screens/Game/index.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/frontend/screens/Login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default React.memo(function NewLogin() {

async function handleLibraryClick() {
await refreshLibrary({ runInBackground: false })
navigate('/library')
navigate('/')
}

return (
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/screens/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function Settings() {
if (!fromGameCard) {
returnPath = `/gamepage/${runner}/${appName}`
if (returnPath.includes('default')) {
returnPath = '/library'
returnPath = '/'
}
}

Expand Down
23 changes: 11 additions & 12 deletions src/frontend/screens/WebView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { useNavigate, useLocation, useParams } from 'react-router'
import { ToggleSwitch, UpdateComponent } from 'frontend/components/UI'
import WebviewControls from 'frontend/components/UI/WebviewControls'
import ContextProvider from 'frontend/state/ContextProvider'
import { Runner } from 'common/types'
import './index.css'
import LoginWarning from '../Login/components/LoginWarning'
import { NileLoginData } from 'common/types/nile'
Expand All @@ -21,11 +20,7 @@ import {
DialogHeader
} from 'frontend/components/UI/Dialog'

interface Props {
store?: 'epic' | 'gog' | 'amazon'
}

const validStoredUrl = (url: string, store: 'epic' | 'gog' | 'amazon') => {
const validStoredUrl = (url: string, store: string) => {
switch (store) {
case 'epic':
return url.includes('epicgames.com')
Expand All @@ -38,7 +33,7 @@ const validStoredUrl = (url: string, store: 'epic' | 'gog' | 'amazon') => {
}
}

export default function WebView({ store }: Props) {
export default function WebView() {
const { i18n } = useTranslation()
const { pathname, search } = useLocation()
const { t } = useTranslation()
Expand All @@ -56,6 +51,11 @@ export default function WebView({ store }: Props) {
const navigate = useNavigate()
const webviewRef = useRef<Electron.WebviewTag>(null)

// `store` is set to epic/gog/amazon depending on which storefront we're
// supposed to show, `runner` is set to a runner if we're supposed to show its
// login prompt
const { store, runner } = useParams()

let lang = i18n.language
if (i18n.language === 'pt') {
lang = 'pt-BR'
Expand All @@ -73,12 +73,11 @@ export default function WebView({ store }: Props) {
'https://auth.gog.com/auth?client_id=46899977096215655&redirect_uri=https%3A%2F%2Fembed.gog.com%2Fon_login_success%3Forigin%3Dclient&response_type=code&layout=galaxy'

const trueAsStr = 'true' as unknown as boolean | undefined
const { runner } = useParams() as { runner: Runner }

const urls: { [pathname: string]: string } = {
'/epicstore': epicStore,
'/gogstore': gogStore,
'/amazonstore': amazonStore,
'/store/epic': epicStore,
'/store/gog': gogStore,
'/store/amazon': amazonStore,
'/wiki': wikiURL,
'/loginEpic': epicLoginUrl,
'/loginGOG': gogLoginUrl,
Expand All @@ -89,7 +88,7 @@ export default function WebView({ store }: Props) {
let startUrl = urls[pathname]

if (store) {
sessionStorage.setItem('last-store', `/${store}store`)
sessionStorage.setItem('last-store', store)
const lastUrl = sessionStorage.getItem(`last-url-${store}`)
if (lastUrl && validStoredUrl(lastUrl, store)) {
startUrl = lastUrl
Expand Down