Skip to content

Commit

Permalink
Merge pull request #24184 from allroundexperts/fix-24183
Browse files Browse the repository at this point in the history
  • Loading branch information
dangrous authored Aug 7, 2023
2 parents 5249d02 + 42bf664 commit 7b13f11
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 191 deletions.
152 changes: 79 additions & 73 deletions src/components/AvatarWithImagePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import * as FileUtils from '../libs/fileDownload/FileUtils';
import getImageResolution from '../libs/fileDownload/getImageResolution';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import DotIndicatorMessage from './DotIndicatorMessage';
import * as Browser from '../libs/Browser';

const propTypes = {
/** Avatar source to display */
Expand Down Expand Up @@ -229,42 +230,24 @@ class AvatarWithImagePicker extends React.Component {
render() {
const DefaultAvatar = this.props.DefaultAvatar;
const additionalStyles = _.isArray(this.props.style) ? this.props.style : [this.props.style];
const menuItems = [
{
icon: Expensicons.Upload,
text: this.props.translate('avatarWithImagePicker.uploadPhoto'),
onSelected: () => {},
},
];

// If current avatar isn't a default avatar, allow Remove Photo option
if (!this.props.isUsingDefaultAvatar) {
menuItems.push({
icon: Expensicons.Trashcan,
text: this.props.translate('avatarWithImagePicker.removePhoto'),
onSelected: () => {
this.setError(null, {});
this.props.onImageRemoved();
},
});
}

return (
<View style={[styles.alignItemsCenter, ...additionalStyles]}>
<PressableWithoutFeedback
onPress={() => this.setState((prev) => ({isMenuVisible: !prev.isMenuVisible}))}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={this.props.translate('avatarWithImagePicker.editImage')}
disabled={this.state.isAvatarCropModalOpen}
>
<View style={[styles.pRelative, styles.avatarLarge]}>
<OfflineWithFeedback
pendingAction={this.props.pendingAction}
errors={this.props.errors}
errorRowStyles={this.props.errorRowStyles}
onClose={this.props.onErrorClose}
>
<Tooltip text={this.props.translate('avatarWithImagePicker.editImage')}>
<View style={[styles.pRelative, styles.avatarLarge]}>
<OfflineWithFeedback
pendingAction={this.props.pendingAction}
errors={this.props.errors}
errorRowStyles={this.props.errorRowStyles}
onClose={this.props.onErrorClose}
>
<Tooltip text={this.props.translate('avatarWithImagePicker.editImage')}>
<PressableWithoutFeedback
onPress={() => this.setState((prev) => ({isMenuVisible: !prev.isMenuVisible}))}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
accessibilityLabel={this.props.translate('avatarWithImagePicker.editImage')}
disabled={this.state.isAvatarCropModalOpen}
ref={this.anchorRef}
>
<View>
{this.props.source ? (
<Avatar
Expand All @@ -279,47 +262,70 @@ class AvatarWithImagePicker extends React.Component {
<DefaultAvatar />
)}
</View>
</Tooltip>
</OfflineWithFeedback>

<AttachmentPicker type={CONST.ATTACHMENT_PICKER_TYPE.IMAGE}>
{({openPicker}) => (
<>
<Tooltip text={this.props.translate('avatarWithImagePicker.editImage')}>
<View style={[styles.smallEditIcon, styles.smallAvatarEditIcon]}>
<Icon
src={Expensicons.Camera}
width={variables.iconSizeSmall}
height={variables.iconSizeSmall}
fill={themeColors.textLight}
/>
</View>
</Tooltip>
<PopoverMenu
isVisible={this.state.isMenuVisible}
onClose={() => this.setState({isMenuVisible: false})}
onItemSelected={(item, index) => {
this.setState({isMenuVisible: false});
// In order for the file picker to open dynamically, the click
// function must be called from within a event handler that was initiated
// by the user.
if (index === 0) {
openPicker({
onPicked: this.showAvatarCropModal,
});
}
}}
menuItems={menuItems}
anchorPosition={this.props.anchorPosition}
withoutOverlay
anchorRef={this.anchorRef}
anchorAlignment={this.props.anchorAlignment}
<View style={[styles.smallEditIcon, styles.smallAvatarEditIcon]}>
<Icon
src={Expensicons.Camera}
width={variables.iconSizeSmall}
height={variables.iconSizeSmall}
fill={themeColors.textLight}
/>
</>
)}
</AttachmentPicker>
</View>
</PressableWithoutFeedback>
</View>
</PressableWithoutFeedback>
</Tooltip>
</OfflineWithFeedback>
<AttachmentPicker type={CONST.ATTACHMENT_PICKER_TYPE.IMAGE}>
{({openPicker}) => {
const menuItems = [
{
icon: Expensicons.Upload,
text: this.props.translate('avatarWithImagePicker.uploadPhoto'),
onSelected: () => {
if (Browser.isSafari()) {
return;
}
openPicker({
onPicked: this.showAvatarCropModal,
});
},
},
];

// If current avatar isn't a default avatar, allow Remove Photo option
if (!this.props.isUsingDefaultAvatar) {
menuItems.push({
icon: Expensicons.Trashcan,
text: this.props.translate('avatarWithImagePicker.removePhoto'),
onSelected: () => {
this.setError(null, {});
this.props.onImageRemoved();
},
});
}
return (
<PopoverMenu
isVisible={this.state.isMenuVisible}
onClose={() => this.setState({isMenuVisible: false})}
onItemSelected={(item, index) => {
this.setState({isMenuVisible: false});
// In order for the file picker to open dynamically, the click
// function must be called from within a event handler that was initiated
// by the user on Safari.
if (index === 0 && Browser.isSafari()) {
openPicker({
onPicked: this.showAvatarCropModal,
});
}
}}
menuItems={menuItems}
anchorPosition={this.props.anchorPosition}
withoutOverlay
anchorRef={this.anchorRef}
anchorAlignment={this.props.anchorAlignment}
/>
);
}}
</AttachmentPicker>
</View>
{this.state.validationError && (
<DotIndicatorMessage
style={[styles.mt6]}
Expand Down
4 changes: 2 additions & 2 deletions src/components/PopoverProvider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ function PopoverContextProvider(props) {
}
closePopover();
};
document.addEventListener('keydown', listener);
document.addEventListener('keydown', listener, true);
return () => {
document.removeEventListener('keydown', listener);
document.removeEventListener('keydown', listener, true);
};
}, [closePopover]);

Expand Down
6 changes: 5 additions & 1 deletion src/libs/Browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ function isMobileChrome() {
return false;
}

function isSafari() {
return false;
}

function openRouteInDesktopApp() {}

export {getBrowser, isMobile, isMobileSafari, isMobileChrome, openRouteInDesktopApp};
export {getBrowser, isMobile, isMobileSafari, isSafari, isMobileChrome, openRouteInDesktopApp};
6 changes: 5 additions & 1 deletion src/libs/Browser/index.web.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ function isMobileChrome() {
return /Android/i.test(userAgent) && /chrome|chromium|crios/i.test(userAgent);
}

function isSafari() {
return getBrowser() === 'safari' || isMobileSafari();
}

/**
* The session information needs to be passed to the Desktop app, and the only way to do that is by using query params. There is no other way to transfer the data.
* @param {String} shortLivedAuthToken
Expand Down Expand Up @@ -100,4 +104,4 @@ function openRouteInDesktopApp(shortLivedAuthToken = '', email = '') {
}
}

export {getBrowser, isMobile, isMobileSafari, isMobileChrome, openRouteInDesktopApp};
export {getBrowser, isMobile, isMobileSafari, isSafari, isMobileChrome, openRouteInDesktopApp};
Loading

0 comments on commit 7b13f11

Please sign in to comment.