forked from Expensify/App
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into fix/20759-remove-new-notifiers-when-deleting…
…-last-message
- Loading branch information
Showing
14 changed files
with
316 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,20 @@ | ||
--- | ||
title: Expensify Referral Program | ||
description: using joining links to track them, we'll pay referrers if their referral adopts Expensify. | ||
description: Send your joining link, submit a receipt or invoice, and we'll pay you if your referral adopts Expensify. | ||
--- | ||
<!-- The lines above are required by Jekyll to process the .md file --> | ||
|
||
# About | ||
|
||
Expensify has grown thanks to our users who love Expensify so much that they tell their friends, colleagues, managers, and fellow business founders to use it, too. This is how we’ve acquired more customers than all other expense management companies combined. | ||
Expensify has grown thanks to our users who love Expensify so much that they tell their friends, colleagues, managers, and fellow business founders to use it, too. | ||
|
||
As a thank you, every time you bring a new user into the platform who directly or indirectly leads to the adoption of a paid annual plan on Expensify, you will earn $250. | ||
|
||
# How-to get paid for referring people to Expensify | ||
# How to get paid for referring people to Expensify | ||
|
||
1. Submit a report or invoice, or share your referral link with anyone you know who is spending too much time on expenses, or works at a company that could benefit from using Expensify. | ||
|
||
2. You’ll get $250 for any referred business that commits to an annual subscription, has 2 or more active users, and makes two monthly payments. | ||
2. You will get $250 for any referred business that commits to an annual subscription, has 2 or more active users, and makes two monthly payments. | ||
|
||
That’s right! You can refer anyone working at any company you know. | ||
|
||
|
@@ -50,4 +50,4 @@ Please send a message to [email protected] with the billing owner of the c | |
|
||
Expensify members who are opted-in for our newsletters will have received an email containing their unique referral link. | ||
|
||
On the mobile app, go to Settings > Invite a Friend > Share Invite Link to retrieve your referral link. | ||
On the mobile app, go to **Settings** > **Invite a Friend** > **Share Invite Link** to retrieve your referral link. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
diff --git a/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js | ||
index 2f48f9e..6418c76 100644 | ||
--- a/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js | ||
+++ b/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js | ||
@@ -65,6 +65,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> { | ||
_subscriptions: Array<EventSubscription> = []; | ||
viewRef: {current: React.ElementRef<typeof View> | null, ...}; | ||
_initialFrameHeight: number = 0; | ||
+ _bottom: number = 0; | ||
|
||
constructor(props: Props) { | ||
super(props); | ||
@@ -107,18 +108,20 @@ class KeyboardAvoidingView extends React.Component<Props, State> { | ||
|
||
_onKeyboardChange = (event: ?KeyboardEvent) => { | ||
this._keyboardEvent = event; | ||
+ // $FlowFixMe[unused-promise] | ||
this._updateBottomIfNecessary(); | ||
}; | ||
|
||
_onLayout = async (event: ViewLayoutEvent) => { | ||
- const wasFrameNull = this._frame == null; | ||
+ const oldFrame = this._frame; | ||
this._frame = event.nativeEvent.layout; | ||
if (!this._initialFrameHeight) { | ||
// save the initial frame height, before the keyboard is visible | ||
this._initialFrameHeight = this._frame.height; | ||
} | ||
|
||
- if (wasFrameNull) { | ||
+ // update bottom height for the first time or when the height is changed | ||
+ if (!oldFrame || oldFrame.height !== this._frame.height) { | ||
await this._updateBottomIfNecessary(); | ||
} | ||
|
||
@@ -127,20 +130,31 @@ class KeyboardAvoidingView extends React.Component<Props, State> { | ||
} | ||
}; | ||
|
||
+ // Avoid unnecessary renders if the KeyboardAvoidingView is disabled. | ||
+ _setBottom = (value: number) => { | ||
+ const {enabled = true} = this.props; | ||
+ this._bottom = value; | ||
+ if (enabled) { | ||
+ this.setState({bottom: value}); | ||
+ } | ||
+ }; | ||
+ | ||
_updateBottomIfNecessary = async () => { | ||
if (this._keyboardEvent == null) { | ||
- this.setState({bottom: 0}); | ||
+ this._setBottom(0); | ||
return; | ||
} | ||
|
||
const {duration, easing, endCoordinates} = this._keyboardEvent; | ||
const height = await this._relativeKeyboardHeight(endCoordinates); | ||
|
||
- if (this.state.bottom === height) { | ||
+ if (this._bottom === height) { | ||
return; | ||
} | ||
|
||
- if (duration && easing) { | ||
+ this._setBottom(height); | ||
+ | ||
+ if (enabled && duration && easing) { | ||
LayoutAnimation.configureNext({ | ||
// We have to pass the duration equal to minimal accepted duration defined here: RCTLayoutAnimation.m | ||
duration: duration > 10 ? duration : 10, | ||
@@ -150,9 +164,15 @@ class KeyboardAvoidingView extends React.Component<Props, State> { | ||
}, | ||
}); | ||
} | ||
- this.setState({bottom: height}); | ||
}; | ||
|
||
+ componentDidUpdate(_: Props, prevState: State): void { | ||
+ const {enabled = true} = this.props; | ||
+ if (enabled && this._bottom !== prevState.bottom) { | ||
+ this.setState({bottom: this._bottom}); | ||
+ } | ||
+ } | ||
+ | ||
componentDidMount(): void { | ||
if (Platform.OS === 'ios') { | ||
this._subscriptions = [ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* Focus a multiline text input and place the cursor at the end of the value (if there is a value in the input). | ||
* | ||
* When a multiline input contains a text value that goes beyond the scroll height, the cursor will be placed | ||
* at the end of the text value, and automatically scroll the input field to this position after the field gains | ||
* focus. This provides a better user experience in cases where the text in the field has to be edited. The auto- | ||
* scroll behaviour works on all platforms except iOS native. | ||
* See https://github.com/Expensify/App/issues/20836 for more details. | ||
* | ||
* @param {Object} input the input element | ||
*/ | ||
export default function focusAndUpdateMultilineInputRange(input) { | ||
if (!input) { | ||
return; | ||
} | ||
|
||
input.focus(); | ||
if (input.value && input.setSelectionRange) { | ||
const length = input.value.length; | ||
input.setSelectionRange(length, length); | ||
// eslint-disable-next-line no-param-reassign | ||
input.scrollTop = input.scrollHeight; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.