Skip to content

Comments

feat(edit-profile): allow switch gravar / Google avatar picture#1001

Open
moshfeu wants to merge 6 commits intomasterfrom
gravatar-switch
Open

feat(edit-profile): allow switch gravar / Google avatar picture#1001
moshfeu wants to merge 6 commits intomasterfrom
gravatar-switch

Conversation

@moshfeu
Copy link
Member

@moshfeu moshfeu commented Jan 28, 2026

Changes

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.

Backend changes:

  • Added a new API endpoint /users/current/avatar (POST) to allow users to switch between their Google profile picture and Gravatar avatar. The endpoint updates the user's avatar URL in the database and returns the updated user object. [1] [2] [3]
  • Updated the current user handler to prefer the stored avatar, falling back to the Auth0 picture if not set, and to return both avatar and auth0Picture fields.
  • Improved error handling in user update endpoints for better type safety.

Frontend changes:

  • Added UI components (AvatarField and updates to Avatar.tsx and EditProfile.js) to let users toggle between Gravatar and Google profile avatars, including a switch and contextual help links. [1] [2] [3] [4] [5] [6] [7]
  • Integrated the new API endpoint into the frontend's API service and updated user context after avatar changes. [1] [2] [3]
  • Removed all usage of the legacy getAvatarUrl helper, updating all avatar references to use the direct avatar URL from the user object. [1] [2] [3] [4] [5] [6]

UI consistency and fallback improvements:

  • Updated avatar display logic throughout the app to consistently use the stored avatar URL, with fallback to Auth0 picture if needed, and improved error handling for broken avatar images. [1] [2] [3] [4]

Demo

Screen.Recording.2026-01-29.at.0.52.52.mov

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 PR adds a feature allowing users with Google OAuth accounts to toggle between using their Google profile picture and a Gravatar avatar as their profile image.

Changes:

  • Added backend API endpoint /users/current/avatar (POST) to handle avatar switching with appropriate user lookup and URL generation
  • Added frontend UI components (AvatarField) to display avatar selection toggle with contextual help links
  • Updated avatar display logic throughout the application to use stored avatar URL with auth0Picture fallback, and removed the legacy getAvatarUrl helper function

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/types/models.d.ts Added auth0Picture and auth0Id optional fields to User type
src/helpers/avatar.js Removed legacy getAvatarUrl helper function
src/helpers/authProvider.ts Added new helper to detect auth provider from auth0Id
src/components/MemberArea/model.js Reorganized avatar field configuration, removed validation
src/components/MemberArea/PendingApplications.js Updated to use avatar URL directly instead of helper function
src/components/MemberArea/MemberArea.js Added avatar error handling with fallback to auth0Picture
src/components/MemberArea/EditProfile.js Integrated avatar toggle functionality with new AvatarField component
src/components/MemberArea/AvatarField.tsx New component providing avatar toggle UI for Google OAuth users
src/components/Card/Card.tsx Removed getAvatarUrl usage, minor whitespace cleanup
src/api/index.ts Added toggleAvatar API method
src/Me/Routes/Home/Avatar/Avatar.tsx Integrated avatar toggle with Switch component and user feedback
src/Me/MentorshipRequests/UsersList.tsx Updated to use avatar URL directly
netlify/functions-src/functions/users.ts Added route for avatar toggle endpoint
netlify/functions-src/functions/modules/users/userInfo.ts Improved error handling type safety
netlify/functions-src/functions/modules/users/toggleAvatar.ts New handler implementing avatar toggle logic
netlify/functions-src/functions/modules/users/current.ts Updated to return auth0Picture and prefer stored avatar

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,14 +1,17 @@
import React, { FC } from 'react';
import React, { FC, useState, useEffect } from 'react';
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The useEffect import is unused in this file. It should be removed from the imports to keep the code clean.

Suggested change
import React, { FC, useState, useEffect } from 'react';
import React, { FC, useState } from 'react';

Copilot uses AI. Check for mistakes.
import React, { FC, useState, useEffect } from 'react';
import styled from 'styled-components/macro';
import { useUser } from '../../../../context/userContext/UserContext';
import type { User } from '../../../../types/models';
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The User type import is unused in this file. It should be removed from the imports to keep the code clean.

Suggested change
import type { User } from '../../../../types/models';

Copilot uses AI. Check for mistakes.
user: fromMtoVM(this.context.currentUser),
errors: [],
agree: false,
isUsingGravatar: this.context.currentUser?.avatar?.includes('gravatar.com') || false,
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The logic for determining whether a user is using Gravatar relies on checking if the avatar URL contains 'gravatar.com'. However, this approach may not work correctly if the avatar URL is undefined or if a user switches from Google to Gravatar and the URL hasn't been updated yet. Consider checking the avatar URL against both the auth0Picture to determine which one is currently active, or storing the avatar preference explicitly in the database.

Copilot uses AI. Check for mistakes.
return null;
}

const isUsingGravatar = currentUser.avatar?.includes('gravatar.com') || false;
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The logic for determining whether a user is using Gravatar relies on checking if the avatar URL contains 'gravatar.com'. However, this approach may not work correctly if the avatar URL is undefined or if a user switches from Google to Gravatar and the URL hasn't been updated yet. Consider checking the avatar URL against both the auth0Picture to determine which one is currently active, or storing the avatar preference explicitly in the database.

Suggested change
const isUsingGravatar = currentUser.avatar?.includes('gravatar.com') || false;
const isUsingGravatar =
!!currentUser.avatar &&
!!(currentUser as User).auth0Picture &&
currentUser.avatar !== (currentUser as User).auth0Picture;

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +38
const avatarUrl = useGravatar ? getGravatarUrl(currentUser.email) : context.user?.picture;

Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The backend handler should validate that the user is a Google OAuth user before allowing them to switch to their Google profile picture. Currently, any user can call this endpoint with useGravatar=false, which would set their avatar to context.user?.picture even if they're not a Google OAuth user. Consider adding validation similar to the frontend's isGoogleOAuthUser check to ensure only Google OAuth users can switch to their Google profile picture.

Suggested change
const avatarUrl = useGravatar ? getGravatarUrl(currentUser.email) : context.user?.picture;
const isGoogleOAuthUser = auth0Id.startsWith('google-oauth2|');
if (!useGravatar) {
if (!isGoogleOAuthUser || !context.user?.picture) {
return error(
'Switching to Google profile picture is only allowed for Google OAuth users.',
400
);
}
}
const avatarUrl = useGravatar ? getGravatarUrl(currentUser.email) : context.user.picture;

Copilot uses AI. Check for mistakes.
return error('User not found', 404);
}

const avatarUrl = useGravatar ? getGravatarUrl(currentUser.email) : context.user?.picture;
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

When useGravatar is false, the avatar URL is set to context.user?.picture, which could potentially be undefined. This could result in setting the avatar to undefined in the database. Consider adding validation to ensure context.user?.picture exists before allowing the switch, or falling back to generating a Gravatar URL if it's missing.

Suggested change
const avatarUrl = useGravatar ? getGravatarUrl(currentUser.email) : context.user?.picture;
const avatarUrl =
useGravatar || !context.user?.picture
? getGravatarUrl(currentUser.email)
: context.user.picture;

Copilot uses AI. Check for mistakes.
@@ -1,14 +1,17 @@
import React, { FC } from 'react';
import React, { FC, useState, useEffect } from 'react';
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Unused import useEffect.

Suggested change
import React, { FC, useState, useEffect } from 'react';
import React, { FC } from 'react';

Copilot uses AI. Check for mistakes.
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.

1 participant