diff --git a/esbuild.config.mjs b/esbuild.config.mjs
index d0a1eec87..0de6574f4 100644
--- a/esbuild.config.mjs
+++ b/esbuild.config.mjs
@@ -146,6 +146,7 @@ const esbuild = {
TITLE: env.parsed.TITLE || env.parsed.MAP_GENERAL_TITLE || '',
SENTRY_DSN: env.parsed.SENTRY_DSN || '',
SENTRY_TRACES_SAMPLE_RATE: env.parsed.SENTRY_TRACES_SAMPLE_RATE || 0.1,
+ SENTRY_DEBUG: env.parsed.SENTRY_DEBUG || false,
VERSION: version,
DEVELOPMENT: isDevelopment,
CUSTOM: hasCustom,
diff --git a/example.env b/example.env
index 60b6163a9..efa006cf7 100644
--- a/example.env
+++ b/example.env
@@ -5,4 +5,5 @@ SENTRY_AUTH_TOKEN=""
SENTRY_ORG=""
SENTRY_PROJECT=""
SENTRY_TRACES_SAMPLE_RATE=0.1
-DEV_PORT=""
\ No newline at end of file
+SENTRY_DEBUG=
+DEV_PORT=""
diff --git a/package.json b/package.json
index ac93b36e5..ee6e291e2 100644
--- a/package.json
+++ b/package.json
@@ -101,7 +101,7 @@
"react-i18next": "^11.9.0",
"react-leaflet": "3.2.2",
"react-leaflet-markercluster": "3.0.0-rc1",
- "react-router-dom": "^5.2.0",
+ "react-router-dom": "^6.2.0",
"react-virtualized-auto-sizer": "^1.0.5",
"react-window": "^1.8.6",
"require-from-string": "^2.0.2",
diff --git a/src/components/App.jsx b/src/components/App.jsx
index 11c2ea712..d21c81727 100644
--- a/src/components/App.jsx
+++ b/src/components/App.jsx
@@ -1,10 +1,12 @@
import '@assets/css/main.css'
import React, { Suspense } from 'react'
+import { BrowserRouter } from 'react-router-dom'
+
import { ApolloProvider } from '@apollo/client'
import client from '@services/apollo'
-import ReactRouter from './ReactRouter'
+import Config from './Config'
import ErrorBoundary from './ErrorBoundary'
const SetText = () => {
@@ -32,12 +34,13 @@ const SetText = () => {
export default function App() {
document.body.classList.add('dark')
-
return (
}>
-
+
+
+
diff --git a/src/components/ClearStorage.jsx b/src/components/ClearStorage.jsx
index 27f0d9789..61b592361 100644
--- a/src/components/ClearStorage.jsx
+++ b/src/components/ClearStorage.jsx
@@ -1,8 +1,8 @@
import React from 'react'
-import { Redirect } from 'react-router-dom'
+import { Navigate } from 'react-router-dom'
export default function ClearStorage() {
localStorage.clear()
sessionStorage.clear()
- return
+ return
}
diff --git a/src/components/Config.jsx b/src/components/Config.jsx
new file mode 100644
index 000000000..af3ba5ed7
--- /dev/null
+++ b/src/components/Config.jsx
@@ -0,0 +1,62 @@
+import React, { useEffect, useState, useCallback } from 'react'
+import { ThemeProvider } from '@material-ui/styles'
+import { useTranslation } from 'react-i18next'
+
+import setTheme from '@assets/mui/theme'
+import UIcons from '@services/Icons'
+import Fetch from '@services/Fetch'
+
+import ReactRouter from './ReactRouter'
+import HolidayEffects from './HolidayEffects'
+
+const rootLoading = document.getElementById('loader')
+const loadingText = document.getElementById('loading-text')
+
+export default function Config() {
+ const { t } = useTranslation()
+ const [serverSettings, setServerSettings] = useState(null)
+
+ if (rootLoading) {
+ if (serverSettings) {
+ rootLoading.style.display = 'none'
+ }
+ }
+
+ if (rootLoading) {
+ if (serverSettings) {
+ rootLoading.style.display = 'none'
+ }
+ }
+ const getServerSettings = useCallback(async () => {
+ const data = await Fetch.getSettings()
+ const Icons = data.masterfile ? new UIcons(data.config.icons, data.masterfile.questRewardTypes) : null
+ if (Icons) {
+ Icons.build(data.config.icons.styles)
+ if (data.config.icons.defaultIcons) {
+ Icons.setSelection(data.config.icons.defaultIcons)
+ }
+ }
+ setServerSettings({ ...data, Icons })
+ }, [])
+
+ useEffect(() => {
+ if (!serverSettings) {
+ if (loadingText) {
+ loadingText.innerText = t('loading_settings')
+ }
+ getServerSettings()
+ }
+ }, [])
+
+ if (!serverSettings) {
+ return
+ }
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/src/components/Container.jsx b/src/components/Container.jsx
new file mode 100644
index 000000000..bd3d3d77f
--- /dev/null
+++ b/src/components/Container.jsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import { MapContainer } from 'react-leaflet'
+import { useStore } from '@hooks/useStore'
+
+import Map from './Map'
+
+export default function Container({ serverSettings, params }) {
+ const location = useStore(state => state.location)
+ const zoom = useStore(state => state.zoom)
+
+ return (
+
+ {(serverSettings.user && serverSettings.user.perms.map) && (
+
+ )}
+
+ )
+}
diff --git a/src/components/ReactRouter.jsx b/src/components/ReactRouter.jsx
index e652df024..ae0a617b9 100644
--- a/src/components/ReactRouter.jsx
+++ b/src/components/ReactRouter.jsx
@@ -1,82 +1,36 @@
-import React, { useEffect, useState, useCallback } from 'react'
-import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
-import { useTranslation } from 'react-i18next'
-import { ThemeProvider } from '@material-ui/styles'
-
-import setTheme from '@assets/mui/theme'
-import UIcons from '@services/Icons'
-import Fetch from '@services/Fetch'
+import React from 'react'
+import { Route, Routes } from 'react-router-dom'
+import useConfig from '@hooks/useConfig'
import Auth from './layout/auth/Auth'
import Login from './layout/auth/Login'
-import RouteChangeTracker from './RouteChangeTracker'
import Errors from './Errors'
import ClearStorage from './ClearStorage'
-import HolidayEffects from './HolidayEffects'
-
-const rootLoading = document.getElementById('loader')
-const loadingText = document.getElementById('loading-text')
-
-export default function ReactRouter() {
- const { t } = useTranslation()
- const [serverSettings, setServerSettings] = useState(null)
- if (rootLoading) {
- if (serverSettings) {
- rootLoading.style.display = 'none'
- }
- }
- const getServerSettings = useCallback(async () => {
- const data = await Fetch.getSettings()
- const Icons = data.masterfile ? new UIcons(data.config.icons, data.masterfile.questRewardTypes) : null
- if (Icons) {
- Icons.build(data.config.icons.styles)
- if (data.config.icons.defaultIcons) {
- Icons.setSelection(data.config.icons.defaultIcons)
- }
- }
- setServerSettings({ ...data, Icons })
- }, [])
+export default function ReactRouter({ serverSettings, getServerSettings }) {
+ useConfig(serverSettings)
- useEffect(() => {
- if (!serverSettings) {
- if (loadingText) {
- loadingText.innerText = t('loading_settings')
- }
- getServerSettings()
- }
- }, [])
+ const authRoute =
return (
-
-
- {(inject.GOOGLE_ANALYTICS_ID) && }
-
-
-
-
-
- {serverSettings && }
-
-
- {serverSettings && (
-
- )}
-
-
- {serverSettings && }
-
-
- {serverSettings && }
-
-
-
-
-
-
+
+
+ } />
+
+ )}
+ />
+
+
+
+
+ } />
+
)
}
diff --git a/src/components/RouteChangeTracker.jsx b/src/components/RouteChangeTracker.jsx
deleted file mode 100644
index 8bd40378c..000000000
--- a/src/components/RouteChangeTracker.jsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react'
-import { withRouter } from 'react-router-dom'
-import ReactGA from 'react-ga'
-
-const RouteChangeTracker = ({ history }) => {
- history.listen((location) => {
- ReactGA.set({ page: location.pathname })
- ReactGA.pageview(location.pathname)
- })
-
- return
-}
-
-export default withRouter(RouteChangeTracker)
diff --git a/src/components/WebhookQuery.jsx b/src/components/WebhookQuery.jsx
index 4cedfda2d..7ccb56d17 100644
--- a/src/components/WebhookQuery.jsx
+++ b/src/components/WebhookQuery.jsx
@@ -2,10 +2,10 @@ import React from 'react'
import { useQuery } from '@apollo/client'
import Query from '@services/Query'
-import ConfigSettings from './ConfigSettings'
+import ConfigSettings from './Container'
-export default function WebhookQuery({ match, serverSettings }) {
- let lowercase = match.params.category.toLowerCase()
+export default function WebhookQuery({ params, serverSettings }) {
+ let lowercase = params.category.toLowerCase()
if (lowercase === 'invasions'
|| lowercase === 'lures'
|| lowercase === 'quests') {
@@ -16,8 +16,8 @@ export default function WebhookQuery({ match, serverSettings }) {
}
const { data } = useQuery(Query[lowercase]('id'), {
variables: {
- id: match.params.id,
- perm: match.params.category.toLowerCase(),
+ id: params.id,
+ perm: params.category.toLowerCase(),
version: inject.VERSION,
},
})
@@ -26,8 +26,8 @@ export default function WebhookQuery({ match, serverSettings }) {
paramLocation={data[`${lowercase}Single`]
? [data[`${lowercase}Single`].lat, data[`${lowercase}Single`].lon]
: null}
- paramZoom={match.params.zoom}
- match={match}
+ paramZoom={params.zoom}
+ params={params}
serverSettings={serverSettings}
/>
) : null
diff --git a/src/components/layout/FloatingBtn.jsx b/src/components/layout/FloatingBtn.jsx
index 58a15e8a5..25362001c 100644
--- a/src/components/layout/FloatingBtn.jsx
+++ b/src/components/layout/FloatingBtn.jsx
@@ -26,6 +26,7 @@ export default function FloatingButtons({
scanZoneMode, setScanZoneMode,
}) {
const { t } = useTranslation()
+
const { map: { enableFloatingProfileButton },
scanner: { scannerType, enableScanNext, enableScanZone } } = useStatic(state => state.config)
const { loggedIn } = useStatic(state => state.auth)
@@ -78,7 +79,13 @@ export default function FloatingButtons({
) : null}
{(perms?.webhooks?.length && webhooks && selectedWebhook) ? (
- setWebhookMode('open')} title={selectedWebhook} disabled={Boolean(webhookMode) || Boolean(scanNextMode) || Boolean(scanZoneMode)}>
+ setWebhookMode('open')}
+ title={selectedWebhook}
+ disabled={Boolean(webhookMode) || Boolean(scanNextMode) || Boolean(scanZoneMode)}
+ >
diff --git a/src/components/layout/Nav.jsx b/src/components/layout/Nav.jsx
index 6e27b1f1e..9b63754c1 100644
--- a/src/components/layout/Nav.jsx
+++ b/src/components/layout/Nav.jsx
@@ -28,7 +28,6 @@ export default function Nav({
isMobile, isTablet,
}) {
const classes = useStyles()
-
const { perms } = useStatic(state => state.auth)
const webhookAlert = useStatic(state => state.webhookAlert)
const setWebhookAlert = useStatic(state => state.setWebhookAlert)
@@ -38,6 +37,7 @@ export default function Nav({
const feedback = useStatic(state => state.feedback)
const setFeedback = useStatic(state => state.setFeedback)
const resetFilters = useStatic(state => state.resetFilters)
+ const setResetFilters = useStatic(state => state.setResetFilters)
const filters = useStore(state => state.filters)
const setFilters = useStore(state => state.setFilters)
@@ -84,7 +84,6 @@ export default function Nav({
return
}
setDialog({ open, category, type })
-
if (filter && type === 'search') {
setManualParams({ id: filter.id })
map.flyTo([filter.lat, filter.lon], 16)
@@ -132,6 +131,7 @@ export default function Nav({
open={userProfile}
fullScreen={isMobile}
fullWidth={!isMobile}
+ onClose={() => setUserProfile(false)}
>
setTutorial(false)}
>
diff --git a/src/components/layout/auth/Auth.jsx b/src/components/layout/auth/Auth.jsx
index b1db329a6..b5317388c 100644
--- a/src/components/layout/auth/Auth.jsx
+++ b/src/components/layout/auth/Auth.jsx
@@ -1,21 +1,23 @@
import React from 'react'
-import { Redirect, withRouter } from 'react-router-dom'
+import { Navigate, useParams } from 'react-router-dom'
-import ConfigSettings from '../../ConfigSettings'
+import ConfigSettings from '../../Container'
import Login from './Login'
import WebhookQuery from '../../WebhookQuery'
-const Auth = ({ serverSettings, getServerSettings, match }) => {
+export default function Auth({ serverSettings, getServerSettings }) {
+ const params = useParams()
+
if (serverSettings.error) {
return (
-
+
)
}
if ((serverSettings.authMethods.length && !serverSettings.user)
|| (serverSettings.user && !serverSettings.user?.perms?.map)) {
- if (match.params.category || match.params.lat) {
- localStorage.setItem('params', JSON.stringify(match.params))
+ if (params.category || params.lat) {
+ localStorage.setItem('params', JSON.stringify(params))
}
return
}
@@ -25,19 +27,17 @@ const Auth = ({ serverSettings, getServerSettings, match }) => {
const url = cachedParams.category
? `/id/${cachedParams.category}/${cachedParams.id}/${cachedParams.zoom || 18}`
: `/@/${cachedParams.lat}/${cachedParams.lon}/${cachedParams.zoom || 18}`
- return
+ return
}
- if (match.params.category) {
+ if (params.category) {
return (
)
}
return (
-
+
)
}
-
-export default withRouter(Auth)
diff --git a/src/components/layout/auth/Local.jsx b/src/components/layout/auth/Local.jsx
index 9f3ff49a6..999f1b665 100644
--- a/src/components/layout/auth/Local.jsx
+++ b/src/components/layout/auth/Local.jsx
@@ -1,5 +1,5 @@
import React, { useState } from 'react'
-import { Redirect } from 'react-router-dom'
+import { Navigate } from 'react-router-dom'
import {
Grid, Typography, Button, OutlinedInput, InputLabel, FormControl, InputAdornment, IconButton,
} from '@material-ui/core'
@@ -47,7 +47,7 @@ export default function LocalLogin({ href, serverSettings, getServerSettings })
}
if (redirect) {
- return
+ return
}
return (
diff --git a/src/components/layout/auth/Login.jsx b/src/components/layout/auth/Login.jsx
index bd14f17f0..d5f9cedcc 100644
--- a/src/components/layout/auth/Login.jsx
+++ b/src/components/layout/auth/Login.jsx
@@ -1,6 +1,6 @@
/* eslint-disable react/no-array-index-key */
import React from 'react'
-import { withRouter } from 'react-router-dom'
+import { useLocation } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { Grid, Typography, useMediaQuery } from '@material-ui/core'
import { useTheme } from '@material-ui/styles'
@@ -11,12 +11,13 @@ import DiscordLogin from './Discord'
import TelegramLogin from './Telegram'
import CustomTile from '../custom/CustomTile'
-const Login = ({ clickedTwice, location, serverSettings, getServerSettings }) => {
+export default function Login({ clickedTwice, serverSettings, getServerSettings }) {
+ const location = useLocation()
const { t } = useTranslation()
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.only('xs'))
-
const { settings, components } = serverSettings.config.map.loginPage
+
return components.length ? (
)
}
-
-export default withRouter(Login)
diff --git a/src/components/layout/dialogs/ResetFilters.jsx b/src/components/layout/dialogs/ResetFilters.jsx
index 3535236f1..e51207bd0 100644
--- a/src/components/layout/dialogs/ResetFilters.jsx
+++ b/src/components/layout/dialogs/ResetFilters.jsx
@@ -2,7 +2,7 @@ import React, { useState } from 'react'
import {
Button, Typography, DialogContent,
} from '@material-ui/core'
-import { Redirect } from 'react-router-dom'
+import { Navigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useStatic } from '@hooks/useStore'
@@ -16,7 +16,7 @@ export default function ResetFilters() {
const setResetFilters = useStatic(state => state.setResetFilters)
if (redirect) {
- return
+ return
}
return (
<>
diff --git a/src/components/layout/dialogs/UserProfile.jsx b/src/components/layout/dialogs/UserProfile.jsx
index 0fd6fd214..b6cda806b 100644
--- a/src/components/layout/dialogs/UserProfile.jsx
+++ b/src/components/layout/dialogs/UserProfile.jsx
@@ -338,7 +338,7 @@ const BadgeTile = ({ data, rowIndex, columnIndex, style }) => {
{item.name || t('unknown_gym')}
-