Skip to content

Conversation

@akabiru
Copy link
Member

@akabiru akabiru commented Jan 8, 2026

https://community.openproject.org/wp/69230

Server-side URL validation would add latency and can't handle relative URLs without knowing the host. Hence, we use client-side error handling:

  • Always wrap avatars in element with pre-generated SVG stored in data-fallback-src attribute
  • Listen for img error events to swap broken images to fallback SVG
  • Check if loading completed but no actual image data loaded to catch errors that fired before the listener was attached (race condition)

Warning

There is a brief flicker from client-side based fallback- not sure if there's a way around this issue. One idea is switching to server-size validation, but requires the component to know about the host. As this is a fallback mechanism for broken images, I suppose this flicker is acceptable.

avatar-fallback-404

@akabiru akabiru requested review from HDinger, Copilot and myabc January 8, 2026 11:55
@akabiru akabiru self-assigned this Jan 8, 2026
@changeset-bot
Copy link

changeset-bot bot commented Jan 8, 2026

🦋 Changeset detected

Latest commit: 36d8fb8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@openproject/primer-view-components Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request implements client-side error handling for avatar images that fail to load (404 errors, network failures, etc.). The component now automatically falls back to displaying SVG initials when an image fails to load, avoiding broken image icons.

Key changes:

  • All avatars are now wrapped in an <avatar-fallback> custom element with pre-generated fallback SVG
  • Client-side error listener detects image load failures and swaps to fallback SVG
  • Race condition handling for errors that fire before listener attachment
  • Updated tests to reflect new always-wrapped behavior

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
app/components/primer/open_project/avatar_with_fallback.rb Changed from conditionally wrapping in avatar-fallback to always wrapping; added fallback_src data attribute
app/components/primer/open_project/avatar_fallback.ts Added error event handling, race condition checking, and image-broken detection logic
test/components/open_project/avatar_with_fallback_test.rb Updated tests to verify always-wrapped behavior and fallback SVG presence
test/components/open_project/avatar_stack_test.rb Updated avatar-fallback count expectation from 1 to 2 to reflect new behavior
previews/primer/open_project/avatar_with_fallback_preview.rb Added two new preview methods for demonstrating 404 error handling
previews/primer/open_project/avatar_with_fallback_preview/multiple_broken_images.html.erb New template demonstrating multiple broken images
static/previews.json Auto-generated: Added entries for new preview methods
static/info_arch.json Auto-generated: Added entries for new preview methods
.changeset/olive-eyes-juggle.md Added changeset entry for this patch-level change

Server-side URL validation would add latency and can't handle relative URLs
without knowing the host. Instead, we use client-side error handling:

- Always wrap avatars in <avatar-fallback> element with pre-generated SVG
  stored in data-fallback-src attribute
- Listen for img error events to swap broken images to fallback SVG
- Check img.complete && naturalWidth === 0 on connect to catch errors that
  fired before the listener was attached (race condition fix)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@akabiru
Copy link
Member Author

akabiru commented Jan 9, 2026

UX/UI Meeting Outcome: https://community.openproject.org/meetings/8147#meeting-agenda-item-23298

  • The flickering is bad given the Gravatar is enabled per instance and will thus cause heavy flickering on those instances
  • We agreed to support static URLs to be loaded beforehand to catch those flickerings. For relative URLs failures, the flickering is ok.

@akabiru akabiru force-pushed the bug/69230-invalid-src-fallback branch from d8ff04f to fdd9db0 Compare January 9, 2026 11:52
@akabiru
Copy link
Member Author

akabiru commented Jan 9, 2026

See:

#396 (comment)

Note

Flickering addressed for known hosts (Gravatars)

avatar-fallback-server-side.mp4

@akabiru akabiru force-pushed the bug/69230-invalid-src-fallback branch 3 times, most recently from 370680d to 6e5fab8 Compare January 9, 2026 12:25
@akabiru akabiru requested a review from Copilot January 9, 2026 12:26
@akabiru akabiru marked this pull request as ready for review January 9, 2026 12:27
@akabiru akabiru requested review from HDinger and myabc January 9, 2026 12:27
Copy link

Copilot AI left a comment

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 13 out of 13 changed files in this pull request and generated 8 comments.

@akabiru
Copy link
Member Author

akabiru commented Jan 9, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link

Copilot AI commented Jan 9, 2026

@akabiru I've opened a new pull request, #397, to work on those changes. Once the pull request is ready, I'll request review from you.

@akabiru akabiru force-pushed the bug/69230-invalid-src-fallback branch from d515ed4 to be01160 Compare January 9, 2026 13:35
@akabiru
Copy link
Member Author

akabiru commented Jan 9, 2026

@HDinger @myabc I've extracted server side validation to a separate PR- as I think it warrants more discussion and also for the benefit of unblocking this work that is needed for the 17.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment