Add Expensify.cash to iOS and Android native share menus

### Details
Uses [react-native-share-menu](https://github.com/meedan/react-native-share-menu) to add Expensify.cash to the native share menu on mobile platforms and enables sharing to the app.

Chat selection is made on separate page, which reuses components from Home page. To achieve this I had to modify some sidebar related components and functions, mainly to add callbacks for getting selected chat id.

### Fixed Issues
Fixes #1294

### Tests
1. Open some other app on iOS or Android, for example image gallery or web browser.
2. Activate share menu for the element that needs to be shared.
3. Confirm that Expensify.cash is present in Share menu.
4. Select Expensify.cash.
5. Confirm that Expensify.cash is opened and routes to `Send to...` page.
6. Select or create and select some chat.
7. Confirm that shared item is posted to selected chat.

### Tested On

- [ ] Web
- [ ] Mobile Web
- [ ] Desktop
- [x] iOS
- [x] Android

### Screenshots
#### iOS
https://user-images.githubusercontent.com/130532/106333690-e499d980-6291-11eb-9d99-68ea9473a482.mp4

#### Android
https://user-images.githubusercontent.com/130532/106398712-3327af00-641d-11eb-9106-fe0def954ad9.mp4

[Improvement] Add expensify.cash to iOS and Android native share menus
If you haven’t already, check out our [contributing guidelines](https://github.com/Expensify/ReactNativeChat/blob/master/CONTRIBUTING.md) for onboarding!
___

**Platform - version:**
iOS, Android - All versions

## Problem

A common action when using a mobile device is to share something (a web page, an image, a tweet, etc) with another person. Both iOS and Android have a native "share" button that allows you to share things via apps that you have installed on your phone.

Here's an example of what the native iOS share menu looks like:
![image](https://user-images.githubusercontent.com/1371996/103492514-0fa71f80-4df1-11eb-9eb0-b803669edc9d.png)

## Why is this important?
The native share function is a common flow and one of the easier ways to share something with someone. For example, I find it to be easier than copying the url of a web page from my mobile browser, switching apps, and pasting it in to the messenger app. It's much easier to just hit the share button, choose the messenger app, and select who I want to send the url to.

## Solution
Add support for sharing directly to our app. Here is an [example react native library](https://github.com/meedan/react-native-share-menu) that helps with this, though I haven't done any research into it. I think the way we would implement it is:
1. Expensify.cash shows up as an option in the native share menu
2. When Expensify.cash is selected, we bring up your Expensify.cash home screen (Screenshot is below)
3. You can select a chat
4. Whatever you are sharing (url, image, etc) is sent to that chat

This is very similar to the flow when using the native share functionality with WhatsApp.

Screenshot of Expensify.cash home screen:

![image](https://user-images.githubusercontent.com/5997400/105258369-7bea8880-5b3e-11eb-9949-7f6a9c315784.png)

Upwork Job Link: https://www.upwork.com/jobs/~01fb534e5bfc655563

Is this task still available? I would like to work on this issue.

NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=4096' npx --no-install jest tests/unit/loginTest.js --json --outputFile=/tmp/test-results.json --passWithNoTests 2>&1

diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 68c269fe1bbe..12e96677ec23 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -19,11 +19,18 @@
         android:label="@string/app_name"
         android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
         android:launchMode="singleTask"
+        android:documentLaunchMode="never"
         android:windowSoftInputMode="adjustResize">
         <intent-filter>
             <action android:name="android.intent.action.MAIN" />
             <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
+        <intent-filter>
+            <action android:name="android.intent.action.SEND" />
+            <category android:name="android.intent.category.DEFAULT" />
+            <data android:mimeType="*/*" />
+            <!-- Any other mime types you want to support -->
+        </intent-filter>
       </activity>
       <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
     </application>
diff --git a/ios/ExpensifyCash.xcodeproj/project.pbxproj b/ios/ExpensifyCash.xcodeproj/project.pbxproj
index 1cce13f3aa8e..dc707d8df42e 100644
--- a/ios/ExpensifyCash.xcodeproj/project.pbxproj
+++ b/ios/ExpensifyCash.xcodeproj/project.pbxproj
@@ -23,6 +23,10 @@
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		8821A238A081483FA947BC4E /* GTAmericaExp-RgIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 918D7FEFF96242E6B5F5E14D /* GTAmericaExp-RgIt.otf */; };
 		8C86654500DCC843A74147B5 /* libPods-ExpensifyCash-ExpensifyCashTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2AB27DDDFCCE3CD100EA0C /* libPods-ExpensifyCash-ExpensifyCashTests.a */; };
+		9842B1200DD5443D16989CD2 /* libPods-ShareExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 981BE962FCA2842553D2AA78 /* libPods-ShareExtension.a */; };
+		B23ED19125C1A46900CA34C5 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B23ED18F25C1A46900CA34C5 /* MainInterface.storyboard */; };
+		B23ED19525C1A46900CA34C5 /* ShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = B23ED18B25C1A46900CA34C5 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+		B2E844AF25C3A34300909139 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E844AE25C3A34300909139 /* ShareViewController.swift */; };
 		BB6CECBDA023256B6B955321 /* libPods-ExpensifyCash.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F2C8BDCC1FF0B64AE2DFC9B /* libPods-ExpensifyCash.a */; };
 		E9DF872D2525201700607FDC /* AirshipConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = E9DF872C2525201700607FDC /* AirshipConfig.plist */; };
 /* End PBXBuildFile section */
@@ -35,8 +39,29 @@
 			remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
 			remoteInfo = ExpensifyCash;
 		};
+		B23ED19325C1A46900CA34C5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = B23ED18A25C1A46900CA34C5;
+			remoteInfo = ShareExtension;
+		};
 /* End PBXContainerItemProxy section */

+/* Begin PBXCopyFilesBuildPhase section */
+		B23ED19625C1A46900CA34C5 /* Embed App Extensions */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 13;
+			files = (
+				B23ED19525C1A46900CA34C5 /* ShareExtension.appex in Embed App Extensions */,
+			);
+			name = "Embed App Extensions";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
 /* Begin PBXFileReference section */
 		008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
 		00E356EE1AD99517003FC87E /* ExpensifyCashTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExpensifyCashTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -54,15 +79,24 @@
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ExpensifyCash/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		8437A5A38F2047E0BCCD7C2F /* GTAmericaExpMono-Rg.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExpMono-Rg.otf"; path = "../assets/fonts/GTAmericaExpMono-Rg.otf"; sourceTree = "<group>"; };
 		8C7003903C1E4957824899BB /* GTAmericaExp-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Regular.otf"; path = "../assets/fonts/GTAmericaExp-Regular.otf"; sourceTree = "<group>"; };
+		915BA207DEFC455EEAC9EE2A /* Pods-ShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.release.xcconfig"; sourceTree = "<group>"; };
 		918D7FEFF96242E6B5F5E14D /* GTAmericaExp-RgIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-RgIt.otf"; path = "../assets/fonts/GTAmericaExp-RgIt.otf"; sourceTree = "<group>"; };
+		981BE962FCA2842553D2AA78 /* libPods-ShareExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ShareExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		A13EE2CFAF952F935D201D2F /* Pods-ExpensifyCash.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash.release.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash.release.xcconfig"; sourceTree = "<group>"; };
 		A292718541C841859D97DF2F /* GTAmericaExp-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Thin.otf"; path = "../assets/fonts/GTAmericaExp-Thin.otf"; sourceTree = "<group>"; };
 		A5AAD008CBD84A6CAEB9AC97 /* GTAmericaExp-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Bold.otf"; path = "../assets/fonts/GTAmericaExp-Bold.otf"; sourceTree = "<group>"; };
 		A8D6F2F722FD4E66A38EBBB6 /* GTAmericaExp-BdIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-BdIt.otf"; path = "../assets/fonts/GTAmericaExp-BdIt.otf"; sourceTree = "<group>"; };
 		AE65058949E14DA5A2D5435D /* GTAmericaExp-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-Medium.otf"; path = "../assets/fonts/GTAmericaExp-Medium.otf"; sourceTree = "<group>"; };
 		AF728B3FCBC8C2731C4DA7B4 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig"; sourceTree = "<group>"; };
+		B23ED18B25C1A46900CA34C5 /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+		B23ED19025C1A46900CA34C5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
+		B23ED19225C1A46900CA34C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		B2E844AE25C3A34300909139 /* ShareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShareViewController.swift; path = "../../node_modules/react-native-share-menu/ios/ShareViewController.swift"; sourceTree = "<group>"; };
+		B2E844B325C3A5D200909139 /* ShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ShareExtension-Bridging-Header.h"; sourceTree = "<group>"; };
+		B2E9EC3725C1E5CD00BD6AE5 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = "<group>"; };
 		DB5A1365442D4419AF6F08E5 /* GTAmericaExp-MdIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExp-MdIt.otf"; path = "../assets/fonts/GTAmericaExp-MdIt.otf"; sourceTree = "<group>"; };
 		E7967C67752432EA2031954F /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig"; path = "Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig"; sourceTree = "<group>"; };
+		E7FF6451784072419C0107A6 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
 		E9DF872C2525201700607FDC /* AirshipConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AirshipConfig.plist; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
 		ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
@@ -87,6 +121,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		B23ED18825C1A46900CA34C5 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9842B1200DD5443D16989CD2 /* libPods-ShareExtension.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */

 /* Begin PBXGroup section */
