-
-
Notifications
You must be signed in to change notification settings - Fork 428
feat(edit-profile): allow custom avatar #995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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 PR adds a custom avatar feature that allows users to set any public image URL for their profile picture, with automatic fallback to their OAuth provider's avatar if the custom URL fails to load.
Key changes:
- Added client-side validation for avatar URLs with http/https protocol checking
- Implemented error handling with automatic fallback to OAuth provider avatars
- Added new modal UI component for editing avatars with user-friendly hints
- Modified backend to support custom avatar storage while maintaining OAuth avatar as fallback
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
src/types/models.d.ts |
Added optional auth0Id field to User type for provider identification |
src/components/MemberArea/model.js |
Updated avatar validation to accept any valid http/https URL instead of restricting to specific providers |
src/components/MemberArea/MemberArea.js |
Added error state management and fallback logic for failed avatar URLs |
src/components/MemberArea/EditProfile.js |
Replaced static Gravatar redirect with editable URL input field and fallback error handling |
src/Me/Routes/Home/Avatar/AvatarEditModal.tsx |
New modal component for editing avatar URLs with clear/save functionality |
src/Me/Routes/Home/Avatar/Avatar.tsx |
Complete refactor with modal integration, error handling, badge indicators, and state management |
netlify/functions-src/functions/modules/users/current.ts |
Modified to prioritize custom avatar over OAuth picture and expose auth0Picture for client-side fallback |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this 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 15 out of 16 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (2)
src/Me/Routes/Home/Avatar/Avatar.tsx:1
- Unused import useEffect.
import React, { FC, useState, useEffect } from 'react';
src/Me/Routes/Home/Avatar/Avatar.tsx:59
- Unused variable isSaving.
const [isSaving, setIsSaving] = useState(false);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ...currentUser, | ||
| email_verified: context.user?.email_verified, | ||
| avatar: context.user?.picture, | ||
| avatar: avatarUrl, |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The auth0Picture and auth0Id fields are not being populated in the response. The frontend components like AvatarField.tsx and Avatar.tsx depend on these fields to determine if the user is a Google user and to provide fallback avatar URLs.
You should add these fields to the response:
const applicationUser = {
...currentUser,
email_verified: context.user?.email_verified,
avatar: avatarUrl,
auth0Picture: context.user?.picture,
auth0Id: currentUser.auth0Id,
};| avatar: avatarUrl, | |
| avatar: avatarUrl, | |
| auth0Picture: context.user?.picture, | |
| auth0Id: currentUser.auth0Id, |
| const { currentUser } = useUser<true>(); | ||
| const { currentUser, updateCurrentUser } = useUser<true>(); | ||
| const api = useApi(); | ||
| const [isSaving, setIsSaving] = useState(false); |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The isSaving state is declared but never used to disable the UI or show a loading state during the avatar toggle operation. Consider using this state to provide visual feedback:
<Switch
label="Use Gravatar"
isChecked={isUsingGravatar}
onToggle={handleToggleGravatar}
size="small"
disabled={isSaving} // Add this
/>| const updatedUser = await upsertUser(userDto); | ||
|
|
||
| return success({ | ||
| data: updatedUser, |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The toggleAvatarHandler should return the complete user object with auth0Picture and auth0Id fields to match what the frontend expects. Currently, upsertUser returns the database user object which may not include these fields populated from the Auth0 context.
Consider returning a complete application user similar to the current handler:
const updatedUser = await upsertUser(userDto);
return success({
data: {
...updatedUser,
auth0Picture: context.user?.picture,
auth0Id: updatedUser.auth0Id,
},
});| data: updatedUser, | |
| data: { | |
| ...updatedUser, | |
| auth0Picture: context.user?.picture, | |
| auth0Id: updatedUser.auth0Id, | |
| }, |
| position="bottom" | ||
| > | ||
| <i className="fa fa-info-circle"></i> | ||
| </Tooltip>{" "} |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] There's an inconsistent space character {" "} on line 116. Consider placing the content inline or formatting it consistently with line 126:
</Tooltip>
<ToggleLabel>or remove the space entirely as it's not needed between these elements.
| </Tooltip>{" "} | |
| </Tooltip> |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This pull request introduces a new feature that allows users to toggle between using their Google profile picture and a Gravatar image as their avatar. The backend now supports updating and persisting the avatar choice, while the frontend provides a clear UI for switching and previewing the selected avatar.
Backend: Avatar selection and persistence
/current/avatar, POST) and handler (toggleAvatarHandler) to allow users to switch their avatar between Gravatar and their Auth0/Google profile picture. The handler computes the Gravatar URL and updates the user record accordingly. [1] [2]Frontend: Avatar UI and logic
getAvatarUrlhelper. This affects components such asUsersList,Card,MemberArea, andEditProfile. [1] [2] [3] [4]Avatar.tsx,EditProfile.js, and newAvatarField.tsx) for Google-authenticated users to switch between Gravatar and Google profile picture. The UI provides links to update the avatar at the relevant provider. [1] [2] [3]API integration
toggleAvatarmethod to theApiServicefor calling the backend endpoint and updating the current user context after avatar changes.Error handling and UI polish