diff --git a/esbuild.config.mjs b/esbuild.config.mjs
index 0de6574f4..69aa15f8a 100644
--- a/esbuild.config.mjs
+++ b/esbuild.config.mjs
@@ -124,12 +124,7 @@ const esbuild = {
metafile: true,
minify: isRelease || !isDevelopment,
logLevel: isDevelopment ? 'info' : 'error',
- target: [
- 'safari11',
- 'chrome64',
- 'firefox58',
- 'edge88',
- ],
+ target: ['safari11.1', 'chrome64', 'firefox66', 'edge88'],
watch: isDevelopment
? {
onRebuild(error) {
diff --git a/package.json b/package.json
index 19fdbc308..1d86322dc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "reactmap",
- "version": "1.2.3",
+ "version": "1.2.4",
"description": "React based frontend map.",
"main": "ReactMap.mjs",
"author": "TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>",
@@ -106,6 +106,6 @@
"react-window": "^1.8.6",
"require-from-string": "^2.0.2",
"suncalc": "^1.8.0",
- "zustand": "^3.3.3"
+ "zustand": "^4.0.0-rc.1"
}
}
diff --git a/server/src/graphql/mapTypes.js b/server/src/graphql/mapTypes.js
index 8a84f4b76..c60ba1f94 100644
--- a/server/src/graphql/mapTypes.js
+++ b/server/src/graphql/mapTypes.js
@@ -1,7 +1,15 @@
const { gql } = require('apollo-server-express')
module.exports = gql`
-
+ type Available {
+ masterfile: JSON
+ pokestops: [String]
+ gyms: [String]
+ pokemon: [String]
+ nests: [String]
+ filters: JSON
+ }
+
type Badge {
id: String
name: String
diff --git a/server/src/graphql/resolvers.js b/server/src/graphql/resolvers.js
index b31d053f2..3ba5b0ad7 100644
--- a/server/src/graphql/resolvers.js
+++ b/server/src/graphql/resolvers.js
@@ -3,7 +3,6 @@ const GraphQLJSON = require('graphql-type-json')
const { AuthenticationError, UserInputError } = require('apollo-server-core')
const config = require('../services/config')
-const { Event } = require('../services/initialization')
const { User, Badge } = require('../models/index')
const Utility = require('../services/Utility')
const Fetch = require('../services/Fetch')
@@ -11,6 +10,21 @@ const Fetch = require('../services/Fetch')
module.exports = {
JSON: GraphQLJSON,
Query: {
+ available: (_, args, { Event, perms, version }) => {
+ if (args.version && args.version !== version) throw new UserInputError('old_client')
+ if (!perms) throw new AuthenticationError('session_expired')
+ const available = {
+ pokemon: perms.pokemon ? Event.available.pokemon : [],
+ gyms: perms.gyms ? Event.available.gyms : [],
+ nests: perms.nests ? Event.available.nests : [],
+ pokestops: perms.pokestops ? Event.available.pokestops : [],
+ }
+ return {
+ ...available,
+ masterfile: { ...Event.masterfile, invasions: Event.invasions },
+ filters: Utility.buildDefaultFilters(perms, available),
+ }
+ },
badges: async (_, args, { req, perms, Db, version }) => {
if (args.version && args.version !== version) throw new UserInputError('old_client')
if (!perms) throw new AuthenticationError('session_expired')
diff --git a/server/src/graphql/typeDefs.js b/server/src/graphql/typeDefs.js
index fb83f2862..49b1966be 100644
--- a/server/src/graphql/typeDefs.js
+++ b/server/src/graphql/typeDefs.js
@@ -11,6 +11,7 @@ module.exports = gql`
scalar JSON
type Query {
+ available(version: String): Available
badges(version: String): [Badge]
devices(version: String): [Device]
geocoder(search: String, name: String, version: String): [Geocoder]
diff --git a/server/src/routes/rootRouter.js b/server/src/routes/rootRouter.js
index 942500fcc..ac4e2a07a 100644
--- a/server/src/routes/rootRouter.js
+++ b/server/src/routes/rootRouter.js
@@ -97,6 +97,7 @@ rootRouter.get('/settings', async (req, res) => {
user: await getUser(),
settings: {},
authMethods: config.authMethods,
+ masterfile: { ...Event.masterfile, invasions: Event.invasions },
config: {
map: {
...config.map,
@@ -199,8 +200,6 @@ rootRouter.get('/settings', async (req, res) => {
serverSettings.userSettings = clientValues
serverSettings.clientMenus = clientMenus
- serverSettings.masterfile = { ...Event.masterfile, invasions: Event.invasions }
-
if (config.webhooks.length && serverSettings.user?.perms?.webhooks?.length) {
serverSettings.webhooks = {}
const filtered = config.webhooks.filter(webhook => serverSettings.user.perms.webhooks.includes(webhook.name))
diff --git a/src/components/Map.jsx b/src/components/Map.jsx
index cfc4255b8..5379a2a29 100644
--- a/src/components/Map.jsx
+++ b/src/components/Map.jsx
@@ -6,6 +6,9 @@ import L from 'leaflet'
import Utility from '@services/Utility'
import { useStatic, useStore } from '@hooks/useStore'
+import useRefresh from '@hooks/useRefresh'
+import useGenerate from '@hooks/useGenerate'
+
import Nav from './layout/Nav'
import QueryData from './QueryData'
import Webhook from './layout/dialogs/webhooks/Webhook'
@@ -67,13 +70,14 @@ export default function Map({ serverSettings:
const [error, setError] = useState('')
const [windowState, setWindowState] = useState(true)
const [active, setActive] = useState(true)
-
const [lc] = useState(L.control.locate({
position: 'bottomright',
icon: 'fas fa-location-arrow',
keepCurrentZoomLevel: true,
setView: 'untilPan',
}))
+ const startFetching = useRefresh(active)
+ useGenerate()
const onMove = useCallback((latLon) => {
const newCenter = latLon || map.getCenter()
@@ -110,6 +114,12 @@ export default function Map({ serverSettings:
}
}, [settings.navigationControls])
+ useEffect(() => {
+ if (active) {
+ startFetching()
+ }
+ }, [active])
+
return (
<>
+
)
}
diff --git a/src/components/layout/dialogs/filters/MenuTile.jsx b/src/components/layout/dialogs/filters/MenuTile.jsx
index 907a07cc8..73e8426f2 100644
--- a/src/components/layout/dialogs/filters/MenuTile.jsx
+++ b/src/components/layout/dialogs/filters/MenuTile.jsx
@@ -9,7 +9,8 @@ export default function MenuTile({
}) {
const [name, setName] = useState(true)
const {
- tileItem, columnCount, tempFilters, setTempFilters, toggleAdvMenu, isMobile, type, toggleSlotsMenu, Utility,
+ tileItem, columnCount, tempFilters, setTempFilters, toggleAdvMenu,
+ isMobile, type, toggleSlotsMenu, Utility, standard,
} = data
const item = tileItem[rowIndex * columnCount + columnIndex]
@@ -19,12 +20,12 @@ export default function MenuTile({
}
const handleFilterChange = () => {
+ const newFilter = tempFilters[item.id]
+ ? { ...tempFilters[item.id], enabled: !tempFilters[item.id].enabled }
+ : { ...standard, enabled: true }
setTempFilters({
...tempFilters,
- [item.id]: {
- ...tempFilters[item.id],
- enabled: !tempFilters[item.id].enabled,
- },
+ [item.id]: newFilter,
})
Utility.analytics('Filtering', `${item.name} Status: ${!tempFilters[item.id]?.enabled}`, type)
}
diff --git a/src/components/layout/general/Menu.jsx b/src/components/layout/general/Menu.jsx
index ae9ee8dd4..c926cfd87 100644
--- a/src/components/layout/general/Menu.jsx
+++ b/src/components/layout/general/Menu.jsx
@@ -86,7 +86,7 @@ export default function Menu({
setAdvancedFilter({
open,
id,
- tempFilters: tempFilters[id],
+ tempFilters: tempFilters[id] ?? filters.standard,
standard: filters.standard,
})
} else if (id === 'global') {
@@ -233,6 +233,7 @@ export default function Menu({
Utility,
toggleWebhook,
webhookCategory,
+ standard: filters.standard,
}}
Tile={Tile}
/>
diff --git a/src/hooks/useConfig.js b/src/hooks/useConfig.js
index 0c33983e5..540f8555d 100644
--- a/src/hooks/useConfig.js
+++ b/src/hooks/useConfig.js
@@ -5,8 +5,6 @@ import * as Sentry from '@sentry/react'
import Utility from '@services/Utility'
import { useStore, useStatic } from '@hooks/useStore'
-import useGenerate from '@hooks/useGenerate'
-
export default function useConfig(serverSettings, paramLocation) {
Utility.analytics('User', serverSettings.user ? `${serverSettings.user.username} (${serverSettings.user.id})` : 'Not Logged In', 'Permissions', true)
@@ -34,7 +32,6 @@ export default function useConfig(serverSettings, paramLocation) {
const setUi = useStatic(state => state.setUi)
const setStaticFilters = useStatic(state => state.setFilters)
const setWebhookData = useStatic(state => state.setWebhookData)
- const setMenuFilters = useStatic(state => state.setMenuFilters)
const setIsNight = useStatic(state => state.setIsNight)
const localState = JSON.parse(localStorage.getItem('local-state'))
@@ -121,7 +118,6 @@ export default function useConfig(serverSettings, paramLocation) {
}
setIcons(serverSettings.Icons.selection)
setStaticIcons(serverSettings.Icons)
- setMenuFilters(useGenerate())
setConfig(serverSettings.config)
setWebhookData(serverSettings.webhooks)
diff --git a/src/hooks/useGenerate.js b/src/hooks/useGenerate.js
index 07b9ccd77..8904945a7 100644
--- a/src/hooks/useGenerate.js
+++ b/src/hooks/useGenerate.js
@@ -1,4 +1,4 @@
-import { useMemo, useCallback } from 'react'
+import { useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import genPokemon from '@services/filtering/genPokemon'
@@ -12,14 +12,13 @@ export default function useGenerate() {
const { pokemon } = useStatic(useCallback(s => s.masterfile, []))
const { gyms, pokestops } = useStatic(useCallback(s => s.filters, []))
const staticMenus = useStatic(useCallback(s => s.menus, []))
+ const setMenuFilters = useStatic(s => s.setMenuFilters)
- const pokeFilters = useMemo(() => genPokemon(t, pokemon, staticMenus.pokemon.categories), [localStorage.getItem('i18nextLng')])
- const gymFilters = useMemo(() => genGyms(t, gyms, staticMenus.gyms.categories), [localStorage.getItem('i18nextLng')])
- const stopFilters = useMemo(() => genPokestops(t, pokemon, pokestops, staticMenus.pokestops.categories), [localStorage.getItem('i18nextLng')])
+ useEffect(() => {
+ const pokeFilters = genPokemon(t, pokemon, staticMenus.pokemon.categories)
+ const gymFilters = genGyms(t, gyms, staticMenus.gyms.categories)
+ const stopFilters = genPokestops(t, pokemon, pokestops, staticMenus.pokestops.categories)
- return {
- ...gymFilters,
- ...stopFilters,
- ...pokeFilters,
- }
+ setMenuFilters({ ...gymFilters, ...stopFilters, ...pokeFilters })
+ }, [localStorage.getItem('i18nextLng'), pokemon])
}
diff --git a/src/hooks/useRefresh.js b/src/hooks/useRefresh.js
new file mode 100644
index 000000000..6858762a8
--- /dev/null
+++ b/src/hooks/useRefresh.js
@@ -0,0 +1,29 @@
+import { useLazyQuery } from '@apollo/client'
+import getAvailable from '@services/queries/available'
+import { useEffect } from 'react'
+
+import { useStatic } from './useStore'
+
+export default function useRefresh(active) {
+ const setAvailable = useStatic(s => s.setAvailable)
+ const setMasterfile = useStatic(s => s.setMasterfile)
+ const setStaticFilters = useStatic(s => s.setFilters)
+
+ const [startFetching, { data }] = useLazyQuery(getAvailable, {
+ variables: { version: inject.VERSION },
+ fetchPolicy: active ? 'network-only' : 'cache-only',
+ pollInterval: 1000 * 60 * 10,
+ skip: !active,
+ })
+
+ useEffect(() => {
+ if (data?.available) {
+ const { masterfile, filters, ...rest } = data.available
+ setAvailable(rest)
+ setMasterfile(masterfile)
+ setStaticFilters(filters)
+ }
+ }, [data])
+
+ return startFetching
+}
diff --git a/src/services/queries/available.js b/src/services/queries/available.js
new file mode 100644
index 000000000..a2f07ab43
--- /dev/null
+++ b/src/services/queries/available.js
@@ -0,0 +1,16 @@
+import { gql } from '@apollo/client'
+
+const getAvailable = gql`
+ query Available($version: String) {
+ available(version: $version) {
+ masterfile
+ pokestops
+ gyms
+ pokemon
+ nests
+ filters
+ }
+ }
+`
+
+export default getAvailable
diff --git a/yarn.lock b/yarn.lock
index ef86b951a..71128da84 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4688,6 +4688,11 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"
+use-sync-external-store@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz#3343c3fe7f7e404db70f8c687adf5c1652d34e82"
+ integrity sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==
+
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -4898,7 +4903,9 @@ zen-observable@^0.8.14:
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
-zustand@^3.3.3:
- version "3.5.5"
- resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.5.5.tgz#628458ad70621ddc2a17dbee49be963e5c0dccb5"
- integrity sha512-iTiJoxzYFtiD7DhscgwK2P4Kft1JcZEI2U7mG8IxiOFM4KpBAiJZfFop3r/3wbCuyltXI6ph1Fx90e4j/S43XA==
+zustand@^4.0.0-rc.1:
+ version "4.0.0-rc.1"
+ resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.0.0-rc.1.tgz#ec30a3afc03728adec7e1bd7bcc3592176372201"
+ integrity sha512-qgcs7zLqBdHu0PuT3GW4WCIY5SgXdsv30GQMu9Qpp1BA2aS+sNS8l4x0hWuyEhjXkN+701aGWawhKDv6oWJAcw==
+ dependencies:
+ use-sync-external-store "1.1.0"