Skip to content

Commit

Permalink
[dev-launcher] Update user avatars to use the same logic as the websi…
Browse files Browse the repository at this point in the history
…te (expo#23114)

# Why

Closes ENG-7614

# How
 
This PR adds a building icon to `dev-client-components` (the same one
used on the website) and adds a `Avatar` component to `dev-launcher` to
handle all the logic for rendering an account avatar.


# Test Plan

Run dev-client through bare-expo 

<table>
    <tr><th>Android</th><th>iOS</th></tr>
    <tr>
    <td>
<video
src="https://github.com/expo/expo/assets/11707729/f1ce2d4f-a1e1-4988-85d7-5250a3a2ad23"/>
   </td>
   <td>
<video
src="https://github.com/expo/expo/assets/11707729/d5a7df31-2dd8-47ce-8580-f4a0b7e1cf5b"
/>
    </td>
</tr> 
</table> 


# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
This is required for changes to Expo modules.
-->

- [ ] Documentation is up to date to reflect these changes (eg:
https://docs.expo.dev and README.md).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
  • Loading branch information
gabrieldonadel authored Jun 26, 2023
1 parent cfeebad commit fd7025d
Show file tree
Hide file tree
Showing 18 changed files with 611 additions and 500 deletions.
2 changes: 2 additions & 0 deletions packages/expo-dev-client-components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### 🎉 New features

- Add Building icon. ([#23114](https://github.com/expo/expo/pull/23114) by [@gabrieldonadel](https://github.com/gabrieldonadel))

### 🐛 Bug fixes

### 💡 Others
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';

import { Image } from '../Image';

const icon = require('../../assets/building-icon.png');

export function BuildingIcon(props: Partial<React.ComponentProps<typeof Image>>) {
return <Image source={icon} {...props} />;
}
1 change: 1 addition & 0 deletions packages/expo-dev-client-components/src/icons/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './BuildingIcon';
export * from './BranchIcon';
export * from './CheckIcon';
export * from './ChevronRightIcon';
Expand Down
1 change: 1 addition & 0 deletions packages/expo-dev-launcher/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### 🎉 New features

- Add support for SSO users. ([#22873](https://github.com/expo/expo/pull/22873) by [@wschurman](https://github.com/wschurman))
- Update user avatars to use the same logic as the website. ([#23114](https://github.com/expo/expo/pull/23114) by [@gabrieldonadel](https://github.com/gabrieldonadel))

### 🐛 Bug fixes

Expand Down

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 11 additions & 19 deletions packages/expo-dev-launcher/bundle/components/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useWindowDimensions } from 'react-native';
import { SafeAreaTop } from '../components/SafeAreaTop';
import { useBuildInfo } from '../providers/BuildInfoProvider';
import { useUser } from '../providers/UserContextProvider';
import { Avatar } from './Avatar';

export function AppHeader({ navigation }) {
const buildInfo = useBuildInfo();
Expand Down Expand Up @@ -69,11 +70,16 @@ export function AppHeader({ navigation }) {
<View>
{isAuthenticated ? (
<View rounded="full" padding="small">
<View height="xl" width="xl" bg="secondary" rounded="full">
{selectedUserImage && (
<Image size="xl" rounded="full" source={{ uri: selectedUserImage }} />
)}
</View>
<Avatar
profilePhoto={selectedUserImage}
name={
selectedAccount?.ownerUserActor?.fullName
? selectedAccount.ownerUserActor.fullName
: selectedAccount?.name
}
isOrganization={selectedAccount?.ownerUserActor === null}
size="xl"
/>
</View>
) : (
<View mx="small">
Expand All @@ -84,20 +90,6 @@ export function AppHeader({ navigation }) {
)}
</View>
</Button.HighlightOnPressContainer>
{!selectedUserImage && (
<Row
style={{
height: scale[2],
flexWrap: 'wrap',
maxWidth: scale[16],
paddingRight: scale[2],
transform: [{ translateY: -scale[2] }],
}}>
<Text numberOfLines={1} size="small" align="center" weight="medium">
{selectedAccount?.name}
</Text>
</Row>
)}
</View>
</Row>
</View>
Expand Down
96 changes: 96 additions & 0 deletions packages/expo-dev-launcher/bundle/components/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { iconSize, palette } from '@expo/styleguide-native';
import { View, Image, scale, BuildingIcon, UserIcon } from 'expo-dev-client-components';
import React from 'react';
import { StyleSheet } from 'react-native';

type Props = {
name?: string;
profilePhoto?: string;
isOrganization?: boolean;
size?: React.ComponentProps<typeof Image>['size'];
};

export function Avatar({ profilePhoto, size = 'large', name = '', isOrganization = false }: Props) {
const firstLetter = name?.charAt(0).toLowerCase();
const viewSize = getViewSize(size);

if (isOrganization) {
const { backgroundColor, tintColor } = getOrganizationColor(firstLetter);
return (
<View
style={{
height: viewSize,
width: viewSize,
backgroundColor,
}}
rounded="full"
align="centered"
bg="secondary">
<BuildingIcon resizeMode="center" style={styles.icon} tintColor={tintColor} />
</View>
);
}

if (!profilePhoto || !firstLetter) {
return (
<View
style={{ height: viewSize, width: viewSize }}
rounded="full"
align="centered"
bg="secondary">
<UserIcon resizeMode="center" style={styles.icon} />
</View>
);
}

let _profilePhoto = profilePhoto;
if (profilePhoto.match('gravatar.com')) {
const defaultProfilePhoto = encodeURIComponent(
`https://storage.googleapis.com/expo-website-default-avatars-2023/${firstLetter}.png`
);
_profilePhoto = `${profilePhoto}&d=${defaultProfilePhoto}`;
}

return (
<View rounded="full" bg="secondary">
<Image rounded="full" source={{ uri: _profilePhoto }} size={size} />
</View>
);
}

function getOrganizationColor(firstLetter?: string) {
if (firstLetter?.match(/[a-d]/)) {
return { backgroundColor: palette.light.blue[200], tintColor: palette.light.blue[900] };
} else if (firstLetter?.match(/[e-h]/)) {
return { backgroundColor: palette.light.green[200], tintColor: palette.light.green[900] };
} else if (firstLetter?.match(/[i-l]/)) {
return { backgroundColor: palette.light.yellow[400], tintColor: palette.light.yellow[900] };
} else if (firstLetter?.match(/[m-p]/)) {
return { backgroundColor: palette.light.orange[200], tintColor: palette.light.orange[900] };
} else if (firstLetter?.match(/[q-t]/)) {
return { backgroundColor: palette.light.red[200], tintColor: palette.light.red[900] };
} else if (firstLetter?.match(/[u-z]/)) {
return { backgroundColor: palette.light.pink[200], tintColor: palette.light.pink[900] };
} else {
return { backgroundColor: palette.light.purple[200], tintColor: palette.light.purple[900] };
}
}

function getViewSize(size?: React.ComponentProps<typeof Image>['size']) {
switch (size) {
case 'tiny':
return scale.small;
case 'small':
return iconSize.small;
case 'large':
return iconSize.large;
case 'xl':
return scale.xl;
default:
return iconSize.large;
}
}

const styles = StyleSheet.create({
icon: { width: '45%', height: '45%' },
});
18 changes: 11 additions & 7 deletions packages/expo-dev-launcher/bundle/screens/UserProfileScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as React from 'react';
import { ActivityIndicator, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

import { Avatar } from '../components/Avatar';
import { LogoutConfirmationModal } from '../components/LogoutConfirmationModal';
import { UserAccount, UserData } from '../functions/getUserProfileAsync';
import { useModalStack } from '../providers/ModalStackProvider';
Expand Down Expand Up @@ -213,13 +214,16 @@ function UserAccountSelector({
roundedBottom={isLast ? 'large' : 'none'}
roundedTop={isFirst ? 'large' : 'none'}>
<Row align="center" py="small" px="medium" bg="default">
<View rounded="full" bg="secondary">
<Image
size="large"
rounded="full"
source={{ uri: account.ownerUserActor?.profilePhoto }}
/>
</View>
<Avatar
profilePhoto={account?.ownerUserActor?.profilePhoto}
name={
account?.ownerUserActor?.fullName
? account.ownerUserActor.fullName
: account?.name
}
isOrganization={account?.ownerUserActor === null}
size="large"
/>
<Spacer.Horizontal size="small" />

<View>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit fd7025d

Please sign in to comment.