Skip to content

ERA-13076: Remove approach to loading icons via one enormous sprite#1529

Open
jeslefcourt wants to merge 11 commits into
developfrom
ERA-13076-remove-sprite-approach-to-loading-icons
Open

ERA-13076: Remove approach to loading icons via one enormous sprite#1529
jeslefcourt wants to merge 11 commits into
developfrom
ERA-13076-remove-sprite-approach-to-loading-icons

Conversation

@jeslefcourt

@jeslefcourt jeslefcourt commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes the single large SVG sprite as the icon-loading mechanism (drops the preloaded ReportTypeIconSprite from App.js and the sprite-lookup logic from DasIcon)
  • DasIcon now fetches each icon's SVG from its static URL, sanitizes the markup, and inlines it (via dangerouslySetInnerHTML) so the SVG can inherit currentColor and be recolored by CSS. Sanitization strips hardcoded fill/stroke colors, <style> blocks, and class attributes, rewriting them to currentColor. Fetched icons are cached in a module-level svgCache
  • Falls back to a plain <img> tag when the fetched resource is not SVG, and for type === 'subjects' icons; falls back to the generic icon when an icon fails to load
  • Updates CSS selectors in patrol/report list and header styles from svg to img, and uses filter: invert(1) to render icons white on dark headers

Jira

ERA-13076

Test plan

  • Event icons render correctly in the report list
  • Patrol icons render correctly in the patrol list and detail view
  • Collection icons show the correct badge icon
  • Generic fallback icon displays when an icon is missing
  • Community-scoped routes load icons from the community API endpoint
  • Icons recolor correctly via currentColor (e.g. white on dark headers)
  • Cluster markers render and update correctly, including when an event has unsaved local edits

🤖 Generated with Claude Code

Replace SVG sprite-based icon loading with direct img tags using static SVG file URLs, simplifying the icon rendering pipeline and removing the preloaded sprite dependency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jeslefcourt jeslefcourt self-assigned this Apr 8, 2026
@jeslefcourt jeslefcourt requested a review from luixlive April 8, 2026 21:55

@luixlive luixlive left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple small suggestions and a couple questions. Nothing hard-blocking, but worth taking a minute to think them through.

Comment thread src/DasIcon/index.js Outdated
Comment thread src/DasIcon/index.js Outdated
Comment thread src/EventIcon/index.js Outdated
Comment thread src/EventIcon/index.js Outdated
Comment thread src/PatrolDetailView/Header/styles.module.scss Outdated
Comment thread src/App.js

This comment was marked as outdated.

…mage files. Had a bit of a snowball effect into things impacted by cascading styles.

This comment was marked as outdated.

- Remove !important flags on svgs
- Fixed icon colors in clusters and cluster popups changing when editing events before saving
- Sanitize SVGs to avoid injection attacks
@jeslefcourt jeslefcourt requested a review from Copilot April 9, 2026 04:52

This comment was marked as outdated.

This comment was marked as outdated.

@jeslefcourt jeslefcourt force-pushed the ERA-13076-remove-sprite-approach-to-loading-icons branch from d4bcd19 to 3d4d8ab Compare April 9, 2026 06:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 27 changed files in this pull request and generated 3 comments.

Comment thread src/DasIcon/index.js Outdated
Comment thread src/SvgIcon/index.js
Comment thread src/EventIcon/index.js Outdated
@jeslefcourt jeslefcourt changed the title ERA-13076: Remove sprite approach to loading icons ERA-13076: Remove approach to loading icons via one enormous sprite Apr 9, 2026
@jeslefcourt jeslefcourt requested a review from luixlive April 9, 2026 07:40

@JoshuaVulcan JoshuaVulcan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks and feels pretty good so far! Will keep manually testing. My feedback on this review pass is around finishing off the refactor by making sure files and names are cleaned up.

Comment thread src/ClustersLayer/utils.js Outdated
import mapboxgl from 'mapbox-gl';

import { CLUSTER_CLICK_ZOOM_THRESHOLD, LAYER_IDS, SUBJECT_FEATURE_CONTENT_TYPE } from '../constants';
import { calcSvgImageIconId } from '../MapImageFromSvgSpriteRenderer';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like MapImageFromSvgSpriteRenderer should be removed entirely, and the utility function to calculate image URLS lifted/shifted elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lifted calcSvgImageIconId into src/utils/mapImages.js and repointed all importers (commit b10b38e). On removing MapImageFromSvgSpriteRenderer entirely: its default-export component is still load-bearing — it generates state.view.mapImages, which both EventsLayer's on-map symbol layer and the cluster markers consume — so fully removing it needs a separate migration of the on-map rendering path. I'd suggest tracking that as a follow-up rather than expanding this PR. Leaving this thread open for your call on the follow-up.

Comment thread src/ClustersLayer/utils.js Outdated
Comment thread src/SvgIcon/index.test.js

@luixlive luixlive left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple more comments and questions. I see now we are also updating the clusters when we have a locally edited event, which is a nice addition, but it's increasing the size of this PR considerably.

Once these comments are solved / responded, I'll be ready to approve. Still think we will need a special treatment from QA to make sure all icons render correctly and that clusters work and update correctly when we have local changes in an event that haven't been saved yet 👍 @AlanCalvillo

Comment thread src/ClustersLayer/index.js
Comment thread src/ClustersLayer/utils.js Outdated
Comment thread src/DasIcon/index.js Outdated
… rename

- Refactor sanitizeSvg into named per-pass helpers for readability (no behavior change)
- Rename DasIcon -> SvgIcon (component, directory, all importers); sprite is gone
- Stabilize ClustersLayer update callback via refs so it stops re-firing on every
  eventStore change; effects now fire only on locallyEditedEvent / mapImages
- Simplify getFeatureIcon (only priority is user-editable) and drop the dead
  eventStore threading through createClusterHTMLMarker/addNewClusterMarkers
- Extract calcSvgImageIconId into src/utils/mapImages.js; repoint importers
- Rename isLocally -> isLocallyEdited
- LayerSelectorPopup: hide the list <img> on load error so missing sources
  don't render a broken-image glyph

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jeslefcourt and others added 3 commits June 15, 2026 11:40
…prite-approach-to-loading-icons

# Conflicts:
#	package.json
#	src/DasIcon/index.js
#	src/EventsLayer/index.js
#	src/LayerSelectorPopup/index.js
#	src/ReportManager/Header/styles.module.scss
#	yarn.lock
develop's eslint-9/react-hooks-7 upgrade flags render-phase ref mutation.
These refs hold the latest values read only inside the async marker-update
callback and effects, never during render; synchronous assignment guarantees
they are current before any effect/callback runs. Add justified disables.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ster comment

- Add SvgIcon tests covering the community events (extension-less) and
  community non-events (sprite-src .svg) icon endpoints
- injectClass: trim merged class value to avoid leading/double spaces
- sanitizeSvg: return null on DOMParser parsererror so the fallback engages
- ClustersLayer: comment why imageLoaded uses the original-priority icon key
  for locally-edited features (markers are always recreated anyway)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants