Skip to content

Commit 78759b5

Browse files
committed
Merge branch 'main' into perf/improve-MentionUserRenderer
2 parents 65648a3 + 538e440 commit 78759b5

253 files changed

Lines changed: 3594 additions & 1611 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintrc.changed.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module.exports = {
88
'deprecation/deprecation': 'error',
99
'rulesdir/no-default-id-values': 'error',
1010
'rulesdir/provide-canBeMissing-in-useOnyx': 'error',
11+
'rulesdir/no-unstable-hook-defaults': 'error',
1112
'no-restricted-syntax': [
1213
'error',
1314
{

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ module.exports = {
219219
'es/no-optional-chaining': 'off',
220220
'deprecation/deprecation': 'off',
221221
'arrow-body-style': 'off',
222+
'no-continue': 'off',
222223

223224
// Import specific rules
224225
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],

.github/scripts/buildActions.sh

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,21 @@ for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do
4949
ASYNC_BUILDS[i]=$!
5050
done
5151

52+
EXIT_CODE=0
5253
for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do
5354
ACTION=${GITHUB_ACTIONS[$i]}
5455
ACTION_DIR=$(dirname "$ACTION")
56+
ACTION_NAME=$(basename "$ACTION" .ts)
5557

5658
# Wait for the background build to finish
57-
wait "${ASYNC_BUILDS[$i]}"
58-
59-
# Prepend the warning note to the top of the compiled file
60-
OUTPUT_FILE="$ACTION_DIR/index.js"
61-
echo "$NOTE_DONT_EDIT$(cat "$OUTPUT_FILE")" > "$OUTPUT_FILE"
59+
if wait "${ASYNC_BUILDS[$i]}"; then
60+
# Prepend the warning note to the top of the compiled file
61+
OUTPUT_FILE="$ACTION_DIR/index.js"
62+
echo "$NOTE_DONT_EDIT$(cat "$OUTPUT_FILE")" > "$OUTPUT_FILE"
63+
else
64+
echo "$ACTION_NAME failed to build: $ACTION_DIR/index.js" >&2
65+
EXIT_CODE=1
66+
fi
6267
done
68+
69+
exit $EXIT_CODE

.storybook/preview.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import React from 'react';
33
import Onyx from 'react-native-onyx';
44
import {SafeAreaProvider} from 'react-native-safe-area-context';
55
import type {Parameters} from 'storybook/internal/types';
6+
import OnyxListItemProvider from '@components/OnyxListItemProvider';
67
import {SearchContextProvider} from '@components/Search/SearchContext';
78
import ComposeProviders from '@src/components/ComposeProviders';
89
import HTMLEngineProvider from '@src/components/HTMLEngineProvider';
910
import {LocaleContextProvider} from '@src/components/LocaleContextProvider';
10-
import OnyxProvider from '@src/components/OnyxProvider';
1111
import {EnvironmentProvider} from '@src/components/withEnvironment';
1212
import {KeyboardStateProvider} from '@src/components/withKeyboardState';
1313
import ONYXKEYS from '@src/ONYXKEYS';
@@ -23,7 +23,16 @@ Onyx.init({
2323
const decorators = [
2424
(Story: React.ElementType) => (
2525
<ComposeProviders
26-
components={[OnyxProvider, LocaleContextProvider, HTMLEngineProvider, SafeAreaProvider, PortalProvider, EnvironmentProvider, KeyboardStateProvider, SearchContextProvider]}
26+
components={[
27+
OnyxListItemProvider,
28+
LocaleContextProvider,
29+
HTMLEngineProvider,
30+
SafeAreaProvider,
31+
PortalProvider,
32+
EnvironmentProvider,
33+
KeyboardStateProvider,
34+
SearchContextProvider,
35+
]}
2736
>
2837
<Story />
2938
</ComposeProviders>

Mobile-Expensify

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ android {
114114
minSdkVersion rootProject.ext.minSdkVersion
115115
targetSdkVersion rootProject.ext.targetSdkVersion
116116
multiDexEnabled rootProject.ext.multiDexEnabled
117-
versionCode 1009018106
118-
versionName "9.1.81-6"
117+
versionCode 1009018202
118+
versionName "9.1.82-2"
119119
// Supported language variants must be declared here to avoid from being removed during the compilation.
120120
// This also helps us to not include unnecessary language variants in the APK.
121121
resConfigs "en", "es"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Mentions highlighting in Composer input and chat messages
2+
3+
## Glossary
4+
**Full mention** - called more simply `userMention` is the full email of a user. In Expensify app _every_ correct full email gets highlighted in text.
5+
When parsed via ExpensiMark into html, this mention is described with tag `<mention-user>`.
6+
#### Examples of user mentions: `@john.doe@company.org`, `@vit@expensify.com`
7+
8+
**Short mention** - a special type of mention that contains only the login part of a user email **AND** the email domain has to be the same as our email domain. Any other `@mention` will not get highlighted if domains don't match
9+
When parsed via ExpensiMark into html, it is described with tag `<mention-short>`.
10+
11+
#### Examples of short mentions:
12+
- `@vit` - **IF** my domain is `expensify.com` **AND** there exists a user with email `vit@expensify.com` - it will get highlighted ✅
13+
- `@mateusz` - **IF** my domain is `expensify.com` **AND** there is **NO** user with email `mateusz@expensify.com`, but there is for example `mateusz@company.org` - it will NOT get highlighted ❌
14+
15+
**ExpensiMark** - parser that we are using, which allows for parsing between markdown <---> html formats. Imported from `expensify-common` package.
16+
17+
## tl;dr - the most important part
18+
- there are 2 slightly different flows of handling mentions - one is inside the Composer Input and the other outside of it
19+
- both are complex and need to support both userMentions and shortMentions - See **FAQ**
20+
21+
## Parsing mentions inside Composer/Input (LiveMarkdown)
22+
Our `Composer` component uses `react-native-live-markdown` for writing and editing markdown and handling mentions. When discussing how mentions work **inside** the composer input always look for answers in this [library](https://github.com/Expensify/react-native-live-markdown).
23+
24+
### Mention parsing flow in live-markdown
25+
1. User types in some text
26+
2. `RNMarkdownTextInput` will handle the text by calling `parseExpensiMark`, which is an internal function of live-markdown: https://github.com/Expensify/react-native-live-markdown/blob/main/src/parseExpensiMark.ts
27+
3. `parseExpensiMark` will use `ExpensiMark` for parsing, then do several extra operations so that the component can work correctly
28+
4. When `ExpensiMark` parses the text, any full email will get parsed to `<mention-user>...</mention-user>` and any `@phrase` will get parsed to `<mention-short>...</mention-short>`
29+
5. `userMentions` are ready to use as they are so they require no further modification, however for `shortMentions` we need to check if they actually should get the highlighting
30+
5. We use the `parser` prop of `<MarkdownTextInput>` to pass custom parsing logic - this allows us to do some extra processing after `parseExpensiMark` runs.
31+
6. Our custom logic will go over every `<mention-short>` entry and verify if this login is someone that exists in userDetails data, then transform this into a full mention which gets highlighting
32+
33+
**NOTE:** this entire process takes part only "inside" Composer input. This is what happens between user typing in some text and user seeing the markdown/highlights in real time.
34+
35+
## Parsing mentions outside of Composer/Input
36+
When a user types in a message and wants to send it, we need to process the message text and then call the appropriate backend command.
37+
However, backend only accepts text in html format. This means that text payload sent to backend has to be parsed via ExpensiMark. In addition, api **will not** accept `<mention-short>` tag - it only accepts full user mention with email. Frontend needs to process every `shortMention` into a `userMention` or stripping it completely from text.
38+
39+
### Mention processing flow when sending a message
40+
1. After typing in some text user hits ENTER or presses the send button
41+
2. Several functions are called but ultimately `addActions(...)` is the one that will prepare backend payload and make the Api call.
42+
3. The function solely responsible for getting the correctly parsed text is `getParsedComment()` - it should return the string that is safe to send to backend.
43+
4. We **do not** have access to `parseExpensiMark` or any functions that worked in worklets, as we are outside of `live-markdown` but we need to process `shortMentions` regardless.
44+
5. The processing is done in `getParsedMessageWithShortMentions`: we parse via `ExpensiMark` with options very similar to what happens inside `parseExpensiMark` in `live-markdown`. (this is similar to Step 5. from previous flow).
45+
6. We then find every `<mention-short>...</mention-short>` and try to see if the specific mention exists in userDetails data.
46+
47+
## FAQ
48+
### Q: Why can't we simply use `parseExpensiMark` in both cases?!
49+
We cannot call `parseExpensiMark` in both cases, because `parseExpensiMark` returns a special data structure, called `MarkdownRange` which is both created and consumed by `react-native-live-markdown`.
50+
51+
Expensify API only accepts HTML and not markdown range.
52+
53+
Useful graph:
54+
```
55+
ExpensiMark: (raw text with markdown markers) ----> (HTML)
56+
parseExpensiMark: (raw text with markdown markers) ----> MarkdownRange[] structure
57+
```
58+
```
59+
<MarkdownTextInput> accepts MarkdownRange[]
60+
Expensify Api call accepts HTML
61+
```

docs/articles/expensify-classic/expensify-billing/Billing-Overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Collect is perfect for small teams that need an easy way to track receipts and g
3838

3939
## 🌍 Localized Pricing
4040

41-
- Equivalent pricing available in **GBP**, **AUD**, and **NZD**
41+
- Equivalent pricing available in **EUR**, **GBP**, **AUD**, and **NZD**
4242

4343
## 🔄 Flexible Scaling
4444

docs/articles/new-expensify/billing-and-subscriptions/Billing-Overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ For a full breakdown, visit the [Expensify pricing page](https://www.expensify.c
3434

3535
## 🌍 Localized pricing
3636

37-
- Pricing available in **GBP**, **AUD**, and **NZD**
37+
- Pricing available in **EUR**, **GBP**, **AUD**, and **NZD**
3838

3939
## 🔄 Flexible scaling
4040

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
---
2-
title: Update Email Address
3-
description: Add or update contact methods for your Expensify account, including changing your default email.
4-
keywords: [New Expensify, change email, add email, contact method, update default email, account access]
2+
title: Update Contact Methods
3+
description: Add or update contact methods for your Expensify account, including changing your default email or phone number.
4+
keywords: [New Expensify, change email, add email, change phone number, add phone number, contact method, update default email, account access]
55
---
66
<div id="new-expensify" markdown="1">
77

8-
Update or add new email addresses to keep your Expensify account secure and accessible. You can add personal or secondary emails, change your default email, and remove outdated addresses.
8+
Update or add new contact methods to keep your Expensify account secure and accessible. You can add personal or secondary contact methods, change your default contact method, and remove outdated contact methods.
99

1010
---
1111

12-
# Why Add Another Email Address?
12+
# Why Add Another Contact Method?
1313

14-
Adding an additional email helps you:
14+
Adding an additional contact method helps you:
1515

1616
- **Switch your default email** to a new one (e.g., a personal address).
1717
- **Maintain access** if your primary email is tied to an employer domain.
@@ -21,14 +21,13 @@ Adding an additional email helps you:
2121

2222
---
2323

24-
# Add or Change an Email Address
24+
# Add or Change a Contact Method
2525

26-
## On Desktop:
2726
1. In the left-hand menu, click **Account > Profile**.
2827
2. Under **Contact Method**, click **New Contact Method**.
2928
3. Enter the email address or phone number you want to add.
3029
4. Click **Add**.
31-
5. Check your email for a **verification code**, enter it in Expensify, and click **Verify**.
30+
5. Check your email or texts for a **verification code**, enter it in Expensify, and click **Verify**.
3231

3332
After verifying, click any contact method to:
3433
- Set it as your **default**
@@ -39,7 +38,7 @@ After verifying, click any contact method to:
3938

4039
# Important Notes
4140

42-
- You can’t remove your default email until another verified contact method is set as default.
41+
- You can’t remove your default contact method until another verified contact method is set as default.
4342
- You can add multiple contact methods for flexibility when logging in or recovering your account.
4443

4544
</div>

0 commit comments

Comments
 (0)