Skip to content

Conversation

vinodsingh-dev-gsoc
Copy link

This change improves the user experience by displaying a consistent placeholder when an avatar image fails to load from its URL.

Adds an errorBuilder to the AvatarImage widget and includes a test case to verify the new behavior.

Fixes #1558.

@vinodsingh-dev-gsoc vinodsingh-dev-gsoc force-pushed the fix/avatar-placeholder-1558 branch from 60b16e2 to 97f92e7 Compare October 1, 2025 16:17
@chrisbobbe
Copy link
Collaborator

Thanks for the PR! Please post before/after screenshots of the change. Please also change the commit sequence so the tests are added in the same commit that adds the behavior being tested.

@vinodsingh-dev-gsoc vinodsingh-dev-gsoc force-pushed the fix/avatar-placeholder-1558 branch from 97f92e7 to 3f69209 Compare October 2, 2025 06:36
@vinodsingh-dev-gsoc
Copy link
Author

Hi chrisbobbe! Thanks a lot for the detailed feedback. I'm currently working on your suggestions. I've gathered the before/after screenshots and am now in the process of squashing the commits and fixing the test suite to make the PR perfect. I'll push the updated changes shortly! 😊

@vinodsingh-dev-gsoc vinodsingh-dev-gsoc force-pushed the fix/avatar-placeholder-1558 branch from 3f69209 to 0b69fea Compare October 3, 2025 14:04
@vinodsingh-dev-gsoc vinodsingh-dev-gsoc force-pushed the fix/avatar-placeholder-1558 branch from 0b69fea to aa123be Compare October 3, 2025 14:27
@vinodsingh-dev-gsoc
Copy link
Author

status CombinedScreen DM List Profile Screen
Before before_fix_for_combined_list before_fix_for_dm_list before_fix_for_profile_page
After fix after_fix_for_combined_list after_fix_for_dm_list after_fix_profile_page

As you can see in the "After" screenshot, the fix ensures that a placeholder is now displayed whenever an avatar URL is null or fails to load, instead of showing a blank space. This provides a clearer and more consistent UI for the user.

Copy link
Collaborator

@chrisbobbe chrisbobbe left a comment

Choose a reason for hiding this comment

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

Thanks! Small comments below.

Comment on lines +18 to +23
class MockHttpClient extends Fake implements HttpClient {
@override
Future<HttpClientRequest> getUrl(Uri url) async {
throw const SocketException('test error');
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks like the kind of thing that FakeImageHttpClient is for, in test/test_images.dart. Can we use that?

Oh! Or maybe add a boolean success param to prepareBoringImageHttpClient in that file (defaulting to true), and pass false in this case to make it prepare an HttpStats.notFound response?

await tester.pump(); // Image fails to load
expect(find.byIcon(ZulipIcons.person), findsOneWidget);

expect(find.byType(DecoratedBox), findsOneWidget);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems like it could easily find a DecoratedBox that's not related to the behavior we're testing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

How about checking the icon in this way:

        check(find.descendant(
          of: find.byType(AvatarImage),
          matching: find.byIcon(ZulipIcons.person),
        )).findsOne();

(adding the import 'package:flutter_checks/flutter_checks.dart'; at the top as needed)

@chrisbobbe
Copy link
Collaborator

Also please update the commit message to mention the issue being fixed, according to our style.

@gnprice gnprice added the maintainer review PR ready for review by Zulip maintainers label Oct 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
maintainer review PR ready for review by Zulip maintainers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

For avatars that don't load, reuse muted-user placeholder?
3 participants