From 2a9cbbf180313064830a524f86eae62f41b6b87b Mon Sep 17 00:00:00 2001 From: Mygod Date: Tue, 9 Dec 2025 11:58:50 -0800 Subject: [PATCH 01/22] fix: battle/raid filtering race condition --- src/features/drawer/Stations.jsx | 25 +++++++++++++++++-------- src/features/drawer/gyms/Raids.jsx | 25 +++++++++++++++++-------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/features/drawer/Stations.jsx b/src/features/drawer/Stations.jsx index d2c99ddf2..de1c4f5eb 100644 --- a/src/features/drawer/Stations.jsx +++ b/src/features/drawer/Stations.jsx @@ -6,8 +6,8 @@ import ListItemText from '@mui/material/ListItemText' import MenuItem from '@mui/material/MenuItem' import { useTranslation } from 'react-i18next' -import { useMemory } from '@store/useMemory' import { useDeepStore, useStorage } from '@store/useStorage' +import { useGetAvailable } from '@hooks/useGetAvailable' import { FCSelect } from '@components/inputs/FCSelect' import { CollapsibleItem } from './components/CollapsibleItem' @@ -15,7 +15,7 @@ import { SelectorListMemo } from './components/SelectorList' function StationLevels() { const { t } = useTranslation() - const available = useMemory((s) => s.available.stations) + const { available } = useGetAvailable('stations') const enabled = useStorage( (s) => !!s.filters?.stations?.maxBattles && !s.filters?.stations?.allStations, @@ -24,6 +24,20 @@ function StationLevels() { 'filters.stations.battleTier', 'all', ) + + const battleTiers = React.useMemo(() => { + const availableTiers = available + .filter((x) => x.startsWith('j')) + .map((y) => +y.slice(1)) + if (filters === 'all') return availableTiers + + const storedTier = Number(filters) + if (Number.isNaN(storedTier) || availableTiers.includes(storedTier)) { + return availableTiers + } + return [storedTier, ...availableTiers] + }, [available, filters]) + return ( - {[ - 'all', - ...available - .filter((x) => x.startsWith('j')) - .map((y) => +y.slice(1)), - ].map((tier, i) => ( + {['all', ...battleTiers].map((tier, i) => ( {t(i ? `max_battle_${tier}_plural` : 'disabled')} diff --git a/src/features/drawer/gyms/Raids.jsx b/src/features/drawer/gyms/Raids.jsx index 2bc7621f7..a5b30f8de 100644 --- a/src/features/drawer/gyms/Raids.jsx +++ b/src/features/drawer/gyms/Raids.jsx @@ -5,8 +5,8 @@ import ListItemText from '@mui/material/ListItemText' import MenuItem from '@mui/material/MenuItem' import { useTranslation } from 'react-i18next' -import { useMemory } from '@store/useMemory' import { useStorage, useDeepStore } from '@store/useStorage' +import { useGetAvailable } from '@hooks/useGetAvailable' import { FCSelect } from '@components/inputs/FCSelect' import { CollapsibleItem } from '../components/CollapsibleItem' @@ -14,9 +14,23 @@ import { MultiSelectorList, SelectorListMemo } from '../components/SelectorList' const RaidOverride = () => { const { t } = useTranslation() - const available = useMemory((s) => s.available.gyms) + const { available } = useGetAvailable('gyms') const enabled = useStorage((s) => !!s.filters?.gyms?.raids) const [filters, setFilters] = useDeepStore('filters.gyms.raidTier', 'all') + + const raidTiers = React.useMemo(() => { + const availableTiers = available + .filter((x) => x.startsWith('r')) + .map((y) => +y.slice(1)) + if (filters === 'all') return availableTiers + + const storedTier = Number(filters) + if (Number.isNaN(storedTier) || availableTiers.includes(storedTier)) { + return availableTiers + } + return [storedTier, ...availableTiers] + }, [available, filters]) + return ( { setFilters(e.target.value === 'all' ? 'all' : e.target.value) } > - {[ - 'all', - ...available - .filter((x) => x.startsWith('r')) - .map((y) => +y.slice(1)), - ].map((tier, i) => ( + {['all', ...raidTiers].map((tier, i) => ( {t(i ? `raid_${tier}_plural` : 'disabled')} From cd01a92bda81f786ca2c14f10df8cc4489163fd6 Mon Sep 17 00:00:00 2001 From: Mygod Date: Tue, 9 Dec 2025 12:12:32 -0800 Subject: [PATCH 02/22] fix: ground raid/battle icons --- src/assets/css/main.css | 28 ++++++++++++++++++++++++ src/features/gym/gymMarker.js | 18 ++++++++------- src/features/station/useStationMarker.js | 20 +++++++++-------- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/assets/css/main.css b/src/assets/css/main.css index f6d4a5c95..524bb0502 100644 --- a/src/assets/css/main.css +++ b/src/assets/css/main.css @@ -249,6 +249,34 @@ body { position: absolute; } +.gym-marker__raid-icon, +.station-marker__battle-icon { + position: absolute; + display: flex; + align-items: flex-end; + justify-content: center; + transform: translateX(-50%); +} + +.gym-marker__raid-icon { + width: var(--raid-icon-size, 30px); + height: var(--raid-icon-size, 30px); +} + +.station-marker__battle-icon { + width: var(--battle-icon-size, 30px); + height: var(--battle-icon-size, 30px); +} + +.gym-marker__raid-icon img, +.station-marker__battle-icon img { + width: 100% !important; + height: auto !important; + max-width: 100% !important; + max-height: 100% !important; + object-fit: contain; +} + .invasion-reward { display: inline-block; width: 30px; diff --git a/src/features/gym/gymMarker.js b/src/features/gym/gymMarker.js index afa9f6ed6..2e2479ec2 100644 --- a/src/features/gym/gymMarker.js +++ b/src/features/gym/gymMarker.js @@ -166,20 +166,22 @@ export function gymMarker({ ${ raidIconUrl ? /* html */ - `${raidIconUrl}` + > + ${raidIconUrl} + ` : '' } ${ diff --git a/src/features/station/useStationMarker.js b/src/features/station/useStationMarker.js index 6637d6916..a09434dd5 100644 --- a/src/features/station/useStationMarker.js +++ b/src/features/station/useStationMarker.js @@ -83,18 +83,20 @@ export function useStationMarker({ ${ showBattleIcon ? /* html */ ` - ${battleIcon} + > + ${battleIcon} + ` : '' } From 3717c2ebae353af131cd204d89c814811d301c50 Mon Sep 17 00:00:00 2001 From: Mygod Date: Tue, 9 Dec 2025 12:20:14 -0800 Subject: [PATCH 03/22] chore: centralize overlay logic --- src/assets/css/main.css | 39 ++++++--------------- src/features/gym/gymMarker.js | 25 +++++--------- src/features/station/useStationMarker.js | 24 +++++-------- src/utils/renderOverlayIcon.js | 43 ++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 61 deletions(-) create mode 100644 src/utils/renderOverlayIcon.js diff --git a/src/assets/css/main.css b/src/assets/css/main.css index 524bb0502..0b24d2b70 100644 --- a/src/assets/css/main.css +++ b/src/assets/css/main.css @@ -249,31 +249,25 @@ body { position: absolute; } -.gym-marker__raid-icon, -.station-marker__battle-icon { +.marker-overlay-icon { position: absolute; display: flex; align-items: flex-end; justify-content: center; transform: translateX(-50%); + width: var(--marker-overlay-size, 30px); + height: var(--marker-overlay-size, 30px); } -.gym-marker__raid-icon { - width: var(--raid-icon-size, 30px); - height: var(--raid-icon-size, 30px); -} - -.station-marker__battle-icon { - width: var(--battle-icon-size, 30px); - height: var(--battle-icon-size, 30px); -} - -.gym-marker__raid-icon img, -.station-marker__battle-icon img { - width: 100% !important; +.marker-overlay-icon img, +.leaflet-container + .leaflet-marker-pane + .pokestop-marker__stack-item + img:not(.pokestop-marker__decoration) { + width: var(--marker-overlay-size, var(--marker-size, 30px)) !important; height: auto !important; - max-width: 100% !important; - max-height: 100% !important; + max-width: var(--marker-overlay-size, var(--marker-size, 30px)) !important; + max-height: var(--marker-overlay-size, var(--marker-size, 30px)) !important; object-fit: contain; } @@ -384,17 +378,6 @@ img { transform: translateX(-50%); } -.leaflet-container - .leaflet-marker-pane - .pokestop-marker__stack-item - img:not(.pokestop-marker__decoration) { - width: var(--marker-size, 30px) !important; - height: auto !important; - max-width: var(--marker-size, 30px) !important; - max-height: var(--marker-size, 30px) !important; - object-fit: contain; -} - .leaflet-container .leaflet-marker-pane .pokestop-marker__stack-item[data-reward-type='12'] diff --git a/src/features/gym/gymMarker.js b/src/features/gym/gymMarker.js index 2e2479ec2..3f5f7b6f4 100644 --- a/src/features/gym/gymMarker.js +++ b/src/features/gym/gymMarker.js @@ -1,6 +1,7 @@ // @ts-check import { divIcon } from 'leaflet' import { useMemory } from '@store/useMemory' +import { renderOverlayIcon } from '@utils/renderOverlayIcon' /** @param {number} raidLevel */ const getBadgeColor = (raidLevel) => { @@ -165,23 +166,13 @@ export function gymMarker({ } ${ raidIconUrl - ? /* html */ - `
- ${raidIconUrl} -
` + ? /* html */ renderOverlayIcon({ + url: raidIconUrl, + size: raidIconSize, + opacity, + bottom: gymIconSize * 0.4 + slotModifier * raidMod.offsetY, + left: raidMod.offsetX * 50, + }) : '' } ${ diff --git a/src/features/station/useStationMarker.js b/src/features/station/useStationMarker.js index a09434dd5..241c30fa6 100644 --- a/src/features/station/useStationMarker.js +++ b/src/features/station/useStationMarker.js @@ -4,6 +4,7 @@ import { divIcon } from 'leaflet' import { basicEqualFn, useMemory } from '@store/useMemory' import { useStorage } from '@store/useStorage' import { useOpacity } from '@hooks/useOpacity' +import { renderOverlayIcon } from '@utils/renderOverlayIcon' /** * @@ -82,22 +83,13 @@ export function useStationMarker({ /> ${ showBattleIcon - ? /* html */ ` -
- ${battleIcon} -
- ` + ? /* html */ renderOverlayIcon({ + url: battleIcon, + size: battleSize, + opacity: getOpacity(battle_end), + bottom: baseSize * 0.8 * battleMod.offsetY, + left: battleMod.offsetX * 50, + }) : '' } diff --git a/src/utils/renderOverlayIcon.js b/src/utils/renderOverlayIcon.js new file mode 100644 index 000000000..dcc6f8b42 --- /dev/null +++ b/src/utils/renderOverlayIcon.js @@ -0,0 +1,43 @@ +// @ts-check + +/** + * Render a standard overlay icon wrapper for Leaflet markers. + * @param {{ + * url: string, + * size: number, + * bottom: number, + * left: number, + * opacity?: number, + * className?: string, + * alt?: string, + * }} params + */ +export function renderOverlayIcon({ + url, + size, + bottom, + left, + opacity, + className, + alt = url, +}) { + const classes = ['marker-overlay-icon', className].filter(Boolean).join(' ') + const opacityStyle = typeof opacity === 'number' ? `opacity: ${opacity};` : '' + + return ` +
+ ${alt} +
+ ` +} From 21b50f51b81bf6f7723753a4f77289ead99c51e7 Mon Sep 17 00:00:00 2001 From: Mygod Date: Tue, 9 Dec 2025 16:53:44 -0800 Subject: [PATCH 04/22] fix: weather icon in pokemon background popup --- src/features/pokemon/PokemonPopup.jsx | 40 ++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/features/pokemon/PokemonPopup.jsx b/src/features/pokemon/PokemonPopup.jsx index da91124f6..f88937713 100644 --- a/src/features/pokemon/PokemonPopup.jsx +++ b/src/features/pokemon/PokemonPopup.jsx @@ -286,6 +286,7 @@ export function PokemonPopup({ pokemon, iconUrl, isTutorial = false }) { metaData={metaData} perms={pokePerms} timeOfDay={timeOfDay} + backgroundVisuals={backgroundVisuals} />