From b2e7a9056547ae1f0a7cf4132ee197f0b76a7375 Mon Sep 17 00:00:00 2001 From: Aryan Goharzad Date: Tue, 31 Jan 2023 13:07:06 -0500 Subject: [PATCH] Replaces the alert with dropdown for profile image and banner (#123) * replaces the alert with dropdown for profile image and banner * lint --- src/view/com/util/UserAvatar.tsx | 97 +++++++++++++--------- src/view/com/util/UserBanner.tsx | 84 +++++++++++-------- src/view/com/util/forms/DropdownButton.tsx | 19 +++-- 3 files changed, 118 insertions(+), 82 deletions(-) diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx index e88affec04..bc74c300ed 100644 --- a/src/view/com/util/UserAvatar.tsx +++ b/src/view/com/util/UserAvatar.tsx @@ -1,5 +1,5 @@ -import React, {useCallback} from 'react' -import {Alert, Image, StyleSheet, TouchableOpacity, View} from 'react-native' +import React from 'react' +import {Image, StyleSheet, View} from 'react-native' import Svg, {Circle, Text, Defs, LinearGradient, Stop} from 'react-native-svg' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import { @@ -9,6 +9,7 @@ import { Image as PickedImage, } from 'react-native-image-crop-picker' import {colors, gradients} from '../../lib/styles' +import {DropdownButton} from './forms/DropdownButton' export function UserAvatar({ size, @@ -25,43 +26,6 @@ export function UserAvatar({ }) { const initials = getInitials(displayName || handle) - const handleEditAvatar = useCallback(() => { - Alert.alert('Select upload method', '', [ - { - text: 'Take a new photo', - onPress: () => { - openCamera({ - mediaType: 'photo', - cropping: true, - width: 2000, - height: 2000, - cropperCircleOverlay: true, - forceJpg: true, // ios only - compressImageQuality: 1, - }).then(onSelectNewAvatar) - }, - }, - { - text: 'Select from gallery', - onPress: () => { - openPicker({ - mediaType: 'photo', - }).then(async item => { - await openCropper({ - mediaType: 'photo', - path: item.path, - width: 2000, - height: 2000, - cropperCircleOverlay: true, - forceJpg: true, // ios only - compressImageQuality: 1, - }).then(onSelectNewAvatar) - }) - }, - }, - ]) - }, [onSelectNewAvatar]) - const renderSvg = (svgSize: number, svgInitials: string) => ( @@ -83,9 +47,60 @@ export function UserAvatar({ ) + const dropdownItems = [ + { + label: 'Camera', + icon: 'camera', + // TODO: dark mode icon + onPress: () => { + openCamera({ + mediaType: 'photo', + cropping: true, + width: 2000, + height: 2000, + cropperCircleOverlay: true, + forceJpg: true, // ios only + compressImageQuality: 1, + }).then(onSelectNewAvatar) + }, + }, + { + label: 'Library', + icon: 'image', + onPress: () => { + openPicker({ + mediaType: 'photo', + }).then(async item => { + await openCropper({ + mediaType: 'photo', + path: item.path, + width: 2000, + height: 2000, + cropperCircleOverlay: true, + forceJpg: true, // ios only + compressImageQuality: 1, + }).then(onSelectNewAvatar) + }) + }, + }, + // TODO: Remove avatar https://github.com/bluesky-social/social-app/issues/122 + // { + // label: 'Remove', + // icon: ['far', 'trash-can'], + // onPress: () => { + // // Remove avatar API call + // }, + // }, + ] // onSelectNewAvatar is only passed as prop on the EditProfile component return onSelectNewAvatar ? ( - + {avatar ? ( - + ) : avatar ? ( void }) { - const handleEditBanner = useCallback(() => { - Alert.alert('Select upload method', '', [ - { - text: 'Take a new photo', - onPress: () => { - openCamera({ + const dropdownItems = [ + { + label: 'Camera', + icon: 'camera', + // TODO: Add darkmode support https://github.com/bluesky-social/social-app/issues/78 + onPress: () => { + openCamera({ + mediaType: 'photo', + cropping: true, + compressImageMaxWidth: 6000, + width: 6000, + compressImageMaxHeight: 2000, + height: 2000, + forceJpg: true, // ios only + compressImageQuality: 1, + includeExif: true, + }).then(onSelectNewBanner) + }, + }, + { + label: 'Library', + icon: 'image', + onPress: () => { + openPicker({ + mediaType: 'photo', + }).then(async item => { + await openCropper({ mediaType: 'photo', - cropping: true, + path: item.path, compressImageMaxWidth: 6000, width: 6000, compressImageMaxHeight: 2000, @@ -33,30 +55,18 @@ export function UserBanner({ compressImageQuality: 1, includeExif: true, }).then(onSelectNewBanner) - }, + }) }, - { - text: 'Select from gallery', - onPress: () => { - openPicker({ - mediaType: 'photo', - }).then(async item => { - await openCropper({ - mediaType: 'photo', - path: item.path, - compressImageMaxWidth: 6000, - width: 6000, - compressImageMaxHeight: 2000, - height: 2000, - forceJpg: true, // ios only - compressImageQuality: 1, - includeExif: true, - }).then(onSelectNewBanner) - }) - }, - }, - ]) - }, [onSelectNewBanner]) + }, + // TODO: Remove banner https://github.com/bluesky-social/social-app/issues/122 + // { + // label: 'Remove', + // icon: ['far', 'trash-can'], + // onPress: () => { + // // Remove banner api call + // }, + // }, + ] const renderSvg = () => ( @@ -77,7 +87,13 @@ export function UserBanner({ // setUserBanner is only passed as prop on the EditProfile component return onSelectNewBanner ? ( - + {banner ? ( ) : ( @@ -90,7 +106,7 @@ export function UserBanner({ style={{color: colors.white}} /> - + ) : banner ? ( @@ -43,6 +46,9 @@ export function DropdownButton({ label?: string menuWidth?: number children?: React.ReactNode + openToRight?: boolean + rightOffset?: number + bottomOffset?: number }) { const ref = useRef(null) @@ -59,12 +65,11 @@ export function DropdownButton({ if (!menuWidth) { menuWidth = 200 } - createDropdownMenu( - pageX + width - menuWidth, - pageY + height, - menuWidth, - items, - ) + const newX = openToRight + ? pageX + width + rightOffset + : pageX + width - menuWidth + const newY = pageY + height + bottomOffset + createDropdownMenu(newX, newY, menuWidth, items) }, ) } @@ -184,7 +189,7 @@ function createDropdownMenu( {items.map((item, index) => ( onPressItem(index)}> {item.icon && (