@@ -130,6 +172,7 @@
 				ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
 				6F2C8BDCC1FF0B64AE2DFC9B /* libPods-ExpensifyCash.a */,
 				ED2AB27DDDFCCE3CD100EA0C /* libPods-ExpensifyCash-ExpensifyCashTests.a */,
+				981BE962FCA2842553D2AA78 /* libPods-ShareExtension.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -147,6 +190,7 @@
 				13B07FAE1A68108700A75B9A /* ExpensifyCash */,
 				832341AE1AAA6A7D00B99B32 /* Libraries */,
 				00E356EF1AD99517003FC87E /* ExpensifyCashTests */,
+				B23ED18C25C1A46900CA34C5 /* ShareExtension */,
 				83CBBA001A601CBA00E9B192 /* Products */,
 				2D16E6871FA4F8E400B85C8A /* Frameworks */,
 				EC29677F0A49C2946A495A33 /* Pods */,
@@ -162,6 +206,7 @@
 			children = (
 				13B07F961A680F5B00A75B9A /* Expensify.cash.app */,
 				00E356EE1AD99517003FC87E /* ExpensifyCashTests.xctest */,
+				B23ED18B25C1A46900CA34C5 /* ShareExtension.appex */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -182,6 +227,18 @@
 			name = Resources;
 			sourceTree = "<group>";
 		};
+		B23ED18C25C1A46900CA34C5 /* ShareExtension */ = {
+			isa = PBXGroup;
+			children = (
+				B2E844AE25C3A34300909139 /* ShareViewController.swift */,
+				B2E9EC3725C1E5CD00BD6AE5 /* ShareExtension.entitlements */,
+				B23ED18F25C1A46900CA34C5 /* MainInterface.storyboard */,
+				B23ED19225C1A46900CA34C5 /* Info.plist */,
+				B2E844B325C3A5D200909139 /* ShareExtension-Bridging-Header.h */,
+			);
+			path = ShareExtension;
+			sourceTree = "<group>";
+		};
 		EC29677F0A49C2946A495A33 /* Pods */ = {
 			isa = PBXGroup;
 			children = (
@@ -189,6 +246,8 @@
 				A13EE2CFAF952F935D201D2F /* Pods-ExpensifyCash.release.xcconfig */,
 				AF728B3FCBC8C2731C4DA7B4 /* Pods-ExpensifyCash-ExpensifyCashTests.debug.xcconfig */,
 				E7967C67752432EA2031954F /* Pods-ExpensifyCash-ExpensifyCashTests.release.xcconfig */,
+				E7FF6451784072419C0107A6 /* Pods-ShareExtension.debug.xcconfig */,
+				915BA207DEFC455EEAC9EE2A /* Pods-ShareExtension.release.xcconfig */,
 			);
 			path = Pods;
 			sourceTree = "<group>";
@@ -229,22 +288,44 @@
 				C9071365B664DE0D85DC5195 /* [CP] Copy Pods Resources */,
 				CF6259710B5A341870372EA2 /* [CP-User] [RNFB] Core Configuration */,
 				ED5B8E90A3384FC6A128FB95 /* [CP-User] [RNFB] Crashlytics Configuration */,
+				B23ED19625C1A46900CA34C5 /* Embed App Extensions */,
 			);
 			buildRules = (
 			);
 			dependencies = (
+				B23ED19425C1A46900CA34C5 /* PBXTargetDependency */,
 			);
 			name = ExpensifyCash;
 			productName = ExpensifyCash;
 			productReference = 13B07F961A680F5B00A75B9A /* Expensify.cash.app */;
 			productType = "com.apple.product-type.application";
 		};
+		B23ED18A25C1A46900CA34C5 /* ShareExtension */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = B23ED19925C1A46900CA34C5 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
+			buildPhases = (
+				C55D1D9B7EB40F37CFB79F72 /* [CP] Check Pods Manifest.lock */,
+				B23ED18725C1A46900CA34C5 /* Sources */,
+				B23ED18825C1A46900CA34C5 /* Frameworks */,
+				B23ED18925C1A46900CA34C5 /* Resources */,
+				CAD20EC45A7B56F8F8F2BDE9 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ShareExtension;
+			productName = ShareExtension;
+			productReference = B23ED18B25C1A46900CA34C5 /* ShareExtension.appex */;
+			productType = "com.apple.product-type.app-extension";
+		};
 /* End PBXNativeTarget section */

 /* Begin PBXProject section */
 		83CBB9F71A601CBA00E9B192 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
+				LastSwiftUpdateCheck = 1230;
 				LastUpgradeCheck = 1130;
 				TargetAttributes = {
 					00E356ED1AD99517003FC87E = {
@@ -257,6 +338,12 @@
 						LastSwiftMigration = 1120;
 						ProvisioningStyle = Manual;
 					};
+					B23ED18A25C1A46900CA34C5 = {
+						CreatedOnToolsVersion = 12.3;
+						DevelopmentTeam = 368M544MTT;
+						LastSwiftMigration = 1230;
+						ProvisioningStyle = Manual;
+					};
 				};
 			};
 			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ExpensifyCash" */;
@@ -274,6 +361,7 @@
 			targets = (
 				13B07F861A680F5B00A75B9A /* ExpensifyCash */,
 				00E356ED1AD99517003FC87E /* ExpensifyCashTests */,
+				B23ED18A25C1A46900CA34C5 /* ShareExtension */,
 			);
 		};
 /* End PBXProject section */
@@ -306,6 +394,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		B23ED18925C1A46900CA34C5 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				B23ED19125C1A46900CA34C5 /* MainInterface.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXResourcesBuildPhase section */

 /* Begin PBXShellScriptBuildPhase section */
@@ -367,6 +463,28 @@
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
+		C55D1D9B7EB40F37CFB79F72 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-ShareExtension-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
 		C9071365B664DE0D85DC5195 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -495,6 +613,24 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
+		CAD20EC45A7B56F8F8F2BDE9 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-ShareExtension/Pods-ShareExtension-resources.sh",
+				"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ShareExtension/Pods-ShareExtension-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 		CF6259710B5A341870372EA2 /* [CP-User] [RNFB] Core Configuration */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -682,6 +818,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		B23ED18725C1A46900CA34C5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				B2E844AF25C3A34300909139 /* ShareViewController.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */

 /* Begin PBXTargetDependency section */
@@ -690,8 +834,24 @@
 			target = 13B07F861A680F5B00A75B9A /* ExpensifyCash */;
 			targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
 		};
+		B23ED19425C1A46900CA34C5 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = B23ED18A25C1A46900CA34C5 /* ShareExtension */;
+			targetProxy = B23ED19325C1A46900CA34C5 /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */

+/* Begin PBXVariantGroup section */
+		B23ED18F25C1A46900CA34C5 /* MainInterface.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				B23ED19025C1A46900CA34C5 /* Base */,
+			);
+			name = MainInterface.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
 /* Begin XCBuildConfiguration section */
 		00E356F61AD99517003FC87E /* Debug */ = {
 			isa = XCBuildConfiguration;
@@ -743,6 +903,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = F4BC0E78FF1E9BD8B2D38C66 /* Pods-ExpensifyCash.debug.xcconfig */;
 			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = ExpensifyCash/Chat.entitlements;
@@ -775,6 +936,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = A13EE2CFAF952F935D201D2F /* Pods-ExpensifyCash.release.xcconfig */;
 			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = ExpensifyCash/Chat.entitlements;
@@ -914,6 +1076,81 @@
 			};
 			name = Release;
 		};
+		B23ED19725C1A46900CA34C5 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = E7FF6451784072419C0107A6 /* Pods-ShareExtension.debug.xcconfig */;
+			buildSettings = {
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
+				CODE_SIGN_IDENTITY = "iPhone Distribution";
+				CODE_SIGN_STYLE = Manual;
+				CURRENT_PROJECT_VERSION = 386;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				DEVELOPMENT_TEAM = 368M544MTT;
+				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				INFOPLIST_FILE = ShareExtension/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+				MARKETING_VERSION = 1.0.1;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat.ShareExtension;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore;
+				SKIP_INSTALL = YES;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+				SWIFT_OBJC_BRIDGING_HEADER = "ShareExtension/ShareExtension-Bridging-Header.h";
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		B23ED19825C1A46900CA34C5 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 915BA207DEFC455EEAC9EE2A /* Pods-ShareExtension.release.xcconfig */;
+			buildSettings = {
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
+				CODE_SIGN_IDENTITY = "iPhone Distribution";
+				CODE_SIGN_STYLE = Manual;
+				COPY_PHASE_STRIP = NO;
+				CURRENT_PROJECT_VERSION = 386;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DEVELOPMENT_TEAM = 368M544MTT;
+				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				INFOPLIST_FILE = ShareExtension/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+				MARKETING_VERSION = 1.0.1;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat.ShareExtension;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore;
+				SKIP_INSTALL = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = "ShareExtension/ShareExtension-Bridging-Header.h";
+				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */

 /* Begin XCConfigurationList section */
@@ -944,6 +1181,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		B23ED19925C1A46900CA34C5 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				B23ED19725C1A46900CA34C5 /* Debug */,
+				B23ED19825C1A46900CA34C5 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
diff --git a/ios/ExpensifyCash/AppDelegate.m b/ios/ExpensifyCash/AppDelegate.m
index 63afe3635692..23a8f024b08e 100644
--- a/ios/ExpensifyCash/AppDelegate.m
+++ b/ios/ExpensifyCash/AppDelegate.m
@@ -6,6 +6,7 @@
 #import <Firebase.h>

 #import <UserNotifications/UserNotifications.h>
+#import <RNShareMenu/ShareMenuManager.h>

 #ifdef FB_SONARKIT_ENABLED
 #import <FlipperKit/FlipperClient.h>
@@ -66,4 +67,11 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
 #endif
 }

+- (BOOL)application:(UIApplication *)app
+            openURL:(NSURL *)url
+            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
+{
+  return [ShareMenuManager application:app openURL:url options:options];
+}
+
 @end
diff --git a/ios/ExpensifyCash/Chat.entitlements b/ios/ExpensifyCash/Chat.entitlements
index 903def2af530..68c025067d14 100644
--- a/ios/ExpensifyCash/Chat.entitlements
+++ b/ios/ExpensifyCash/Chat.entitlements
@@ -4,5 +4,9 @@
 <dict>
 	<key>aps-environment</key>
 	<string>development</string>
+	<key>com.apple.security.application-groups</key>
+	<array>
+	    <string>group.com.chat.expensify.chat</string>
+	</array>
 </dict>
 </plist>
diff --git a/ios/ExpensifyCash/Info.plist b/ios/ExpensifyCash/Info.plist
index d75c8f14396c..dcf8bf10a2bc 100644
--- a/ios/ExpensifyCash/Info.plist
+++ b/ios/ExpensifyCash/Info.plist
@@ -48,6 +48,17 @@
 			</dict>
 		</dict>
 	</dict>
+    <key>CFBundleURLTypes</key>
+    <array>
+        <dict>
+            <key>CFBundleTypeRole</key>
+            <string>Editor</string>
+            <key>CFBundleURLSchemes</key>
+            <array>
+                <string>expensify</string>
+            </array>
+        </dict>
+    </array>
 	<key>NSCameraUsageDescription</key>
 	<string>Your camera is used to create chat attachments.</string>
 	<key>NSLocationWhenInUseUsageDescription</key>
diff --git a/ios/Podfile b/ios/Podfile
index b8f5255f0274..1122ac1c6fb2 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -21,8 +21,18 @@ target 'ExpensifyCash' do
   post_install do |installer|
     flipper_post_install(installer)

-    installer.pods_project.build_configurations.each do |config|
-      config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
+    installer.pods_project.targets.each do |target|
+      target.build_configurations.each do |config|
+        config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
+        config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
+      end
     end
   end
 end
+
+target 'ShareExtension' do
+  use_react_native!
+
+  pod 'RNShareMenu', :path => '../node_modules/react-native-share-menu'
+  # Manually link packages here to keep your extension bundle size minimal
+end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 47595c78ddd9..43bab77c6399 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -415,6 +415,8 @@ PODS:
     - Firebase/Crashlytics (~> 6.34.0)
     - React-Core
     - RNFBApp
+  - RNShareMenu (5.0.3):
+    - React
   - RNSVG (12.1.0):
     - React
   - urbanairship-react-native (10.0.0):
@@ -485,6 +487,7 @@ DEPENDENCIES:
   - "RNFBAnalytics (from `../node_modules/@react-native-firebase/analytics`)"
   - "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
   - "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
+  - RNShareMenu (from `../node_modules/react-native-share-menu`)
   - RNSVG (from `../node_modules/react-native-svg`)
   - urbanairship-react-native (from `../node_modules/urbanairship-react-native`)
   - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -595,6 +598,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/@react-native-firebase/app"
   RNFBCrashlytics:
     :path: "../node_modules/@react-native-firebase/crashlytics"
+  RNShareMenu:
+    :path: "../node_modules/react-native-share-menu"
   RNSVG:
     :path: "../node_modules/react-native-svg"
   urbanairship-react-native:
@@ -665,11 +670,12 @@ SPEC CHECKSUMS:
   RNFBAnalytics: 2dc4dd9e2445faffca041b10447a23a71dcdabf8
   RNFBApp: 7eacc7da7ab19f96c05e434017d44a9f09410da8
   RNFBCrashlytics: 4870c14cf8833053b6b5648911abefe1923854d2
+  RNShareMenu: 555df30344da0d60947ccc781b0447ee9e5cd48f
   RNSVG: ce9d996113475209013317e48b05c21ee988d42e
   urbanairship-react-native: dfb6dc22b2f41ccaadd636b73d51b448cd1b2bbc
   Yoga: 7d13633d129fd179e01b8953d38d47be90db185a
   YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

-PODFILE CHECKSUM: 41b806c7f131f87b716be1f1f9377532d6c9e43a
+PODFILE CHECKSUM: dc731cc579bb3ba93e3ed267d05524db4ca67bc6

-COCOAPODS: 1.10.0
+COCOAPODS: 1.10.1
diff --git a/ios/ShareExtension/Base.lproj/MainInterface.storyboard b/ios/ShareExtension/Base.lproj/MainInterface.storyboard
new file mode 100644
index 000000000000..286a50894d87
--- /dev/null
+++ b/ios/ShareExtension/Base.lproj/MainInterface.storyboard
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Share View Controller-->
+        <scene sceneID="ceB-am-kn3">
+            <objects>
+                <viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
+                        <viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+</document>
diff --git a/ios/ShareExtension/Info.plist b/ios/ShareExtension/Info.plist
new file mode 100644
index 000000000000..61844631945e
--- /dev/null
+++ b/ios/ShareExtension/Info.plist
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleDisplayName</key>
+	<string>ShareExtension</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(MARKETING_VERSION)</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>NSExtension</key>
+	<dict>
+		<key>NSExtensionAttributes</key>
+		<dict>
+			<key>NSExtensionActivationRule</key>
+			<string>TRUEPREDICATE</string>
+		</dict>
+		<key>NSExtensionMainStoryboard</key>
+		<string>MainInterface</string>
+		<key>NSExtensionPointIdentifier</key>
+		<string>com.apple.share-services</string>
+	</dict>
+    <key>HostAppBundleIdentifier</key>
+    <string>com.chat.expensify.chat</string>
+    <key>HostAppURLScheme</key>
+    <string>expensify://</string>
+    <key>NSExtension</key>
+    <dict>
+        <key>NSExtensionAttributes</key>
+        <dict>
+            <key>NSExtensionActivationRule</key>
+            <dict>
+                <!-- For a full list of available options, visit https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/AppExtensionKeys.html#//apple_ref/doc/uid/TP40014212-SW10 -->
+                <key>NSExtensionActivationSupportsImageWithMaxCount</key>
+                <integer>1</integer>
+                <key>NSExtensionActivationSupportsText</key>
+                <true/>
+                <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
+                <integer>1</integer>
+            </dict>
+        </dict>
+        <key>NSExtensionMainStoryboard</key>
+        <string>MainInterface</string>
+        <key>NSExtensionPointIdentifier</key>
+        <string>com.apple.share-services</string>
+    </dict>
+</dict>
+</plist>
diff --git a/ios/ShareExtension/ShareExtension-Bridging-Header.h b/ios/ShareExtension/ShareExtension-Bridging-Header.h
new file mode 100644
index 000000000000..bf52ff6e17cd
--- /dev/null
+++ b/ios/ShareExtension/ShareExtension-Bridging-Header.h
@@ -0,0 +1,4 @@
+#import <React/RCTBridge.h>
+#import <React/RCTBundleURLProvider.h>
+#import <React/RCTBridgeDelegate.h>
+#import <React/RCTRootView.h>
diff --git a/ios/ShareExtension/ShareExtension.entitlements b/ios/ShareExtension/ShareExtension.entitlements
new file mode 100644
index 000000000000..4151cc679255
--- /dev/null
+++ b/ios/ShareExtension/ShareExtension.entitlements
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.application-groups</key>
+	<array>
+	    <string>group.com.chat.expensify.chat</string>
+	</array>
+</dict>
+</plist>
diff --git a/package-lock.json b/package-lock.json
index ca9ebecb54f3..64aac94825c1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21302,6 +21302,11 @@
       "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-3.1.8.tgz",
       "integrity": "sha512-9gUlsDZ96QwT9AKzA6aVWM/NX5rlJgauZ9HgCDVzKbe29UQYT1740QJnnaI2GExmkFGp6o7ZLNhCXZW95eYVFA=="
     },
+    "react-native-share-menu": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/react-native-share-menu/-/react-native-share-menu-5.0.3.tgz",
+      "integrity": "sha512-NtL/jLbcApe6WalXLFCNYo8yFfhLGIIbi9AJgSpRLaf1+V141d7vtoJnd1fYObSGxcZJcKLSW2bkeJrpfbmZnw=="
+    },
     "react-native-svg": {
       "version": "12.1.0",
       "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.1.0.tgz",
diff --git a/package.json b/package.json
index 5e0bf86c880b..8204d3336219 100644
--- a/package.json
+++ b/package.json
@@ -67,6 +67,7 @@
     "react-native-pdf": "^6.2.2",
     "react-native-render-html": "^6.0.0-alpha.10",
     "react-native-safe-area-context": "^3.1.4",
+    "react-native-share-menu": "^5.0.3",
     "react-native-svg": "^12.1.0",
     "react-native-web": "^0.14.1",
     "react-native-web-webview": "^1.0.2",
diff --git a/src/Expensify.js b/src/Expensify.js
index a97751414b12..895759f8d4d9 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -7,8 +7,10 @@ import HomePage from './pages/home/HomePage';
 import NotFoundPage from './pages/NotFound';
 import SetPasswordPage from './pages/SetPasswordPage';
 import SignInPage from './pages/signin/SignInPage';
+import SharePage from './pages/SharePage';
 import listenToStorageEvents from './libs/listenToStorageEvents';
 import * as ActiveClientManager from './libs/ActiveClientManager';
+import ShareManager from './libs/ShareManager';
 import ONYXKEYS from './ONYXKEYS';

 import styles from './styles/styles';
@@ -76,6 +78,9 @@ class Expensify extends Component {
             key: ONYXKEYS.SESSION,
             callback: this.removeLoadingState,
         });
+
+        // Subscribe to share events
+        ShareManager.register();
     }

     componentDidUpdate(prevProps, prevState) {
@@ -84,6 +89,10 @@ class Expensify extends Component {
         }
     }

