From 0f0c7d57951272686a55f814bc27eaec34c28a8a Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Fri, 15 Jul 2022 04:02:09 -0400 Subject: [PATCH] Open User avatar in gallery (#6474) --- app/components/profile_picture/image.tsx | 10 ++- app/components/profile_picture/index.tsx | 3 + app/screens/gallery/footer/details/index.tsx | 2 + app/screens/gallery/footer/footer.tsx | 10 ++- .../gallery/lightbox_swipeout/index.tsx | 30 +++++---- app/screens/gallery/viewer/index.tsx | 6 +- app/screens/user_profile/title/avatar.tsx | 11 +++- app/screens/user_profile/title/index.tsx | 65 +++++++++++++++++-- types/screens/gallery.d.ts | 2 +- 9 files changed, 110 insertions(+), 29 deletions(-) diff --git a/app/components/profile_picture/image.tsx b/app/components/profile_picture/image.tsx index 6ffcb954c..4081b28e5 100644 --- a/app/components/profile_picture/image.tsx +++ b/app/components/profile_picture/image.tsx @@ -3,6 +3,7 @@ import React, {useMemo} from 'react'; import FastImage, {Source} from 'react-native-fast-image'; +import Animated from 'react-native-reanimated'; import CompassIcon from '@components/compass_icon'; import {ACCOUNT_OUTLINE_IMAGE} from '@constants/profile'; @@ -16,11 +17,15 @@ import type UserModel from '@typings/database/models/servers/user'; type Props = { author?: UserModel | UserProfile; + forwardRef?: React.RefObject; iconSize?: number; size: number; source?: Source | string; }; +// @ts-expect-error FastImage does work with Animated.createAnimatedComponent +const AnimatedFastImage = Animated.createAnimatedComponent(FastImage); + const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { return { icon: { @@ -29,7 +34,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -const Image = ({author, iconSize, size, source}: Props) => { +const Image = ({author, forwardRef, iconSize, size, source}: Props) => { const theme = useTheme(); const serverUrl = useServerUrl(); const style = getStyleSheet(theme); @@ -69,8 +74,9 @@ const Image = ({author, iconSize, size, source}: Props) => { const pictureUrl = client.getProfilePictureUrl(author.id, lastPictureUpdate); const imgSource = source ?? {uri: `${serverUrl}${pictureUrl}`}; return ( - diff --git a/app/components/profile_picture/index.tsx b/app/components/profile_picture/index.tsx index 794eb04e5..b0383c9ac 100644 --- a/app/components/profile_picture/index.tsx +++ b/app/components/profile_picture/index.tsx @@ -22,6 +22,7 @@ const STATUS_BUFFER = Platform.select({ type ProfilePictureProps = { author?: UserModel | UserProfile; + forwardRef?: React.RefObject; iconSize?: number; showStatus?: boolean; size: number; @@ -60,6 +61,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { const ProfilePicture = ({ author, + forwardRef, iconSize, showStatus = true, size = 64, @@ -105,6 +107,7 @@ const ProfilePicture = ({ > {userElement} + {Boolean(channelName) && + } ); }; diff --git a/app/screens/gallery/footer/footer.tsx b/app/screens/gallery/footer/footer.tsx index 6dd501e7a..a9c1c74d1 100644 --- a/app/screens/gallery/footer/footer.tsx +++ b/app/screens/gallery/footer/footer.tsx @@ -77,7 +77,9 @@ const Footer = ({ } let userDisplayName; - if (enablePostUsernameOverride && post?.props?.override_username) { + if (item.type === 'avatar') { + userDisplayName = item.name; + } else if (enablePostUsernameOverride && post?.props?.override_username) { userDisplayName = post.props.override_username as string; } else { userDisplayName = displayUsername(author, undefined, teammateNameDisplay); @@ -124,12 +126,14 @@ const Footer = ({ } + {item.type !== 'avatar' && + }
( })} - {target.type !== 'image' && typeof renderItem === 'function' ? ( - renderItem({ - source: imageSource, - width: targetWidth.value, - height: targetHeight.value, - itemStyles, - }) - ) : ( - - )} + { + target.type !== 'image' && + target.type !== 'avatar' && + typeof renderItem === 'function' ? ( + renderItem({ + source: imageSource, + width: targetWidth.value, + height: targetHeight.value, + itemStyles, + }) + ) : ( + + ) + } ; user: UserModel; userIconOverride?: string; } @@ -25,11 +30,12 @@ const styles = StyleSheet.create({ }, }); -const UserProfileAvatar = ({enablePostIconOverride, user, userIconOverride}: Props) => { +const UserProfileAvatar = ({enablePostIconOverride, forwardRef, user, userIconOverride}: Props) => { if (enablePostIconOverride && userIconOverride) { return ( - @@ -40,6 +46,7 @@ const UserProfileAvatar = ({enablePostIconOverride, user, userIconOverride}: Pro return ( { + const galleryIdentifier = `${user.id}-avatarPreview`; const intl = useIntl(); const isTablet = useIsTablet(); const theme = useTheme(); + const serverUrl = useServerUrl(); const styles = getStyleSheet(theme); const override = enablePostUsernameOverride && usernameOverride; - let displayName; + let displayName: string; if (override) { displayName = usernameOverride; } else { displayName = displayUsername(user, intl.locale, teammateDisplayName, false); } + const onPress = () => { + let imageUrl: string|undefined; + if (enablePostIconOverride && userIconOverride) { + imageUrl = userIconOverride; + } else { + try { + const client = NetworkManager.getClient(serverUrl); + const lastPictureUpdate = user.isBot ? (user.props?.bot_last_icon_update || 0) : user.lastPictureUpdate; + const pictureUrl = client.getProfilePictureUrl(user.id, lastPictureUpdate); + imageUrl = `${serverUrl}${pictureUrl}`; + } catch { + // handle below that the client is not set + } + } + + if (imageUrl) { + const item: GalleryItemType = { + id: user.id, + uri: imageUrl, + width: 400, + height: 400, + name: displayName, + mime_type: 'images/png', + authorId: user.id, + type: 'avatar', + }; + openGalleryAtIndex(galleryIdentifier, 0, [item]); + } + }; + + const {ref, onGestureEvent, styles: galleryStyles} = useGalleryItem( + galleryIdentifier, + 0, + onPress, + ); + const hideUsername = override || (displayName && displayName === user.username); const prefix = hideUsername ? '@' : ''; return ( - + + + + + + + = ( ) => void; type GalleryItemType = { - type: 'image' | 'video' | 'file'; + type: 'image' | 'video' | 'file' | 'avatar'; id: string; width: number; height: number;