Skip to content

Commit

Permalink
Merge pull request #31482 from software-mansion-labs/ts-migration/avatar
Browse files Browse the repository at this point in the history
[TS migration] Migrate 'Avatar.js' component to TypeScript
  • Loading branch information
AndrewGable authored Dec 4, 2023
2 parents 239767c + df88c1d commit c1844a2
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 129 deletions.
126 changes: 0 additions & 126 deletions src/components/Avatar.js

This file was deleted.

118 changes: 118 additions & 0 deletions src/components/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, {useEffect, useState} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import useNetwork from '@hooks/useNetwork';
import * as ReportUtils from '@libs/ReportUtils';
import {AvatarSource} from '@libs/UserUtils';
import * as StyleUtils from '@styles/StyleUtils';
import type {AvatarSizeName} from '@styles/StyleUtils';
import useTheme from '@styles/themes/useTheme';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {AvatarType} from '@src/types/onyx/OnyxCommon';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import Image from './Image';

type AvatarProps = {
/** Source for the avatar. Can be a URL or an icon. */
source?: AvatarSource;

/** Extra styles to pass to Image */
imageStyles?: StyleProp<ViewStyle>;

/** Additional styles to pass to Icon */
iconAdditionalStyles?: StyleProp<ViewStyle>;

/** Extra styles to pass to View wrapper */
containerStyles?: StyleProp<ViewStyle>;

/** Set the size of Avatar */
size?: AvatarSizeName;

/**
* The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue'
* If the avatar is type === workspace, this fill color will be ignored and decided based on the name prop.
*/
fill?: string;

/** A fallback avatar icon to display when there is an error on loading avatar from remote URL.
* If the avatar is type === workspace, this fallback icon will be ignored and decided based on the name prop.
*/
fallbackIcon?: AvatarSource;

/** Denotes whether it is an avatar or a workspace avatar */
type?: AvatarType;

/** Owner of the avatar. If user, displayName. If workspace, policy name */
name?: string;
};

function Avatar({
source,
imageStyles,
iconAdditionalStyles,
containerStyles,
size = CONST.AVATAR_SIZE.DEFAULT,
fill,
fallbackIcon = Expensicons.FallbackAvatar,
type = CONST.ICON_TYPE_AVATAR,
name = '',
}: AvatarProps) {
const theme = useTheme();
const styles = useThemeStyles();
const [imageError, setImageError] = useState(false);

useNetwork({onReconnect: () => setImageError(false)});

useEffect(() => {
setImageError(false);
}, [source]);

if (!source) {
return null;
}

const isWorkspace = type === CONST.ICON_TYPE_WORKSPACE;
const iconSize = StyleUtils.getAvatarSize(size);

const imageStyle = [StyleUtils.getAvatarStyle(theme, size), imageStyles, styles.noBorderRadius];
const iconStyle = imageStyles ? [StyleUtils.getAvatarStyle(theme, size), styles.bgTransparent, imageStyles] : undefined;

const iconFillColor = isWorkspace ? StyleUtils.getDefaultWorkspaceAvatarColor(name).fill : fill ?? theme.icon;
const fallbackAvatar = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatar(name) : fallbackIcon || Expensicons.FallbackAvatar;

const avatarSource = imageError ? fallbackAvatar : source;

return (
<View style={[containerStyles, styles.pointerEventsNone]}>
{typeof avatarSource === 'function' ? (
<View style={iconStyle}>
<Icon
src={avatarSource}
height={iconSize}
width={iconSize}
fill={imageError ? theme.offline : iconFillColor}
additionalStyles={[
StyleUtils.getAvatarBorderStyle(size, type),
isWorkspace && StyleUtils.getDefaultWorkspaceAvatarColor(name),
imageError && StyleUtils.getBackgroundColorStyle(theme.fallbackIconColor),
iconAdditionalStyles,
]}
/>
</View>
) : (
<View style={[iconStyle, StyleUtils.getAvatarBorderStyle(size, type), iconAdditionalStyles]}>
<Image
source={{uri: avatarSource}}
style={imageStyle}
onError={() => setImageError(true)}
/>
</View>
)}
</View>
);
}

Avatar.displayName = 'Avatar';

export default Avatar;
3 changes: 2 additions & 1 deletion src/components/SubscriptAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as StyleUtils from '@styles/StyleUtils';
import useTheme from '@styles/themes/useTheme';
import useThemeStyles from '@styles/useThemeStyles';
import CONST from '@src/CONST';
import {AvatarType} from '@src/types/onyx/OnyxCommon';
import Avatar from './Avatar';
import UserDetailsTooltip from './UserDetailsTooltip';

Expand All @@ -14,7 +15,7 @@ type SubAvatar = {
source?: AvatarSource;

/** Denotes whether it is an avatar or a workspace avatar */
type?: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE;
type?: AvatarType;

/** Owner of the avatar. If user, displayName. If workspace, policy name */
name?: string;
Expand Down
2 changes: 2 additions & 0 deletions src/styles/StyleUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,8 @@ function getDotIndicatorTextStyles(styles: ThemeStyles, isErrorText = true): Tex
return isErrorText ? {...styles.offlineFeedback.text, color: styles.formError.color} : {...styles.offlineFeedback.text};
}

export type {AvatarSizeName};

export {
combineStyles,
displayIfTrue,
Expand Down
6 changes: 4 additions & 2 deletions src/types/onyx/OnyxCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ type ErrorFields<TKey extends string = string> = Record<TKey, Errors | null | un

type Errors = Record<string, string>;

type AvatarType = typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE;

type Icon = {
/** Avatar source to display */
source: AvatarSource;

/** Denotes whether it is an avatar or a workspace avatar */
type: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE;
type: AvatarType;

/** Owner of the avatar. If user, displayName. If workspace, policy name */
name: string;
Expand All @@ -27,4 +29,4 @@ type Icon = {
fallbackIcon?: AvatarSource;
};

export type {Icon, PendingAction, PendingFields, ErrorFields, Errors};
export type {Icon, PendingAction, PendingFields, ErrorFields, Errors, AvatarType};

0 comments on commit c1844a2

Please sign in to comment.