Skip to content

Commit 47fffaf

Browse files
committed
Pull latest changes
2 parents ed40c1d + 88766ac commit 47fffaf

29 files changed

+406
-302
lines changed

android/app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ android {
150150
minSdkVersion rootProject.ext.minSdkVersion
151151
targetSdkVersion rootProject.ext.targetSdkVersion
152152
multiDexEnabled rootProject.ext.multiDexEnabled
153-
versionCode 1001010804
154-
versionName "1.1.8-4"
153+
versionCode 1001010805
154+
versionName "1.1.8-5"
155155
}
156156
splits {
157157
abi {

ios/NewExpensify/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
</dict>
3232
</array>
3333
<key>CFBundleVersion</key>
34-
<string>1.1.8.4</string>
34+
<string>1.1.8.5</string>
3535
<key>ITSAppUsesNonExemptEncryption</key>
3636
<false/>
3737
<key>LSApplicationQueriesSchemes</key>

ios/NewExpensifyTests/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@
1919
<key>CFBundleSignature</key>
2020
<string>????</string>
2121
<key>CFBundleVersion</key>
22-
<string>1.1.8.4</string>
22+
<string>1.1.8.5</string>
2323
</dict>
2424
</plist>

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "new.expensify",
3-
"version": "1.1.8-4",
3+
"version": "1.1.8-5",
44
"author": "Expensify, Inc.",
55
"homepage": "https://new.expensify.com",
66
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

src/CONST.js

+1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ const CONST = {
213213
SIDEBAR_LOADED: 'sidebar_loaded',
214214
COLD: 'cold',
215215
REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500,
216+
TOOLTIP_SENSE: 1000,
216217
},
217218
PRIORITY_MODE: {
218219
GSD: 'gsd',

src/components/AttachmentView.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ const AttachmentView = (props) => {
6464
</View>
6565
<Text style={[styles.textStrong]}>{props.file && props.file.name}</Text>
6666
{props.shouldShowDownloadIcon && (
67-
<Tooltip text={props.translate('common.download')}>
68-
<View style={styles.ml2}>
67+
<View style={styles.ml2}>
68+
<Tooltip text={props.translate('common.download')}>
6969
<Icon src={Download} />
70-
</View>
71-
</Tooltip>
70+
</Tooltip>
71+
</View>
7272
)}
7373
</View>
7474
);

src/components/AvatarWithImagePicker.js

+11-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize';
1717
import variables from '../styles/variables';
1818
import CONST from '../CONST';
1919
import SpinningIndicatorAnimation from '../styles/animation/SpinningIndicatorAnimation';
20+
import Tooltip from './Tooltip';
2021
import stylePropTypes from '../styles/stylePropTypes';
2122

2223
const propTypes = {
@@ -175,14 +176,16 @@ class AvatarWithImagePicker extends React.Component {
175176
)
176177
: (
177178
<>
178-
<View style={[styles.smallEditIcon, styles.smallAvatarEditIcon]}>
179-
<Icon
180-
src={Camera}
181-
width={variables.iconSizeSmall}
182-
height={variables.iconSizeSmall}
183-
fill={themeColors.iconReversed}
184-
/>
185-
</View>
179+
<Tooltip absolute text={this.props.translate('avatarWithImagePicker.editImage')}>
180+
<View style={[styles.smallEditIcon, styles.smallAvatarEditIcon]}>
181+
<Icon
182+
src={Camera}
183+
width={variables.iconSizeSmall}
184+
height={variables.iconSizeSmall}
185+
fill={themeColors.iconReversed}
186+
/>
187+
</View>
188+
</Tooltip>
186189
<PopoverMenu
187190
isVisible={this.state.isMenuVisible}
188191
onClose={() => this.setState({isMenuVisible: false})}

src/components/FAB/FAB.js

+16-12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {Plus} from '../Icon/Expensicons';
77
import styles, {getAnimatedFABStyle} from '../../styles/styles';
88
import themeColors from '../../styles/themes/default';
99
import fabPropTypes from './fabPropTypes';
10+
import Tooltip from '../Tooltip';
11+
import withLocalize from '../withLocalize';
1012

1113
const AnimatedIcon = Animated.createAnimatedComponent(Icon);
1214
AnimatedIcon.displayName = 'AnimatedIcon';
@@ -58,20 +60,22 @@ class FAB extends PureComponent {
5860
});
5961

6062
return (
61-
<AnimatedPressable
62-
accessibilityLabel={this.props.accessibilityLabel}
63-
accessibilityRole={this.props.accessibilityRole}
64-
onPress={this.props.onPress}
65-
style={[
66-
styles.floatingActionButton,
67-
getAnimatedFABStyle(rotate, backgroundColor),
68-
]}
69-
>
70-
<AnimatedIcon src={Plus} fill={fill} />
71-
</AnimatedPressable>
63+
<Tooltip absolute text={this.props.translate('common.new')}>
64+
<AnimatedPressable
65+
accessibilityLabel={this.props.accessibilityLabel}
66+
accessibilityRole={this.props.accessibilityRole}
67+
onPress={this.props.onPress}
68+
style={[
69+
styles.floatingActionButton,
70+
getAnimatedFABStyle(rotate, backgroundColor),
71+
]}
72+
>
73+
<AnimatedIcon src={Plus} fill={fill} />
74+
</AnimatedPressable>
75+
</Tooltip>
7276
);
7377
}
7478
}
7579

7680
FAB.propTypes = fabPropTypes;
77-
export default FAB;
81+
export default withLocalize(FAB);

src/components/FormAlertWithSubmitButton.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const propTypes = {
1616
/** Whether to show the alert text */
1717
isAlertVisible: PropTypes.bool.isRequired,
1818

19+
/** Whether the button is disabled */
20+
isDisabled: PropTypes.bool,
21+
1922
/** Submit function */
2023
onSubmit: PropTypes.func.isRequired,
2124

@@ -31,22 +34,29 @@ const propTypes = {
3134
/** Whether message is in html format */
3235
isMessageHtml: PropTypes.bool,
3336

37+
/** Styles for container element */
38+
containerStyles: PropTypes.arrayOf(PropTypes.object),
39+
3440
...withLocalizePropTypes,
3541
};
3642

3743
const defaultProps = {
3844
message: '',
45+
isDisabled: false,
3946
isMessageHtml: false,
47+
containerStyles: [],
4048
};
4149

4250
const FormAlertWithSubmitButton = ({
4351
isAlertVisible,
52+
isDisabled,
4453
onSubmit,
4554
buttonText,
4655
translate,
4756
onFixTheErrorsLinkPressed,
4857
message,
4958
isMessageHtml,
59+
containerStyles,
5060
}) => {
5161
/**
5262
* @returns {React.Component}
@@ -91,7 +101,7 @@ const FormAlertWithSubmitButton = ({
91101
}
92102

93103
return (
94-
<View style={[styles.mh5, styles.mb5, styles.flex1, styles.justifyContentEnd]}>
104+
<View style={[styles.mh5, styles.mb5, styles.flex1, styles.justifyContentEnd, ...containerStyles]}>
95105
{isAlertVisible && (
96106
<View style={[styles.flexRow, styles.alignItemsCenter, styles.mb3]}>
97107
<Icon src={Exclamation} fill={colors.red} />
@@ -100,9 +110,10 @@ const FormAlertWithSubmitButton = ({
100110
)}
101111
<Button
102112
success
113+
pressOnEnter
103114
text={buttonText}
104115
onPress={onSubmit}
105-
pressOnEnter
116+
isDisabled={isDisabled}
106117
/>
107118
</View>
108119
);
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import _ from 'underscore';
2+
import CONST from '../../CONST';
3+
4+
let active = false;
5+
6+
/**
7+
* Debounced function to deactive the TooltipSense after a specific time
8+
*/
9+
const debouncedDeactivate = _.debounce(() => {
10+
active = false;
11+
}, CONST.TIMING.TOOLTIP_SENSE);
12+
13+
function activate() {
14+
active = true;
15+
debouncedDeactivate.cancel();
16+
}
17+
18+
function deactivate() {
19+
return debouncedDeactivate();
20+
}
21+
22+
function isActive() {
23+
return active === true;
24+
}
25+
26+
export default {
27+
activate,
28+
deactivate,
29+
isActive,
30+
};

src/components/Tooltip/index.js

+29-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import TooltipRenderedOnPageBody from './TooltipRenderedOnPageBody';
55
import Hoverable from '../Hoverable';
66
import withWindowDimensions from '../withWindowDimensions';
77
import {propTypes, defaultProps} from './TooltipPropTypes';
8+
import TooltipSense from './TooltipSense';
89

910
class Tooltip extends PureComponent {
1011
constructor(props) {
@@ -36,6 +37,9 @@ class Tooltip extends PureComponent {
3637
this.tooltip = null;
3738

3839
this.isComponentMounted = false;
40+
41+
// Whether the tooltip is first tooltip to activate the TooltipSense
42+
this.isTooltipSenseInitiator = false;
3943
this.shouldStartShowAnimation = false;
4044
this.animation = new Animated.Value(0);
4145

@@ -131,12 +135,19 @@ class Tooltip extends PureComponent {
131135
// We may need this check due to the reason that the animation start will fire async
132136
// and hideTooltip could fire before it thus keeping the Tooltip visible
133137
if (this.shouldStartShowAnimation) {
134-
Animated.timing(this.animation, {
135-
toValue: 1,
136-
duration: 140,
137-
delay: 500,
138-
useNativeDriver: false,
139-
}).start();
138+
// When TooltipSense is active, immediately show the tooltip
139+
if (TooltipSense.isActive()) {
140+
this.animation.setValue(1);
141+
} else {
142+
this.isTooltipSenseInitiator = true;
143+
Animated.timing(this.animation, {
144+
toValue: 1,
145+
duration: 140,
146+
delay: 500,
147+
useNativeDriver: false,
148+
}).start();
149+
}
150+
TooltipSense.activate();
140151
}
141152
});
142153
}
@@ -147,11 +158,18 @@ class Tooltip extends PureComponent {
147158
hideTooltip() {
148159
this.animation.stopAnimation();
149160
this.shouldStartShowAnimation = false;
150-
Animated.timing(this.animation, {
151-
toValue: 0,
152-
duration: 140,
153-
useNativeDriver: false,
154-
}).start();
161+
if (TooltipSense.isActive() && !this.isTooltipSenseInitiator) {
162+
this.animation.setValue(0);
163+
} else {
164+
// Hide the first tooltip which initiated the TooltipSense with animation
165+
this.isTooltipSenseInitiator = false;
166+
Animated.timing(this.animation, {
167+
toValue: 0,
168+
duration: 140,
169+
useNativeDriver: false,
170+
}).start();
171+
}
172+
TooltipSense.deactivate();
155173
}
156174

157175
render() {

src/languages/en.js

+4-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default {
88
attachment: 'Attachment',
99
to: 'To',
1010
optional: 'Optional',
11-
new: 'NEW',
11+
new: 'New',
1212
search: 'Search',
1313
next: 'Next',
1414
goBack: 'Go back',
@@ -272,7 +272,7 @@ export default {
272272
changingYourPasswordPrompt: 'Changing your password will update your password for both your Expensify.com\nand New Expensify accounts.',
273273
currentPassword: 'Current password',
274274
newPassword: 'New password',
275-
newPasswordPrompt: 'New password must be different than your old password, have at least 8 characters,\n1 capital letter, 1 lowercase letter, 1 number.',
275+
newPasswordPrompt: 'New password must be different than your old password, have at least 8 characters,\n1 capital letter, 1 lowercase letter, and 1 number.',
276276
confirmNewPassword: 'Confirm new password',
277277
},
278278
addPayPalMePage: {
@@ -399,7 +399,7 @@ export default {
399399
confirmNewPassword: 'Confirm the password',
400400
setPassword: 'Set password',
401401
passwordsDontMatch: 'Passwords must match',
402-
newPasswordPrompt: 'Your password must have at least 8 characters,\n1 capital letter, 1 lowercase letter, 1 number.',
402+
newPasswordPrompt: 'Your password must have at least 8 characters,\n1 capital letter, 1 lowercase letter, and 1 number.',
403403
passwordFormTitle: 'Welcome back to the New Expensify! Please set your password.',
404404
passwordNotSet: 'We were unable to set your new password correctly.',
405405
accountNotValidated: 'We were unable to validate your account. The validation code may have expired.',
@@ -702,14 +702,9 @@ export default {
702702
},
703703
invite: {
704704
invitePeople: 'Invite new members',
705-
invitePeoplePrompt: 'Invite new members to your workspace.',
706705
personalMessagePrompt: 'Add a personal message (optional)',
707-
enterEmailOrPhone: 'Emails or phone numbers',
708-
EmailOrPhonePlaceholder: 'Enter comma-separated list of emails or phone numbers',
709-
pleaseEnterValidLogin: 'Please ensure the email or phone number is valid (e.g. +15005550006).',
710-
pleaseEnterUniqueLogin: 'That user is already a member of this workspace.',
706+
pleaseSelectUser: 'Please select a user from contacts.',
711707
genericFailureMessage: 'An error occurred inviting the user to the workspace, please try again.',
712-
systemUserError: ({email}) => `Sorry, you cannot invite ${email} to a workspace.`,
713708
welcomeNote: ({workspaceName}) => `You have been invited to ${workspaceName}! Download the Expensify mobile app to start tracking your expenses.`,
714709
},
715710
editor: {

src/languages/es.js

+4-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default {
88
attachment: 'Archivo adjunto',
99
to: 'A',
1010
optional: 'Opcional',
11-
new: 'NUEVO',
11+
new: 'Nuevo',
1212
search: 'Buscar',
1313
next: 'Siguiente',
1414
goBack: 'Regresar',
@@ -272,7 +272,7 @@ export default {
272272
changingYourPasswordPrompt: 'El cambio de contraseña va a afectar tanto a la cuenta de Expensify.com\ncomo la de Nuevo Expensify.',
273273
currentPassword: 'Contraseña actual',
274274
newPassword: 'Nueva contraseña',
275-
newPasswordPrompt: 'La nueva contraseña tiene que ser diferente de la antigua, tener al menos 8 letras,\n1 letra mayúscula, 1 letra minúscula y 1 número.',
275+
newPasswordPrompt: 'La nueva contraseña debe ser diferente de la antigua, tener al menos 8 caracteres,\n1 letra mayúscula, 1 letra minúscula y 1 número.',
276276
confirmNewPassword: 'Confirma la nueva contraseña',
277277
},
278278
addPayPalMePage: {
@@ -399,7 +399,7 @@ export default {
399399
confirmNewPassword: 'Confirma la contraseña',
400400
setPassword: 'Configura tu contraseña',
401401
passwordsDontMatch: 'Las contraseñas deben coincidir',
402-
newPasswordPrompt: 'Su contraseña debe tener al menos 8 caracteres, \n1 letra mayúscula, 1 letra minúscula, 1 número.',
402+
newPasswordPrompt: 'La contraseña debe tener al menos 8 caracteres, \n1 letra mayúscula, 1 letra minúscula y 1 número.',
403403
passwordFormTitle: '¡Bienvenido de vuelta al Nuevo Expensify! Por favor, elige una contraseña.',
404404
passwordNotSet: 'No pudimos establecer to contaseña correctamente.',
405405
accountNotValidated: 'No pudimos validar tu cuenta. Es posible que el enlace de validación haya caducado.',
@@ -704,14 +704,9 @@ export default {
704704
},
705705
invite: {
706706
invitePeople: 'Invitar nuevos miembros',
707-
invitePeoplePrompt: 'Invita nuevos miembros a tu espacio de trabajo.',
708707
personalMessagePrompt: 'Agregar un mensaje personal (Opcional)',
709-
enterEmailOrPhone: 'Correos electrónicos o números de teléfono',
710-
EmailOrPhonePlaceholder: 'Introduce una lista de correos electrónicos o números de teléfono separado por comas',
711-
pleaseEnterValidLogin: 'Asegúrese de que el correo electrónico o el número de teléfono sean válidos (e.g. +15005550006).',
712-
pleaseEnterUniqueLogin: 'Ese usuario ya es miembro de este espacio de trabajo.',
708+
pleaseSelectUser: 'Asegúrese de que el correo electrónico o el número de teléfono sean válidos (e.g. +15005550006).',
713709
genericFailureMessage: 'Se produjo un error al invitar al usuario al espacio de trabajo. Vuelva a intentarlo..',
714-
systemUserError: ({email}) => `Lo sentimos, no puedes invitar a ${email} a un espacio de trabajo.`,
715710
welcomeNote: ({workspaceName}) => `¡Has sido invitado a ${workspaceName}! Descargue la aplicación móvil Expensify para comenzar a rastrear sus gastos.`,
716711
},
717712
editor: {

src/libs/Navigation/CustomActions.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,5 @@ function pushDrawerRoute(screenName, params, navigationRef) {
8888

8989
export default {
9090
pushDrawerRoute,
91-
navigateBackToDrawer: navigateBackToRootDrawer,
91+
navigateBackToRootDrawer,
9292
};

0 commit comments

Comments
 (0)