Repository navigation
Conversation
Golbat shipped the available quest field as temp_evolution_id and advertises it on /api/status as filters.quest_temp_evolution_id (UnownHash/Golbat#432). Read the new name and gate temp evo branch mega energy keys on the status flag instead of the field's presence. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# [1.56.0](WatWowMap/ReactMap@v1.55.2...v1.56.0) (2026-10-31) ### Bug Fixes * **pokestop:** key mega energy by temp evolution ([6827243](WatWowMap@6827243)), closes [UnownHash/Golbat#432](UnownHash/Golbat#432) * **pokestop:** read Golbat quest temp evolution id ([8dfbcf6](WatWowMap@8dfbcf6)), closes [UnownHash/Golbat#432](UnownHash/Golbat#432) ### Features * **tappable:** support candy rewards ([9b78da7](WatWowMap@9b78da7)), closes [UnownHash/Golbat#428](UnownHash/Golbat#428) [WatWowMap#1272](WatWowMap#1272)
VirtuosoGrid hides every tile while it restores a snapshot's scrollTop and only finishes once the scroller has reported its position twice, but the restore's own scroll request goes out before the scroller listens for it. In production builds the second report never comes, so a grid that had been scrolled reopened blank every other time; StrictMode's double-run mount effect hid this in dev. Pass the snapshot with scrollTop zeroed instead: the grid still gets its measured sizes on the first render, which makes it tall enough for useDrawerScrollMemory to restore the scroll offset. Closes WatWowMap#1275 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
## [1.56.1](WatWowMap/ReactMap@v1.56.0...v1.56.1) (2026-10-31) ### Bug Fixes * **drawer:** stop scrolled selector grids from reopening blank ([3c493b6](WatWowMap@3c493b6)), closes [WatWowMap#1275](WatWowMap#1275)
Fixes WatWowMap#1270 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
## [1.56.2](WatWowMap/ReactMap@v1.56.1...v1.56.2) (2026-10-31) ### Bug Fixes * **map:** cancel stale idle timer on repeated blur ([959d74b](WatWowMap@959d74b)), closes [WatWowMap#1270](WatWowMap#1270)
…nce (WatWowMap#1278) * fix(holiday): use standard Wikimedia thumbnail size and load images once Wikimedia only serves thumbnails at its standard widths, so the 640px pumpkin and ghost URLs returned 400. Switch them to 120px; the sprites render at about 30px. The animation also created a new Image for every sprite on every frame (about 1000 requests/sec), so a failing URL was requested again on every frame. Load each image once and skip ones that haven't loaded or failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjBJekNgjZKdL2oSVY4PUe * fix(holiday): rely on the naturalWidth check for failed images Chrome marks a failed image complete before its onerror runs, and drawImage throws on it, so the naturalWidth check is what keeps draw() safe. Deleting the map entry in onerror was redundant; drop it and the !image check it required. Also correct the comment: same-URL loads are merged, so the old code re-requested each failed URL once per frame, not once per sprite. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Mygod <contact-git@mygod.be>
## [1.56.3](WatWowMap/ReactMap@v1.56.2...v1.56.3) (2026-11-01) ### Bug Fixes * **holiday:** use standard Wikimedia thumbnail size and load images once ([WatWowMap#1278](WatWowMap#1278)) ([5202ee2](WatWowMap@5202ee2))
engines.node allowed any release from 22.23.4 up, which still includes the unpatched 23.x, 24.x before 24.22.1, 25.x and 26.x before 26.12.1. CVE-2026-111497 is only fixed in 22.23.4, 24.22.1 and 26.12.1, and request body inflation has relied on a patched runtime since 410570c. Accept only the patched release of each line. Yarn refuses to install or run any script on an exposed runtime, so `yarn start` stops there until Node is upgraded. 23.x and 25.x are end of life with no fix and fall outside the range on purpose. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
useManualPopupTracker writes manualParams whenever a popup opens, and useForcePopup's cleanup writes it again when one closes. Every pokemon marker subscribed to the whole manualParams object twice (PokemonTile's isPopupOpen and useForcePopup, which every tile type uses), and so did every QueryData and Clustering instance. Each popup click therefore re-rendered every marker of every layer, and since the marker icons are rebuilt on render, replaced every marker's DOM too. Each subscriber now selects only what it compares: - useForcePopup: whether this marker is the manual target (boolean) - PokemonTile: whether its own popup is open (boolean) - QueryData: this category's manual id, or undefined - Clustering: this category's manual key, or null Opening a popup still refetches its own layer, as before, because that layer's manual id still changes. One behaviour difference: useForcePopup used to rerun when manualParams was rewritten with the same id; it now reruns when the marker becomes or stops being the target. Closing the popup clears manualParams, so selecting the same pokemon again from search still reopens it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PokemonTile built a new Leaflet icon (an Icon, or a divIcon with the glow, background, badge and weather markup) on every render. react-leaflet's Marker calls setIcon whenever the icon prop is a new object, and setIcon removes the marker's element and creates a new one, so any re-render of a tile (a store change its selectors return a new value for, the opacity step, a popup) rebuilt that marker's DOM even when nothing it draws had changed. The icon is now memoized on its inputs: whether it is the fancy variant, the pkmn fields fancyPokemonMarker reads (id, background, pokemon_id, seen_type, weather), the icon URL and size, glow, weather, badge, opacity, time of day and background URL. fancyPokemonMarker also reads the weather, grass and modifier assets straight from Icons, which setSelection changes in place when the viewer picks another set, so the stored icon selection (useStorage icons, a new object on every pick) keys the icon too. The markup is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Each pan or zoom ran a full pass over every pokemon marker, twice for a zoom: - Container listened to both zoomend and moveend. Leaflet only fires zoomend from _moveEnd, immediately followed by moveend, so a zoom saved location/zoom to the persisted store twice (re-serializing every filter into localStorage each time) and fired fetchdata twice. moveend alone now covers both. - setLocationZoom wrote timeOfDay to useMemory on every pan, even when it hadn't changed, and zustand notifies every subscriber on any setState. It now writes only when the value changes. - That mattered because PokemonTile's useMemory selector resolved five asset URLs (pokemon icon, size, badge, background and cry, each a nested suffix search in uicons) for every marker on every useMemory write. The selector now returns only cheap values (timer flag, the interaction-range zoom, time of day, and the Icons and Audio instances), and the lookups are memoized on their inputs. The interaction-range check read the map's zoom inside that selector, so it only followed a zoom because of the timeOfDay write. It now compares the stored zoom in a useStorage selector, as GymTile and TappableTile do, so a tile only re-renders when a zoom crosses interactionRangeZoom. Icons and Audio are mutated in place by setSelection when the viewer picks another icon or audio set, so their identity alone can't key the cache. The stored selection (useStorage icons/audio) is replaced on every change, so the memos key on that as well. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
QueryData filtered its results against the hide list and created a fresh element for every marker on every render, and it re-renders on any write to its category's filters or settings, the hide list or the active flag. Clustering's effect depends on its children, so above the category's forcedLimit (3000 pokemon by default), each of those renders reloaded Supercluster with every point, cleared and re-added the cluster layer, and set a new marker set, forcing a second render that reconciled every child again. The filtered list and the marker elements are now memoized on the query result and the hide list, so Clustering only re-clusters when the data does. The empty-result fallback is a module constant, so it doesn't defeat the memo while nothing has loaded or after an error. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A reverse lookup at coordinates without an address (open water, a field) returns no results, and geocoder() formatted the missing first result anyway. The TypeError was caught and logged as a failed lookup, so every such gym logged a warning with a stack trace for a normal answer. It now returns the empty address straight away. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Perm, trial, area restriction, webhook and scanner roles lists only matched a member's Discord role ids, so a user id listed there was silently ignored, and giving one person a perm took a role of their own. getPerms now adds the user's own id to the roles it fetched for each allowed guild. Snowflakes are unique across users and roles, so the id can never match a real role. The user still has to be in an allowed guild, same as with roles. Telegram is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A gym, pokestop or station search ran against every source of the model, including a Golbat endpoint source with no database behind it. Only Pokemon.search has an endpoint branch; the fort search methods call this.query() on an unbound model, so the endpoint source rejected every time and runScannerSources logged it. A deployment that lists a pure Golbat endpoint next to its database for gyms and pokestops therefore logged a "no database connection available" warning for every widening step of every search, which buried real errors while the database source still answered. search now passes runScannerSources only the sources it can query: every source for Pokemon, and the ones with a database connection for every other model. runScannerSources takes the source list so its rejection log still names the right source. A fort model with only endpoint sources still gets no results, now without a warning, and a failing database source is still logged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The testing guidelines still said there was no dedicated test suite, but `yarn test` runs the masterfile tests and the server suite under node's test runner. Say how to run it, and one file of it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# [1.57.0](WatWowMap/ReactMap@v1.56.3...v1.57.0) (2026-11-01) ### Bug Fixes * **geocoder:** answer empty when a reverse lookup finds no address ([677ac81](WatWowMap@677ac81)) * **search:** skip sources a fort search cannot query ([f56b021](WatWowMap@f56b021)) ### Features * **discord:** accept user ids in roles lists ([b2fa07f](WatWowMap@b2fa07f)) ### Performance Improvements * **map:** make a pan cheap for every marker on the map ([5a9536f](WatWowMap@5a9536f)) * **map:** rebuild a layer's markers only when its data changes ([4e9c564](WatWowMap@4e9c564)) * **map:** stop re-rendering every marker when a popup opens ([d4fc29e](WatWowMap@d4fc29e)) * **pokemon:** build a marker's icon only when what it draws changes ([5dac9d3](WatWowMap@5dac9d3))
…#1261) * fix(auth): link Discord and Telegram for users signed in with either The profile offers "Link Discord" / "Link Telegram" to every signed-in user, but the server only linked when the signed-in row was a local account. Discord and Telegram users got a button that did nothing, and worse: - Telegram checked the row found by the Telegram id instead of the signed-in user, so linking Telegram never worked, not even for local accounts. - Linking Discord while signed in with Telegram rewrote the Telegram row's strategy to "discord" without storing a Discord id. Both clients now share linkAccount(): when a signed-in user authenticates with a platform their row has no id for, the id is attached to their row. A row that only existed for that account is merged in (gym badges keeping the higher badge, backups, nest submissions, profile data) and deleted, in one transaction, and its sessions are cleared. A local account, or one already linked to a different account of the other platform, is never merged away; the user lands on the blocked page with an explanation instead. Signing in with an account the row already has stays a plain login. Webhooks keep following the sign-in method: a Discord sign-in alerts the Discord account and a Telegram sign-in the Telegram one, so the webhook strategy selector stays reserved for local accounts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(auth): address review on account linking - Show the webhook strategy selector to local sessions again. They carry no strategy, so gating on strategy === 'local' hid it for everyone; gate on "not a Discord or Telegram sign-in" instead. - Read and lock both rows (FOR UPDATE, one query) inside the transaction that merges them, so concurrent link callbacks for the same user cannot both link. - Refuse to merge away a row that already has both ids. It is a linked account of its own, and carrying its second id over would carry it without that provider's permissions. - Hand the row read for a plain login back to the Discord and Telegram clients instead of querying it again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(auth): expire linked trial perms and keep linked webhook A session that linked a second platform kept only its own rmStrategy, so the trial cleanup of the linked platform never matched it and its trial perms outlived the trial. Sessions now list every strategy they hold perms from in linkedStrategies, and clearNonDonor/clearTrial match either. Linking also overwrote the computed webhook fallback with the session's null selectedWebhook. linkAccount now stores the fallback on the row when it has none and returns it with the linked fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(auth): clear linked trial perms even when the session is a donor A linked session merges both platforms' perms, so a donor on one platform kept the other platform's trial perms after that trial ended, since clearNonDonor skips donor sessions. Linked sessions now record the strategies that granted trial perms in `trialStrategies`, and clearNonDonor also clears sessions listing the ending strategy there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(auth): only link accounts from a local sign-in Linking from a Discord or Telegram session merged both platforms' perms into one session, which trial expiry and donor checks keyed on a single strategy cannot clear correctly. Only local sign-ins link now, and the profile hides the link buttons for other sessions; a callback for them signs in to that account like any other login. This drops the linkedStrategies and trialStrategies session tracking. Linking also has to be bound to the session that started it: the legacy Telegram widget's signed callback is not, so only the Telegram OAuth flow links, and the Discord strategy now checks the OAuth state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(profile): only offer account linking to local sign-ins Linking Telegram to a Discord sign-in (or the reverse) fails, and making it work means merging two platforms' perms into one session. Hide the link buttons for Discord and Telegram sessions instead and leave the server's linking for local accounts as it is on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## [1.57.1](WatWowMap/ReactMap@v1.57.0...v1.57.1) (2026-11-02) ### Bug Fixes * **profile:** only offer account linking to local sign-ins ([WatWowMap#1261](WatWowMap#1261)) ([f01a1a2](WatWowMap@f01a1a2))
- Multi-stage Dockerfile (build -> prune -> runtime) with a BuildKit yarn cache mount, so the 2.2 GB yarn cache never lands in a layer - Add .dockerignore (keeps .git, node_modules and local configs/secrets out of the build context; configs are mounted as documented) - Pass GIT_SHA/GIT_REF as build args instead of .gitsha/.gitref files, and remove the dead placeholder files - checkForUpdates: read sha/ref from env, fetch the remote sha via the GitHub API (no git binary needed), skip non-branch refs (PR images) - Move vite + build plugins to dependencies since `yarn start` builds the client on boot; lazy-load vite-plugin-checker (dev only) - Name the Sentry release from SENTRY_RELEASE/GIT_SHA (the plugin used `git rev-parse HEAD`, which only worked because the image had .git) - Move openai/gpt-tokenizer to @rm/locales devDependencies and drop the unused `generate` re-export; keep loading .env in @rm/locales - Remove unused monaco-editor devDependency (the playground loads Monaco from jsDelivr via @monaco-editor/loader) - docker.yml: buildx, current action versions, GHA layer cache, provenance disabled to keep publishing a single manifest Image: 3 GB -> 608 MB uncompressed (~1.4 GB -> ~207 MB compressed) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Dockerfile always defines GIT_REF/GIT_SHA (empty without --build-arg), so treat their presence as Docker and never fall back to git, which the image doesn't ship. Also skip the remote lookup whenever the local sha is unknown instead of awaiting a fetch whose result can't be compared. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- checkout v7, setup-buildx v4, login v4, metadata v6, build-push v7 (none of their breaking changes affect this workflow) - BUILDX_METADATA_PROVENANCE=disabled drops the ~600 line provenance trace from the printed build metadata - DOCKER_BUILD_RECORD_UPLOAD=false stops uploading a .dockerbuild artifact on every run; the job summary is kept Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft PR in the fork, only to run the Docker job (upstream skips it for fork PRs). Do not merge, the real PR is WatWowMap#1279.
🤖 Generated with Claude Code