Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tooltip to rotate image button and zoom slider #16920

Merged
merged 4 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions src/components/AvatarCropModal/AvatarCropModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Slider from './Slider';
import cropOrRotateImage from '../../libs/cropOrRotateImage';
import HeaderGap from '../HeaderGap';
import * as StyleUtils from '../../styles/StyleUtils';
import Tooltip from '../Tooltip';

const propTypes = {
/** Link to image for cropping */
Expand Down Expand Up @@ -398,14 +399,16 @@ const AvatarCropModal = (props) => {
>
<Slider sliderValue={translateSlider} onGesture={panSliderGestureEventHandler} />
</Pressable>
<Button
medium
icon={Expensicons.Rotate}
iconFill={themeColors.inverse}
iconStyles={[styles.mr0]}
style={[styles.imageCropRotateButton]}
onPress={rotateImage}
/>
<Tooltip text={props.translate('avatarCropModal.rotateImage')} shiftVertical={-2}>
<Button
medium
icon={Expensicons.Rotate}
iconFill={themeColors.inverse}
iconStyles={[styles.mr0]}
style={[styles.imageCropRotateButton]}
onPress={rotateImage}
/>
</Tooltip>
</View>
</>
)}
Expand Down
24 changes: 20 additions & 4 deletions src/components/AvatarCropModal/Slider.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import PropTypes from 'prop-types';
import React from 'react';
import React, {useState} from 'react';
import {View} from 'react-native';
import {PanGestureHandler} from 'react-native-gesture-handler';
import Animated, {useAnimatedStyle} from 'react-native-reanimated';
import styles from '../../styles/styles';
import gestureHandlerPropTypes from './gestureHandlerPropTypes';
import ControlSelection from '../../libs/ControlSelection';
import Tooltip from '../Tooltip';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';

const propTypes = {
/** React-native-reanimated lib handler which executes when the user is panning slider */
onGesture: gestureHandlerPropTypes,

/** X position of the slider knob */
sliderValue: PropTypes.shape({value: PropTypes.number}),

...withLocalizePropTypes,
};

const defaultProps = {
Expand All @@ -22,6 +26,8 @@ const defaultProps = {

// This component can't be written using class since reanimated API uses hooks.
const Slider = (props) => {
const [tooltipIsVisible, setTooltipIsVisible] = useState(true);

// A reanimated memoized style, which tracks
// a translateX shared value and updates the slider position.
const rSliderStyle = useAnimatedStyle(() => ({
Expand All @@ -32,8 +38,18 @@ const Slider = (props) => {
// default behaviour of cursor - I-beam cursor on drag. See https://github.com/Expensify/App/issues/13688
return (
<View ref={ControlSelection.blockElement} style={styles.sliderBar}>
<PanGestureHandler onGestureEvent={props.onGesture}>
<Animated.View style={[styles.sliderKnob, rSliderStyle]} />
<PanGestureHandler
onBegan={() => setTooltipIsVisible(false)}
onEnded={() => setTooltipIsVisible(true)}
onGestureEvent={props.onGesture}
>
<Animated.View style={[styles.sliderKnob, rSliderStyle]}>
{ tooltipIsVisible && (
<Tooltip text={props.translate('avatarCropModal.zoomImage')} shiftVertical={-2}>
<View style={[styles.sliderKnobTooltipView]} />
</Tooltip>
)}
</Animated.View>
</PanGestureHandler>
</View>
);
Expand All @@ -42,4 +58,4 @@ const Slider = (props) => {
Slider.displayName = 'Slider';
Slider.propTypes = propTypes;
Slider.defaultProps = defaultProps;
export default Slider;
export default withLocalize(Slider);
2 changes: 2 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ export default {
avatarCropModal: {
title: 'Edit photo',
description: 'Drag, zoom, and rotate your image to your preferred specifications',
rotateImage: 'Rotate',
zoomImage: 'Zoom',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these two are just the generic words "rotate" and "zoom", can we move these to the common object? (common.rotate and common.zoom).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

},
composer: {
noExtensionFoundForMimeType: 'No extension found for mime type',
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ export default {
avatarCropModal: {
title: 'Editar foto',
description: 'Arrastra, haz zoom y rota tu imagen para que quede como te gusta.',
rotateImage: 'Girar',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rotateImage: 'Girar',
rotateImage: 'Rotar',

Heard back from our people on this translation. Let's use "Rotar".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

zoomImage: 'Zoom',
},
composer: {
noExtensionFoundForMimeType: 'No se encontró una extension para este tipo de contenido',
Expand Down
6 changes: 6 additions & 0 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,12 @@ const styles = {
cursor: 'move',
},

sliderKnobTooltipView: {
height: variables.sliderKnobSize,
width: variables.sliderKnobSize,
borderRadius: variables.sliderKnobSize / 2,
},

sliderKnob: {
backgroundColor: themeColors.success,
position: 'absolute',
Expand Down