-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Main Issue
Goal
User can upload either a custom avatar or an initial avatar from the new page. This wraps up the project.
Uses InitialAvatars.ts from #71815
Detailed Background
Existing Pattern for Coloring Workspace SVGs:
Color Options for Initials:
Lines 54 to 73 in fa5e06d
| const workspaceColorOptions: SVGAvatarColorStyle[] = [ | |
| {backgroundColor: colors.blue200, fill: colors.blue700}, | |
| {backgroundColor: colors.blue400, fill: colors.blue800}, | |
| {backgroundColor: colors.blue700, fill: colors.blue200}, | |
| {backgroundColor: colors.green200, fill: colors.green700}, | |
| {backgroundColor: colors.green400, fill: colors.green800}, | |
| {backgroundColor: colors.green700, fill: colors.green200}, | |
| {backgroundColor: colors.yellow200, fill: colors.yellow700}, | |
| {backgroundColor: colors.yellow400, fill: colors.yellow800}, | |
| {backgroundColor: colors.yellow700, fill: colors.yellow200}, | |
| {backgroundColor: colors.tangerine200, fill: colors.tangerine700}, | |
| {backgroundColor: colors.tangerine400, fill: colors.tangerine800}, | |
| {backgroundColor: colors.tangerine700, fill: colors.tangerine400}, | |
| {backgroundColor: colors.pink200, fill: colors.pink700}, | |
| {backgroundColor: colors.pink400, fill: colors.pink800}, | |
| {backgroundColor: colors.pink700, fill: colors.pink200}, | |
| {backgroundColor: colors.ice200, fill: colors.ice700}, | |
| {backgroundColor: colors.ice400, fill: colors.ice800}, | |
| {backgroundColor: colors.ice700, fill: colors.ice200}, | |
| ]; |
How we color workspace SVGs:
Lines 309 to 315 in 4f2680e
| /** | |
| * Helper method to return workspace avatar color styles | |
| */ | |
| function getDefaultWorkspaceAvatarColor(text: string): ViewStyle { | |
| const colorHash = hashText(text.trim(), workspaceColorOptions.length); | |
| return workspaceColorOptions.at(colorHash) ?? {backgroundColor: colors.blue200, fill: colors.blue700}; | |
| } |
How we fetch workspace SVG
Lines 2787 to 2805 in 4f2680e
| /** | |
| * Helper method to return the default avatar associated with the given login | |
| */ | |
| function getDefaultWorkspaceAvatar(workspaceName?: string): React.FC<SvgProps> { | |
| if (!workspaceName) { | |
| return defaultWorkspaceAvatars.WorkspaceBuilding; | |
| } | |
| // Remove all chars not A-Z or 0-9 including underscore | |
| const alphaNumeric = workspaceName | |
| .normalize('NFD') | |
| .replace(/[^0-9a-z]/gi, '') | |
| .toUpperCase(); | |
| const workspace = `Workspace${alphaNumeric[0]}` as keyof typeof defaultWorkspaceAvatars; | |
| const defaultWorkspaceAvatar = defaultWorkspaceAvatars[workspace]; | |
| return !alphaNumeric ? defaultWorkspaceAvatars.WorkspaceBuilding : defaultWorkspaceAvatar; | |
| } |
Creating / Uploading an image file
@jmusial Note: we can diverge from this plan if there is a simpler or cleaner solution found:
Option 1
- Create: /src/pages/settings/Profile/Avatar/AvatarGenerator.tsx - dedicated component to render the selected avatar for capturing
- Render the selected SVG: use existingAvatar component/react-native-svg- Pass the user's selected color as a fill prop to the SVG component.
- Capture the view: use exisiting react-native-view-shot - Wrap in <ViewShot> component and capture View as a 400x400 png.
- Generate the image: Expose a capture function via ref that returns the image file URI.
- Upload the image: Use the existing UpdateUserAvatar action. Convert the image URI from the generator into a file object, similar to how it's done in ProfilePage.js for photo library uploads.
Option 2
Instead of generating an image from FE, we call a modified API endpoint (or a new one) and send the identifier for the SVG shape and the selected color value. For example: UpdateUserAvatar({avatar: 'F', color: '#B5853D', fill: '#FFFFF'}) or UpdateUserAvatar({avatar-slug: 'E', color-slug: 'djojd'}) (colors E with some BE allowed color combo under some color ID )