+    componentWillUnmount() {
+        ShareManager.deregister();
+    }
+
     /**
      * When the authToken is updated, the app should remove the loading state and handle the authToken
      *
@@ -130,6 +139,7 @@ class Expensify extends Component {
                     <Route path={[ROUTES.SET_PASSWORD]} component={SetPasswordPage} />
                     <Route path={[ROUTES.NOT_FOUND]} component={NotFoundPage} />
                     <Route path={[ROUTES.SIGNIN_WITH_EXITTO, ROUTES.SIGNIN]} component={SignInPage} />
+                    <Route path={[ROUTES.SHARE]} component={SharePage} />
                     <Route
                         path={[ROUTES.HOME, ROUTES.ROOT]}
                         render={match => (
diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js
index 33dc21e1617e..603a848cba43 100644
--- a/src/ONYXKEYS.js
+++ b/src/ONYXKEYS.js
@@ -41,6 +41,9 @@ export default {
     IS_SIDEBAR_ANIMATING: 'isSidebarAnimating',
     BETAS: 'betas',

+    // Data shared to the app from other apps
+    SHARED_ITEM: 'sharedItem',
+
     // Collection Keys
     COLLECTION: {
         REPORT: 'report_',
diff --git a/src/ROUTES.js b/src/ROUTES.js
index 2c367474d55a..a4032180441b 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -7,6 +7,7 @@ export default {
     NEW_GROUP: '/new/group',
     REPORT: '/r/:reportID',
     getReportRoute: reportID => `/r/${reportID}`,
+    SHARE: '/share',
     ROOT: '/',
     SET_PASSWORD: '/setpassword/:validateCode',
     SIGNIN: '/signin',
diff --git a/src/libs/ShareManager/ShareType.js b/src/libs/ShareManager/ShareType.js
new file mode 100644
index 000000000000..b05ccf28278a
--- /dev/null
+++ b/src/libs/ShareManager/ShareType.js
@@ -0,0 +1,7 @@
+/**
+ * Types of shared content.
+ */
+export default {
+    FILE: 'file',
+    TEXT: 'text',
+};
diff --git a/src/libs/ShareManager/index.js b/src/libs/ShareManager/index.js
new file mode 100644
index 000000000000..571e5b7dfea2
--- /dev/null
+++ b/src/libs/ShareManager/index.js
@@ -0,0 +1,9 @@
+// This is a no-op component for desktop and web,
+// because sharing to the app is only supported on mobile
+import ShareType from './ShareType';
+
+export default {
+    register: () => {},
+    deregister: () => {},
+    TYPE: ShareType,
+};
diff --git a/src/libs/ShareManager/index.native.js b/src/libs/ShareManager/index.native.js
new file mode 100644
index 000000000000..3a503bb41022
--- /dev/null
+++ b/src/libs/ShareManager/index.native.js
@@ -0,0 +1,70 @@
+import ShareMenu from 'react-native-share-menu';
+import {redirect} from '../actions/App';
+import {set as setSharedItem} from '../actions/SharedItem';
+import ROUTES from '../../ROUTES';
+import ShareType from './ShareType';
+
+const TEXT_MIME_TYPE = /^text\//i;
+
+// Share event listener
+let listener;
+
+/**
+ * Prepare shared item for posting
+ *
+ * @param {Object} sharedItem Shared item object
+ * @returns {Object} Prepared shared item structure
+ */
+function prepareSharedItem(sharedItem) {
+    if (sharedItem.mimeType.match(TEXT_MIME_TYPE)) {
+        // Shared item is text or HTML
+        return {
+            type: ShareType.TEXT,
+            data: sharedItem.data,
+        };
+    }
+
+    // Shared item is file attachment
+    return {
+        type: ShareType.FILE,
+        data: {
+            name: 'chat_attachment',
+            type: sharedItem.mimeType,
+            uri: sharedItem.data,
+        },
+    };
+}
+
+/**
+ * Saves shared item and redirects to Share Page.
+ *
+ * @param {Object} sharedItem
+ */
+function handleShare(sharedItem) {
+    if (sharedItem) {
+        const preparedSharedItem = prepareSharedItem(sharedItem);
+        setSharedItem(preparedSharedItem);
+        redirect(ROUTES.SHARE);
+    }
+}
+
+/**
+ * Subscribes to share events.
+ */
+function register() {
+    ShareMenu.getInitialShare(handleShare);
+    listener = ShareMenu.addNewShareListener(handleShare);
+}
+
+/**
+ * Removes share events listener.
+ */
+function deregister() {
+    listener.remove();
+}
+
+export default {
+    register,
+    deregister,
+    TYPE: ShareType,
+};
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 7fbd3b5b45c9..d3046cf520ab 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -504,6 +504,7 @@ function fetchAll(shouldRedirectToReport = true, shouldFetchActions = false, sho
  * set of participants
  *
  * @param {String[]} participants
+ * @returns {Promise} reportID
  */
 function fetchOrCreateChatReport(participants) {
     let reportID;
@@ -512,7 +513,7 @@ function fetchOrCreateChatReport(participants) {
         throw new Error('fetchOrCreateChatReport() must have at least two participants');
     }

-    API.CreateChatReport({
+    return API.CreateChatReport({
         emailList: participants.join(','),
     })

@@ -557,6 +558,8 @@ function fetchOrCreateChatReport(participants) {

             // Redirect the logged in person to the new report
             redirect(ROUTES.getReportRoute(reportID));
+
+            return reportID;
         });
 }

diff --git a/src/libs/actions/SharedItem.js b/src/libs/actions/SharedItem.js
new file mode 100644
index 000000000000..a6fabf8e5a06
--- /dev/null
+++ b/src/libs/actions/SharedItem.js
@@ -0,0 +1,23 @@
+import Onyx from 'react-native-onyx';
+import ONYXKEYS from '../../ONYXKEYS';
+
+/**
+ * Saves shared item to storage.
+ *
+ * @param {Object} sharedItem
+ */
+function set(sharedItem) {
+    Onyx.set(ONYXKEYS.SHARED_ITEM, sharedItem);
+}
+
+/**
+ * Clears shared item from storage.
+ */
+function clear() {
+    Onyx.set(ONYXKEYS.SHARED_ITEM, null);
+}
+
+export {
+    set,
+    clear,
+};
diff --git a/src/pages/SharePage.js b/src/pages/SharePage.js
new file mode 100644
index 000000000000..a30a4832cb5d
--- /dev/null
+++ b/src/pages/SharePage.js
@@ -0,0 +1,176 @@
+import React from 'react';
+import {View} from 'react-native';
+import {SafeAreaProvider} from 'react-native-safe-area-context/src/SafeAreaContext';
+import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
+import {withOnyx} from 'react-native-onyx';
+import PropTypes from 'prop-types';
+import styles from '../styles/styles';
+import ONYXKEYS from '../ONYXKEYS';
+import ShareManager from '../libs/ShareManager';
+import {redirect} from '../libs/actions/App';
+import {clear as clearSharedItem} from '../libs/actions/SharedItem';
+import {hide as hideSidebar} from '../libs/actions/Sidebar';
+import {addAction} from '../libs/actions/Report';
+import ROUTES from '../ROUTES';
+import CustomStatusBar from '../components/CustomStatusBar';
+import SidebarLinks from './home/sidebar/SidebarLinks';
+import FAB from '../components/FAB';
+import CreateMenu from '../components/CreateMenu';
+import * as ChatSwitcher from '../libs/actions/ChatSwitcher';
+
+const propTypes = {
+    // Currently viewed reportID
+    currentlyViewedReportID: PropTypes.string,
+
+    // Shared item object
+    sharedItem: PropTypes.shape({
+        // Shared item type (one of the `ShareType.*`)
+        type: PropTypes.string.isRequired,
+
+        // Shared item data. Differs depending on type
+        data: PropTypes.oneOfType([
+            // Text or HTML for `ShareType.TEXT`
+            PropTypes.string,
+
+            // File data structure for `ShareType.FILE`
+            PropTypes.shape({
+                // File name
+                name: PropTypes.string.isRequired,
+
+                // File MIME type
+                type: PropTypes.string.isRequired,
+
+                // File URI
+                uri: PropTypes.string.isRequired,
+            }),
+        ]).isRequired,
+    }),
+};
+
+const defaultProps = {
+    currentlyViewedReportID: '',
+    sharedItem: null,
+};
+
+class SharePage extends React.Component {
+    constructor(props) {
+        super(props);
+
+        this.state = {
+            isCreateMenuActive: false,
+        };
+
+        this.onCloseButtonClick = this.onCloseButtonClick.bind(this);
+        this.onLinkClick = this.onLinkClick.bind(this);
+        this.onCreateMenuItemSelected = this.onCreateMenuItemSelected.bind(this);
+        this.toggleCreateMenu = this.toggleCreateMenu.bind(this);
+        this.addSharedItemToReport = this.addSharedItemToReport.bind(this);
+    }
+
+    /**
+     * Clears the shared item and closes Share Page.
+     */
+    onCloseButtonClick() {
+        clearSharedItem();
+        redirect(this.props.currentlyViewedReportID !== ''
+            ? ROUTES.getReportRoute(this.props.currentlyViewedReportID)
+            : ROUTES.HOME);
+    }
+
+    /**
+     * Hides navigation menu on redirect to report page.
+     */
+    onLinkClick() {
+        hideSidebar();
+    }
+
+    /**
+     * Method called when a Create Menu item is selected.
+     */
+    onCreateMenuItemSelected() {
+        this.toggleCreateMenu();
+        ChatSwitcher.show();
+    }
+
+    /**
+     * Posts shared item to selected report
+     *
+     * @param {Number} reportID report id
+     */
+    addSharedItemToReport(reportID) {
+        if (!this.props.sharedItem) {
+            return;
+        }
+
+        switch (this.props.sharedItem.type) {
+            case ShareManager.TYPE.TEXT:
+                addAction(reportID, this.props.sharedItem.data);
+                break;
+            case ShareManager.TYPE.FILE:
+                addAction(reportID, '', this.props.sharedItem.data);
+                break;
+            default:
+                break;
+        }
+
+        clearSharedItem();
+    }
+
+    /**
+     * Method called when we click the floating action button
+     *
+     * Method called either when:
+     * Pressing the floating action button to open the CreateMenu modal
+     * Selecting an item on CreateMenu or closing it by clicking outside of the modal component
+     */
+    toggleCreateMenu() {
+        this.setState(state => ({
+            isCreateMenuActive: !state.isCreateMenuActive,
+        }));
+    }
+
+    render() {
+        return (
+            <SafeAreaProvider>
+                <CustomStatusBar />
+                <SafeAreaInsetsContext.Consumer style={[styles.flex1]}>
+                    {insets => (
+                        <>
+                            <View style={[styles.flex1, styles.sidebar]}>
+                                <SidebarLinks
+                                    title="Send to..."
+                                    showCloseButton
+                                    insets={insets}
+                                    onCloseButtonClick={this.onCloseButtonClick}
+                                    onLinkClick={this.onLinkClick}
+                                    onReportSelected={this.addSharedItemToReport}
+                                />
+                                <FAB
+                                    isActive={this.state.isCreateMenuActive}
+                                    onPress={this.toggleCreateMenu}
+                                />
+                            </View>
+                            <CreateMenu
+                                onClose={this.toggleCreateMenu}
+                                isVisible={this.state.isCreateMenuActive}
+                                onItemSelected={this.onCreateMenuItemSelected}
+                            />
+                        </>
+                    )}
+                </SafeAreaInsetsContext.Consumer>
+            </SafeAreaProvider>
+        );
+    }
+}
+
+SharePage.propTypes = propTypes;
+SharePage.defaultProps = defaultProps;
+
+export default withOnyx({
+    currentlyViewedReportID: {
+        key: ONYXKEYS.CURRENTLY_VIEWED_REPORTID,
+    },
+    sharedItem: {
+        key: ONYXKEYS.SHARED_ITEM,
+    },
+})(SharePage);
diff --git a/src/pages/home/sidebar/ChatSwitcherView.js b/src/pages/home/sidebar/ChatSwitcherView.js
index 2bc222c4970a..7f669eef34a4 100644
--- a/src/pages/home/sidebar/ChatSwitcherView.js
+++ b/src/pages/home/sidebar/ChatSwitcherView.js
@@ -35,6 +35,9 @@ const propTypes = {
     // Toggles the navigation menu open and closed
     onLinkClick: PropTypes.func.isRequired,

+    // Called when report is selected
+    onReportSelected: PropTypes.func,
+
     /* Onyx Props */

     // All of the personal details for everyone
@@ -60,6 +63,7 @@ const propTypes = {
     isSidebarAnimating: PropTypes.bool,
 };
 const defaultProps = {
+    onReportSelected: () => {},
     personalDetails: {},
     reports: {},
     session: null,
@@ -241,7 +245,8 @@ class ChatSwitcherView extends React.Component {
      */
     startGroupChat() {
         const userLogins = _.map(this.state.usersToStartGroupReportWith, option => option.login);
-        fetchOrCreateChatReport([this.props.session.email, ...userLogins]);
+        fetchOrCreateChatReport([this.props.session.email, ...userLogins])
+            .then(this.props.onReportSelected);
         this.props.onLinkClick();
         this.reset();
     }
@@ -257,9 +262,11 @@ class ChatSwitcherView extends React.Component {
         // the user that was just selected and everyone in the list
         if (this.state.usersToStartGroupReportWith.length > 0) {
             const userLogins = _.map(this.state.usersToStartGroupReportWith, option => option.login);
-            fetchOrCreateChatReport([this.props.session.email, ...userLogins, selectedOption.login]);
+            fetchOrCreateChatReport([this.props.session.email, ...userLogins, selectedOption.login])
+                .then(this.props.onReportSelected);
         } else {
-            fetchOrCreateChatReport([this.props.session.email, selectedOption.login]);
+            fetchOrCreateChatReport([this.props.session.email, selectedOption.login])
+                .then(this.props.onReportSelected);
         }

         this.props.onLinkClick();
diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js
index 9e685c93abe2..f8da9ee091b7 100644
--- a/src/pages/home/sidebar/SidebarLinks.js
+++ b/src/pages/home/sidebar/SidebarLinks.js
@@ -13,7 +13,7 @@ import {redirect} from '../../../libs/actions/App';
 import ROUTES from '../../../ROUTES';
 import * as ChatSwitcher from '../../../libs/actions/ChatSwitcher';
 import Icon from '../../../components/Icon';
-import {MagnifyingGlass} from '../../../components/Icon/Expensicons';
+import {Close, MagnifyingGlass} from '../../../components/Icon/Expensicons';
 import Header from '../../../components/Header';
 import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton';
 import AvatarWithIndicator from '../../../components/AvatarWithIndicator';
@@ -26,11 +26,26 @@ const propTypes = {
     onLinkClick: PropTypes.func.isRequired,

     // navigates to settings and hides sidebar
-    onAvatarClick: PropTypes.func.isRequired,
+    onAvatarClick: PropTypes.func,
+
+    // Navigates from page
+    onCloseButtonClick: PropTypes.func,
+
+    // Called when report is selected
+    onReportSelected: PropTypes.func,

     // Safe area insets required for mobile devices margins
     insets: SafeAreaInsetPropTypes.isRequired,

+    // Title of the Header
+    title: PropTypes.string,
+
+    // Should we show the avatar
+    showAvatar: PropTypes.bool,
+
+    // Should we show the close button
+    showCloseButton: PropTypes.bool,
+
     /* Onyx Props */
     // List of reports
     reports: PropTypes.objectOf(PropTypes.shape({
@@ -72,6 +87,12 @@ const propTypes = {
 };

 const defaultProps = {
+    title: 'Chats',
+    showAvatar: false,
+    showCloseButton: false,
+    onAvatarClick: () => console.error('`onAvatarClick` is not defined'),
+    onCloseButtonClick: () => console.error('`onCloseButtonClick` is not defined'),
+    onReportSelected: () => {},
     reports: {},
     isChatSwitcherActive: false,
     draftComments: {},
@@ -150,6 +171,7 @@ class SidebarLinks extends React.Component {
                         />
                         <ChatSwitcherView
                             onLinkClick={this.props.onLinkClick}
+                            onReportSelected={this.props.onReportSelected}
                         />
                     </Animated.View>
                 )}
@@ -166,21 +188,31 @@ class SidebarLinks extends React.Component {
                             styles.alignItemsCenter,
                         ]}
                         >
-                            <Header textSize="large" title="Chats" />
+                            <Header textSize="large" title={this.props.title} />
                             <TouchableOpacity
                                 style={[styles.flexRow, styles.ph5]}
                                 onPress={() => ChatSwitcher.show()}
                             >
                                 <Icon src={MagnifyingGlass} />
                             </TouchableOpacity>
-                            <TouchableOpacity
-                                onPress={this.props.onAvatarClick}
-                            >
-                                <AvatarWithIndicator
-                                    source={this.props.myPersonalDetails.avatarURL}
-                                    isActive={this.props.network && !this.props.network.isOffline}
-                                />
-                            </TouchableOpacity>
+                            {this.props.showCloseButton && (
+                                <TouchableOpacity
+                                    style={[styles.flexRow, styles.sidebarCloseButton]}
+                                    onPress={this.props.onCloseButtonClick}
+                                >
+                                    <Icon src={Close} />
+                                </TouchableOpacity>
+                            )}
+                            {this.props.showAvatar && (
+                                <TouchableOpacity
+                                    onPress={this.props.onAvatarClick}
+                                >
+                                    <AvatarWithIndicator
+                                        source={this.props.myPersonalDetails.avatarURL}
+                                        isActive={this.props.network && !this.props.network.isOffline}
+                                    />
+                                </TouchableOpacity>
+                            )}
                         </View>
                         <OptionsList
                             contentContainerStyles={[
@@ -192,6 +224,7 @@ class SidebarLinks extends React.Component {
                                 option => option.reportID === activeReportID
                             ))}
                             onSelectRow={(option) => {
+                                this.props.onReportSelected(option.reportID);
                                 redirect(ROUTES.getReportRoute(option.reportID));
                                 this.props.onLinkClick();
                             }}
diff --git a/src/pages/home/sidebar/SidebarView.js b/src/pages/home/sidebar/SidebarView.js
index 5b7ca98ebbb8..7aef284c29e0 100644
--- a/src/pages/home/sidebar/SidebarView.js
+++ b/src/pages/home/sidebar/SidebarView.js
@@ -33,6 +33,7 @@ const SidebarView = props => (
             <SidebarLinks
                 onLinkClick={props.onLinkClick}
                 insets={props.insets}
+                showAvatar
                 onAvatarClick={props.onAvatarClick}
             />
             <FAB
diff --git a/src/styles/styles.js b/src/styles/styles.js
index 5d23922b64a5..31d77abe1b9d 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -352,6 +352,12 @@ const styles = {
         width: variables.componentSizeNormal,
     },

+    sidebarCloseButton: {
+        paddingLeft: 20,
+        paddingRight: 0,
+        paddingVertical: 12,
+    },
+
     statusIndicator: {
         borderColor: themeColors.sidebar,
         borderRadius: 6,

diff --git a/tests/unit/loginTest.js b/tests/unit/loginTest.js
index 8bc0ec19d6a1..be22eef363f7 100644
--- a/tests/unit/loginTest.js
+++ b/tests/unit/loginTest.js
@@ -10,6 +10,13 @@ import renderer from 'react-test-renderer';
 import App from '../../src/App';
 import Expensify from '../../src/Expensify';

+// Set up manual mocks for methods used in the actions so our test does not fail.
+jest.mock('../../src/libs/ShareManager', () => ({
+    // There is no need for a jest.fn() since we don't need to make assertions against it.
+    register: () => {},
+    deregister: () => {},
+}));
+
 describe('AppComponent', () => {
     it('renders correctly', () => {
         renderer.create(<App />);


[FIX] Mention from suggestions concatenates to query string on autocomplete

<!-- This is a pull request template, you do not need to uncomment or remove the comments, they won't show up in the PR text. -->

## Proposed changes
<!-- Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue below. -->

https://user-images.githubusercontent.com/77742477/153057487-1dbb2bb9-b105-4e44-a77b-734beb40f7b5.mp4

## Issue(s)
<!-- Link the issues being closed by or related to this PR. For example, you can use #594 if this PR closes issue number 594 -->
Fixes #3342

## How to test or reproduce
<!-- Mention how you would reproduce the bug if not mentioned on the issue page already. Also mention which screens are going to have the changes if applicable -->

## Screenshots

## Types of changes
<!-- What types of changes does your code introduce to Rocket.Chat? -->
<!-- Put an `x` in the boxes that apply -->

- [X] Bugfix (non-breaking change which fixes an issue)
- [ ] Improvement (non-breaking change which improves a current function)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Documentation update (if none of the other choices apply)

## Checklist
<!-- Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code. -->

- [X] I have read the [CONTRIBUTING](https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat) doc
- [X] I have signed the [CLA](https://cla-assistant.io/RocketChat/Rocket.Chat.ReactNative)
- [X] Lint and unit tests pass locally with my changes
- [X] I have added tests that prove my fix is effective or that my feature works (if applicable)
- [ ] I have added necessary documentation (if applicable)
- [ ] Any dependent changes have been merged and published in downstream modules

## Further comments
<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->

[bug] Autocomplete don't clear search query
<!--

Please see our guide for opening issues: https://rocket.chat/docs/contributing/reporting-issues

If you have questions or are looking for help/support please see: https://rocket.chat/docs/getting-support

If you are experiencing a bug please search our issues to be sure it is not already present: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues

-->

### Description:

Few versions before (in 4.16 to be accurate) a very good feature was introduced - autocomplete as it works on web client. That autocomplete function search not only name of user, but username too (Real Name on Russian in our case).
But now one pitty bug appeared in that feature - if you start mention with `@` sign and fill few symbols of username and then tap on suggested user - that few symbols remain in message box.

### Environment Information:

- Rocket.Chat Server Version: 3.16.3
- Rocket.Chat App Version: 4.19.0
- Device Name: Xiaomi Mo 9 SE
- OS Version: Android 11

### Steps to reproduce:

1. Start typing `@карла` to mention `Карлан Антон` (that my name)
2. See suggestions
3. Tap correct user from suggestion
4. Correct username concatenated to search query

### Expected behavior:

Suggested username should remain without query string

### Actual behavior:

Write `@карла` and then tap to suggested `karlanaa` user
![Screenshot_2021-08-24-21-32-34-756_chat rocket reactnative](https://user-images.githubusercontent.com/4023037/130639412-b00220f5-ca46-4c58-a6f4-91b04d03c601.jpg)
Got `@карлаkarlanaa` string in message box. Expect to see `@karlanaa`
![Screenshot_2021-08-24-21-32-43-257_chat rocket reactnative](https://user-images.githubusercontent.com/4023037/130639418-20d489e8-c892-489a-b2a4-959b6b6fcb5e.jpg)
Send that wrong string to chat - it's not working (which is very logic)
![Screenshot_2021-08-24-21-32-51-040_chat rocket reactnative](https://user-images.githubusercontent.com/4023037/130639420-d188fef2-ea00-434a-bd10-abc90fe34efa.jpg)

### Additional context:

<!-- Add any other context about the problem here. -->
Related to  #2529 #1580 and improved in #2997 but with that  bug

@diegolmello Hello!
Can you take that issue to next sprint?
Thank you!
 Still an issue in 4.24
@ankar84 Done!

NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=4096' npx --no-install jest app/containers/MessageBox/getMentionRegexp.test.js --passWithNoTests 2>&1

diff --git a/app/containers/MessageBox/getMentionRegexp.ts b/app/containers/MessageBox/getMentionRegexp.ts
new file mode 100644
index 00000000000..ec8ea5d1483
--- /dev/null
+++ b/app/containers/MessageBox/getMentionRegexp.ts
@@ -0,0 +1,4 @@
+// Match query string from the message to replace it with the suggestion
+const getMentionRegexp = (): any => /[^@:#/!]*$/;
+
+export default getMentionRegexp;
diff --git a/app/containers/MessageBox/index.tsx b/app/containers/MessageBox/index.tsx
index 073d04b74de..1b94e80d925 100644
--- a/app/containers/MessageBox/index.tsx
+++ b/app/containers/MessageBox/index.tsx
@@ -31,6 +31,7 @@ import { isAndroid, isTablet } from '../../utils/deviceInfo';
 import { canUploadFile } from '../../utils/media';
 import EventEmiter from '../../utils/events';
 import { KEY_COMMAND, handleCommandShowUpload, handleCommandSubmit, handleCommandTyping } from '../../commands';
+import getMentionRegexp from './getMentionRegexp';
 import Mentions from './Mentions';
 import MessageboxContext from './Context';
 import {
@@ -489,7 +490,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
 		const msg = this.text;
 		const { start, end } = this.selection;
 		const cursor = Math.max(start, end);
-		const regexp = /([a-z0-9._-]+)$/im;
+		const regexp = getMentionRegexp();
 		let result = msg.substr(0, cursor).replace(regexp, '');
 		// Remove the ! after select the canned response
 		if (trackingType === MENTIONS_TRACKING_TYPE_CANNED) {

diff --git a/app/containers/MessageBox/getMentionRegexp.test.js b/app/containers/MessageBox/getMentionRegexp.test.js
new file mode 100644
index 00000000000..8923ae10013
--- /dev/null
+++ b/app/containers/MessageBox/getMentionRegexp.test.js
@@ -0,0 +1,56 @@
+import getMentionRegexp from './getMentionRegexp';
+
+const regexp = getMentionRegexp();
+
+describe('getMentionRegexpUser', function () {
+	test('removing query text on user suggestion autocomplete (latin)', () => {
+		const message = 'Hey @test123';
+		expect(message.replace(regexp, '')).toBe('Hey @');
+	});
+
+	test('removing query text on user suggestion autocomplete (arabic)', () => {
+		const message = 'Hey @اختبار123';
+		expect(message.replace(regexp, '')).toBe('Hey @');
+	});
+
+	test('removing query text on user suggestion autocomplete (russian)', () => {
+		const message = 'Hey @тест123';
+		expect(message.replace(regexp, '')).toBe('Hey @');
+	});
+
+	test('removing query text on user suggestion autocomplete (chinese trad)', () => {
+		const message = 'Hey @測試123';
+		expect(message.replace(regexp, '')).toBe('Hey @');
+	});
+
+	test('removing query text on user suggestion autocomplete (japanese)', () => {
+		const message = 'Hey @テスト123';
+		expect(message.replace(regexp, '')).toBe('Hey @');
+	});
+
+	test('removing query text on user suggestion autocomplete (special characters in query)', () => {
+		const message = "Hey @'=test123";
+		expect(message.replace(regexp, '')).toBe('Hey @');
+	});
+});
+
+describe('getMentionRegexpEmoji', function () {
+	test('removing query text on emoji suggestion autocomplete ', () => {
+		const message = 'Hey :smiley';
+		expect(message.replace(regexp, '')).toBe('Hey :');
+	});
+});
+
+describe('getMentionRegexpCommand', function () {
+	test('removing query text on emoji suggestion autocomplete ', () => {
+		const message = '/archive';
+		expect(message.replace(regexp, '')).toBe('/');
+	});
+});
+
+describe('getMentionRegexpRoom', function () {
+	test('removing query text on emoji suggestion autocomplete ', () => {
+		const message = 'Check #general';
+		expect(message.replace(regexp, '')).toBe('Check #');
+	});
+});


[FIX] Local database searches using non-latin characters

<!-- This is a pull request template, you do not need to uncomment or remove the comments, they won't show up in the PR text. -->

## Proposed changes
<!-- Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue below. -->
Queries using LIKE clause with user input aren't safe by default, so we need to sanitize them first.
WatermelonDB default sanitizer works for latin alphabet only.
This PR adds support for other alphabets.

## Issue(s)
<!-- Link the issues being closed by or related to this PR. For example, you can use #594 if this PR closes issue number 594 -->
Closes #2158
Related to https://github.com/Nozbe/WatermelonDB/issues/734

## How to test or reproduce
<!-- Mention how you would reproduce the bug if not mentioned on the issue page already. Also mention which screens are going to have the changes if applicable -->

## Screenshots

## Types of changes
<!-- What types of changes does your code introduce to Rocket.Chat? -->
<!-- Put an `x` in the boxes that apply -->

- [x] Bugfix (non-breaking change which fixes an issue)
- [ ] Improvement (non-breaking change which improves a current function)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Documentation update (if none of the other choices apply)

## Checklist
<!-- Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code. -->

- [x] I have read the [CONTRIBUTING](https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat) doc
- [x] I have signed the [CLA](https://cla-assistant.io/RocketChat/Rocket.Chat.ReactNative)
- [x] Lint and unit tests pass locally with my changes
- [x] I have added tests that prove my fix is effective or that my feature works (if applicable)
- [ ] I have added necessary documentation (if applicable)
- [ ] Any dependent changes have been merged and published in downstream modules

## Further comments
<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->

Real Name search doesn't work in Add Users form
- Your Rocket.Chat Experimental app version: 4.7.0.17188
- Your Rocket.Chat server version: 3.1.1
- Device (or Simulator) you're running with: Xiaomi Mi 9 SE

Search for users works perfectly in Directory Search. It does search by username and which is really much important for me and my users it does search by Real Name (which in my deployment almost always Cyrillic and not English names)
Here is example of Cyrillic search in mobile application on open.rocket.chat
![Screenshot_2020-05-30-20-49-56-608_chat rocket reactnative](https://user-images.githubusercontent.com/4023037/83330123-5b23a900-a2b7-11ea-9ef2-451156d9574f.jpg)

And here is an example of how Cyrillic search doesn't work in Add Users form (when private chat owner need to add users to his chat)
![Screenshot_2020-05-30-20-50-18-213_chat rocket reactnative](https://user-images.githubusercontent.com/4023037/83330133-65de3e00-a2b7-11ea-8c07-36faddc3af7e.jpg)
So, please, fix that search form and search in mobile application will be consistent and convenient for users.

Thanks for opening this @ankar84, we'll try to add this as a fix at our 4.8.0 release, this will probably be launched at end of June.
If someone from community want to fix this, feel free to open a Pull Request. 😀
is there any news?
The same problem is found in chat search...
@ankar84  @djorkaeffalexandre @diegolmello  Hey I am new here can I work on this?
> @ankar84 @giterium can i work on this?

I'm not a developer, to my deep regret.
@refactor-droidyy sure :)
Has a pull request been made for this issue, and is it closed, or else can I work on it ?
@diegolmello hi! Can you take a look at that issue?
@djorkaeffalexandre told me that it's spotlight related task (idk what it actually is)
> Has a pull request been made for this issue, and is it closed, or else can I work on it ?

Please work on that issue if you can. There is no ready pr for that.
@ankar84 I created the following user:
```
real name: d098
username: diego.mello1409
```

and searched by real name
<img src="https://user-images.githubusercontent.com/804994/93091182-2542de80-f674-11ea-8b6a-86168ea3e227.png" width="350" />

The issue is just the duplicated username?
Or is there something else?
> The issue is just the duplicated username?
> Or is there something else?

No.
Issue is about search users with non English real name (Cyrillic as example) in add users and magnifying glass tool.
Directory search works fine on Cyrillic Real Name (first screen) but when you try to add user to some channel by Cyrillic Real Name - search results are not correct. And magnifying glass too search by Cyrillic Real Name not correct.
Can you create a reproducible example on open server?
> Can you create a reproducible example on open server?

Yes. All screens from open.rocket.chat
Try to find `Антон` in Directory search and with magnifying glass tool.
Directory search
![IMG_20200914_203853](https://user-images.githubusercontent.com/4023037/93093303-bb095880-f6ca-11ea-9856-9d35f495d3e4.jpg)

Magnifying glass tool
![Screenshot_2020-09-14-20-39-04-581_chat rocket reactnative](https://user-images.githubusercontent.com/4023037/93093267-b2188700-f6ca-11ea-9d43-04cc5e87a21c.jpg)

Web version works perfect for both search.

NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=4096' npx --no-install jest app/lib/database/utils.test.js --passWithNoTests 2>&1

diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js
index 8bd71f70499..f5c16bf88b2 100644
--- a/app/containers/MessageBox/index.js
+++ b/app/containers/MessageBox/index.js
@@ -46,6 +46,7 @@ import CommandsPreview from './CommandsPreview';
 import { getUserSelector } from '../../selectors/login';
 import Navigation from '../../lib/Navigation';
 import { withActionSheet } from '../ActionSheet';
+import { sanitizeLikeString } from '../../lib/database/utils';

 const imagePickerConfig = {
 	cropping: true,
@@ -491,8 +492,9 @@ class MessageBox extends Component {
 		const db = database.active;
 		if (keyword) {
 			const customEmojisCollection = db.collections.get('custom_emojis');
+			const likeString = sanitizeLikeString(keyword);
 			let customEmojis = await customEmojisCollection.query(
-				Q.where('name', Q.like(`${ Q.sanitizeLikeString(keyword) }%`))
+				Q.where('name', Q.like(`${ likeString }%`))
 			).fetch();
 			customEmojis = customEmojis.slice(0, MENTIONS_COUNT_TO_DISPLAY);
 			const filteredEmojis = emojis.filter(emoji => emoji.indexOf(keyword) !== -1).slice(0, MENTIONS_COUNT_TO_DISPLAY);
@@ -504,8 +506,9 @@ class MessageBox extends Component {
 	getSlashCommands = debounce(async(keyword) => {
 		const db = database.active;
 		const commandsCollection = db.collections.get('slash_commands');
+		const likeString = sanitizeLikeString(keyword);
 		const commands = await commandsCollection.query(
-			Q.where('id', Q.like(`${ Q.sanitizeLikeString(keyword) }%`))
+			Q.where('id', Q.like(`${ likeString }%`))
 		).fetch();
 		this.setState({ mentions: commands || [] });
 	}, 300)
@@ -734,8 +737,9 @@ class MessageBox extends Component {
 			const db = database.active;
 			const commandsCollection = db.collections.get('slash_commands');
 			const command = message.replace(/ .*/, '').slice(1);
+			const likeString = sanitizeLikeString(command);
 			const slashCommand = await commandsCollection.query(
-				Q.where('id', Q.like(`${ Q.sanitizeLikeString(command) }%`))
+				Q.where('id', Q.like(`${ likeString }%`))
 			).fetch();
 			if (slashCommand.length > 0) {
 				logEvent(events.COMMAND_RUN);
diff --git a/app/lib/database/utils.js b/app/lib/database/utils.js
index 8e580030488..6c5d86b5e7d 100644
--- a/app/lib/database/utils.js
+++ b/app/lib/database/utils.js
@@ -1,1 +1,7 @@
+import XRegExp from 'xregexp';
+
+// Matches letters from any alphabet and numbers
+const likeStringRegex = new XRegExp('[^\\p{L}\\p{Nd}]', 'g');
+export const sanitizeLikeString = str => str.replace(likeStringRegex, '_');
+
 export const sanitizer = r => r;
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index 483f183bdd3..5e60b09fa58 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -56,6 +56,7 @@ import { useSsl } from '../utils/url';
 import UserPreferences from './userPreferences';
 import { Encryption } from './encryption';
 import EventEmitter from '../utils/events';
+import { sanitizeLikeString } from './database/utils';

 const TOKEN_KEY = 'reactnativemeteor_usertoken';
 const CURRENT_SERVER = 'currentServer';
@@ -517,8 +518,12 @@ const RocketChat = {
 		}

 		const db = database.active;
+		const likeString = sanitizeLikeString(searchText);
 		let data = await db.collections.get('subscriptions').query(
-			Q.where('name', Q.like(`%${ Q.sanitizeLikeString(searchText) }%`))
+			Q.or(
+				Q.where('name', Q.like(`%${ likeString }%`)),
+				Q.where('fname', Q.like(`%${ likeString }%`))
+			)
 		).fetch();

 		if (filterUsers && !filterRooms) {
diff --git a/app/views/NewServerView/index.js b/app/views/NewServerView/index.js
index 8b2047acfb4..5d5e4704404 100644
--- a/app/views/NewServerView/index.js
+++ b/app/views/NewServerView/index.js
@@ -30,6 +30,7 @@ import { CloseModalButton } from '../../containers/HeaderButton';
 import { showConfirmationAlert } from '../../utils/info';
 import database from '../../lib/database';
 import ServerInput from './ServerInput';
+import { sanitizeLikeString } from '../../lib/database/utils';

 const styles = StyleSheet.create({
 	title: {
@@ -138,10 +139,11 @@ class NewServerView extends React.Component {
 				Q.experimentalSortBy('updated_at', Q.desc),
 				Q.experimentalTake(3)
 			];
+			const likeString = sanitizeLikeString(text);
 			if (text) {
 				whereClause = [
 					...whereClause,
-					Q.where('url', Q.like(`%${ Q.sanitizeLikeString(text) }%`))
+					Q.where('url', Q.like(`%${ likeString }%`))
 				];
 			}
 			const serversHistory = await serversHistoryCollection.query(...whereClause).fetch();
diff --git a/app/views/SearchMessagesView/index.js b/app/views/SearchMessagesView/index.js
index db7d7013f00..607711eb650 100644
--- a/app/views/SearchMessagesView/index.js
+++ b/app/views/SearchMessagesView/index.js
@@ -22,6 +22,7 @@ import { getUserSelector } from '../../selectors/login';
 import SafeAreaView from '../../containers/SafeAreaView';
 import { CloseModalButton } from '../../containers/HeaderButton';
 import database from '../../lib/database';
+import { sanitizeLikeString } from '../../lib/database/utils';

 class SearchMessagesView extends React.Component {
 	static navigationOptions = ({ navigation, route }) => {
@@ -83,12 +84,13 @@ class SearchMessagesView extends React.Component {
 		if (this.encrypted) {
 			const db = database.active;
 			const messagesCollection = db.collections.get('messages');
+			const likeString = sanitizeLikeString(searchText);
 			return messagesCollection
 				.query(
 					// Messages of this room
 					Q.where('rid', this.rid),
 					// Message content is like the search text
-					Q.where('msg', Q.like(`%${ Q.sanitizeLikeString(searchText) }%`))
+					Q.where('msg', Q.like(`%${ likeString }%`))
 				)
 				.fetch();
 		}
diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js
index 250498e4996..1f94ee7439b 100644
--- a/app/views/ShareListView/index.js
+++ b/app/views/ShareListView/index.js
@@ -26,6 +26,7 @@ import { animateNextTransition } from '../../utils/layoutAnimation';
 import { withTheme } from '../../theme';
 import SafeAreaView from '../../containers/SafeAreaView';
 import RocketChat from '../../lib/rocketchat';
+import { sanitizeLikeString } from '../../lib/database/utils';

 const permission = {
 	title: I18n.t('Read_External_Permission'),
@@ -195,13 +196,14 @@ class ShareListView extends React.Component {
 			Q.experimentalSortBy('room_updated_at', Q.desc)
 		];
 		if (text) {
+			const likeString = sanitizeLikeString(text);
 			return db.collections
 				.get('subscriptions')
 				.query(
 					...defaultWhereClause,
 					Q.or(
-						Q.where('name', Q.like(`%${ Q.sanitizeLikeString(text) }%`)),
-						Q.where('fname', Q.like(`%${ Q.sanitizeLikeString(text) }%`))
+						Q.where('name', Q.like(`%${ likeString }%`)),
+						Q.where('fname', Q.like(`%${ likeString }%`))
 					)
 				).fetch();
 		}
diff --git a/package.json b/package.json
index 82aadc5e967..b47d79dab39 100644
--- a/package.json
+++ b/package.json
@@ -123,7 +123,8 @@
     "semver": "7.3.2",
     "ua-parser-js": "^0.7.21",
     "url-parse": "^1.4.7",
-    "use-deep-compare-effect": "^1.3.1"
+    "use-deep-compare-effect": "^1.3.1",
+    "xregexp": "^4.3.0"
   },
   "devDependencies": {
     "@babel/core": "^7.8.4",
diff --git a/yarn.lock b/yarn.lock
index ee38acfdd37..bc63f35ec84 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16109,7 +16109,7 @@ xregexp@4.1.1:
   resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.1.1.tgz#eb8a032aa028d403f7b1b22c47a5f16c24b21d8d"
   integrity sha512-QJ1gfSUV7kEOLfpKFCjBJRnfPErUzkNKFMso4kDSmGpp3x6ZgkyKf74inxI7PnnQCFYq5TqYJCd7DrgDN8Q05A==

-xregexp@^4.2.4:
+xregexp@^4.2.4, xregexp@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50"
   integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==

diff --git a/app/lib/database/utils.test.js b/app/lib/database/utils.test.js
new file mode 100644
index 00000000000..dd1e3996e1e
--- /dev/null
+++ b/app/lib/database/utils.test.js
@@ -0,0 +1,37 @@
+/* eslint-disable no-undef */
+import * as utils from './utils';
+
+describe('sanitizeLikeStringTester', () => {
+	// example chars that shouldn't return
+	const disallowedChars = ',./;[]!@#$%^&*()_-=+~';
+
+	const sanitizeLikeStringTester = str => expect(utils.sanitizeLikeString(`${ str }${ disallowedChars }`)).toBe(`${ str }${ '_'.repeat(disallowedChars.length) }`);
+
+	// Testing a couple of different alphabets
+	test('render test (latin)', () => {
+		sanitizeLikeStringTester('test123');
+	});
+
+	test('render test (arabic)', () => {
+		sanitizeLikeStringTester('اختبار123');
+	});
+
+	test('render test (russian)', () => {
+		sanitizeLikeStringTester('тест123');
+	});
+
+	test('render test (chinese trad)', () => {
+		sanitizeLikeStringTester('測試123');
+	});
+
+	test('render test (japanese)', () => {
+		sanitizeLikeStringTester('テスト123');
+	});
+});
+
+describe('sanitizer', () => {
+	test('render the same result', () => {
+		const content = { a: true };
+		expect(utils.sanitizer(content)).toBe(content);
+	});
+});