diff --git a/CHANGELOG.md b/CHANGELOG.md
index e680084d384..1215cb1d54b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## Unreleased (develop)
+- added: Home screen long-press shortcuts for "⚠️ Save 2FA First!" warning and "Contact Support".
- added: Show swap KYC/terms modal for NExchange
- added: Nym mixnet warning in Stake, Unstake, and Claim Rewards scenes
- changed: Migrate Thorchain Savers and Thorchain Yield endpoints off NineRealms to gateway.liquify.com.
diff --git a/index.ts b/index.ts
index a621e39496c..d3a7346aec2 100644
--- a/index.ts
+++ b/index.ts
@@ -1,3 +1,4 @@
+import 'expo-modules-core'
import 'react-native-gesture-handler'
import './src/app'
import './src/perf'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 5fc5a714e69..584bb278d19 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -87,6 +87,8 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
+ - ExpoQuickActions (5.0.0):
+ - ExpoModulesCore
- fast_float (6.1.4)
- FBLazyVector (0.79.2)
- Firebase/CoreOnly (10.29.0):
@@ -2889,6 +2891,7 @@ DEPENDENCIES:
- ExpoFont (from `../node_modules/expo-font/ios`)
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
+ - ExpoQuickActions (from `../node_modules/expo-quick-actions/ios`)
- fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
@@ -3089,6 +3092,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-keep-awake/ios"
ExpoModulesCore:
:path: "../node_modules/expo-modules-core"
+ ExpoQuickActions:
+ :path: "../node_modules/expo-quick-actions/ios"
fast_float:
:podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec"
FBLazyVector:
@@ -3347,6 +3352,7 @@ SPEC CHECKSUMS:
ExpoFont: cf508bc2e6b70871e05386d71cab927c8524cc8e
ExpoKeepAwake: bf0811570c8da182bfb879169437d4de298376e7
ExpoModulesCore: 471ae18809dc8a5c9a623193a317eef6048a4f8a
+ ExpoQuickActions: fdbda7f5874aed3dd2b1d891ec00ab3300dc7541
fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6
FBLazyVector: 84b955f7b4da8b895faf5946f73748267347c975
Firebase: cec914dab6fd7b1bd8ab56ea07ce4e03dd251c2d
diff --git a/package.json b/package.json
index 345e1ec54dc..53db9e78926 100644
--- a/package.json
+++ b/package.json
@@ -115,6 +115,7 @@
"edge-login-ui-rn": "^3.35.5",
"ethers": "^5.7.2",
"expo": "^53.0.0",
+ "expo-quick-actions": "^5.0.0",
"jsrsasign": "^11.1.0",
"marked": "^15.0.9",
"p-debounce": "^4.0.0",
diff --git a/src/components/App.tsx b/src/components/App.tsx
index 0e2a98349e2..5f73973ea2d 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -10,6 +10,7 @@ import { SafeAreaProvider } from 'react-native-safe-area-context'
import { useHandler } from '../hooks/useHandler'
import { CrashScene } from './scenes/CrashScene'
import { EdgeCoreManager } from './services/EdgeCoreManager'
+import { QuickActionsManager } from './services/QuickActionsManager'
import { StatusBarManager } from './services/StatusBarManager'
import { ThemeProvider } from './services/ThemeContext'
@@ -38,6 +39,7 @@ const MainApp: React.FC = () => {
fallback={}
>
+
diff --git a/src/components/services/QuickActionsManager.tsx b/src/components/services/QuickActionsManager.tsx
new file mode 100644
index 00000000000..4f398c8fd46
--- /dev/null
+++ b/src/components/services/QuickActionsManager.tsx
@@ -0,0 +1,51 @@
+import * as QuickActions from 'expo-quick-actions'
+import { useQuickActionCallback } from 'expo-quick-actions/hooks'
+import * as React from 'react'
+import { Linking, Platform } from 'react-native'
+
+import { useHandler } from '../../hooks/useHandler'
+import { lstrings } from '../../locales/strings'
+import { showError } from './AirshipInstance'
+
+const DO_NOT_UNINSTALL_URL =
+ 'https://support.edge.app/en/articles/14439418-warning-don-t-uninstall-edge-without-your-login-credentials'
+const CONTACT_SUPPORT_URL =
+ 'https://support.edge.app/en/articles/14054649-need-help-reach-out-via-our-chat-bubble?chat=open'
+
+export const QuickActionsManager: React.FC = () => {
+ React.useEffect(() => {
+ QuickActions.setItems([
+ {
+ id: 'do_not_uninstall',
+ title: lstrings.shortcut_do_not_uninstall_title,
+ subtitle: lstrings.shortcut_do_not_uninstall_subtitle,
+ icon: Platform.select({
+ ios: 'symbol:nosign',
+ default: 'prohibit'
+ }),
+ params: { url: DO_NOT_UNINSTALL_URL }
+ },
+ {
+ id: 'contact_support',
+ title: lstrings.shortcut_contact_support_title,
+ subtitle: lstrings.shortcut_contact_support_subtitle,
+ icon: Platform.select({
+ ios: 'symbol:message.fill',
+ default: 'message'
+ }),
+ params: { url: CONTACT_SUPPORT_URL }
+ }
+ ]).catch(showError)
+ }, [])
+
+ const handleQuickAction = useHandler((action: QuickActions.Action) => {
+ const url = action.params?.url
+ if (typeof url === 'string') {
+ Linking.openURL(url).catch(showError)
+ }
+ })
+
+ useQuickActionCallback(handleQuickAction)
+
+ return null
+}
diff --git a/src/locales/en_US.ts b/src/locales/en_US.ts
index d451fd23a61..0d81d758985 100644
--- a/src/locales/en_US.ts
+++ b/src/locales/en_US.ts
@@ -2551,6 +2551,12 @@ const strings = {
'Please ensure all details are correct before making the transfer.',
// #endregion
+ // Home screen long-press shortcuts (expo-quick-actions)
+ shortcut_do_not_uninstall_title: '⚠️ Save 2FA First!',
+ shortcut_do_not_uninstall_subtitle: 'Login requires 2FA & credentials!',
+ shortcut_contact_support_title: 'Contact Support',
+ shortcut_contact_support_subtitle: 'Get help from our live support agents',
+
unknown_error_message: 'An unknown error occurred.'
} as const
diff --git a/src/locales/strings/enUS.json b/src/locales/strings/enUS.json
index 584b22395b4..a55e99ee014 100644
--- a/src/locales/strings/enUS.json
+++ b/src/locales/strings/enUS.json
@@ -1990,5 +1990,9 @@
"ramp_account_number_label": "Account Number",
"ramp_routing_number_label": "Routing Number",
"ramp_bank_routing_warning": "Please ensure all details are correct before making the transfer.",
+ "shortcut_do_not_uninstall_title": "⚠️ Save 2FA First!",
+ "shortcut_do_not_uninstall_subtitle": "Login requires 2FA & credentials!",
+ "shortcut_contact_support_title": "Contact Support",
+ "shortcut_contact_support_subtitle": "Get help from our live support agents",
"unknown_error_message": "An unknown error occurred."
}
diff --git a/yarn.lock b/yarn.lock
index e125ef7cc9b..126a5206a82 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1063,20 +1063,7 @@
"@babel/parser" "^7.27.2"
"@babel/types" "^7.27.1"
-"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3":
- version "7.28.0"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b"
- integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==
- dependencies:
- "@babel/code-frame" "^7.27.1"
- "@babel/generator" "^7.28.0"
- "@babel/helper-globals" "^7.28.0"
- "@babel/parser" "^7.28.0"
- "@babel/template" "^7.27.2"
- "@babel/types" "^7.28.0"
- debug "^4.3.1"
-
-"@babel/traverse@^7.25.3", "@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0", "@babel/traverse@^7.7.0":
+"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.25.3", "@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0", "@babel/traverse@^7.7.0":
version "7.28.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b"
integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==
@@ -1973,7 +1960,7 @@
resolve-from "^5.0.0"
semver "^7.6.0"
-"@expo/image-utils@^0.7.6":
+"@expo/image-utils@^0.7.6", "@expo/image-utils@~0.7.4":
version "0.7.6"
resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.7.6.tgz#b8442bef770e1c7b39997d57f666bffeeced0a7a"
integrity sha512-GKnMqC79+mo/1AFrmAcUcGfbsXXTRqOMNS1umebuevl3aaw+ztsYEFEiuNhHZW7PQ3Xs3URNT513ZxKhznDscw==
@@ -6771,7 +6758,7 @@ ajv-keywords@^3.5.2:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-ajv-keywords@^5.0.0:
+ajv-keywords@^5.0.0, ajv-keywords@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16"
integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==
@@ -6798,6 +6785,16 @@ ajv@^8.0.0, ajv@^8.8.0:
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
+ajv@^8.9.0:
+ version "8.20.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.20.0.tgz#304b3636add88ba7d936760dd50ece006dea95f9"
+ integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+ fast-uri "^3.0.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+
algo-msgpack-with-bigint@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz#38bb717220525b3ff42232eefdcd9efb9ad405d6"
@@ -10621,6 +10618,15 @@ expo-modules-core@2.5.0:
dependencies:
invariant "^2.2.4"
+expo-quick-actions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/expo-quick-actions/-/expo-quick-actions-5.0.0.tgz#6b3c5c21190607f779be1588ebaf119577a3c120"
+ integrity sha512-NSsDhfbal11gXsHkJbvYVw7x0QUCKrEth2kBBKZUv03dX4J7ZPADSV89LyEpOVYXCkrw6LuanlEtKavg/BFaRA==
+ dependencies:
+ "@expo/image-utils" "~0.7.4"
+ schema-utils "^4.2.0"
+ sf-symbols-typescript "^2.1.0"
+
expo@^53.0.0:
version "53.0.20"
resolved "https://registry.yarnpkg.com/expo/-/expo-53.0.20.tgz#e11b553322de313d47c407367d8d48d3a073e3cc"
@@ -16414,6 +16420,16 @@ schema-utils@^4.0.0:
ajv-formats "^2.1.1"
ajv-keywords "^5.0.0"
+schema-utils@^4.2.0:
+ version "4.3.3"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46"
+ integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.9.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.1.0"
+
scrypt-js@3.0.1, scrypt-js@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312"
@@ -16658,6 +16674,11 @@ setprototypeof@1.2.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+sf-symbols-typescript@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/sf-symbols-typescript/-/sf-symbols-typescript-2.2.0.tgz#926d6e0715e3d8784cadf7658431e36581254208"
+ integrity sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw==
+
sha.js@^2.3.6, sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.12, sha.js@^2.4.8:
version "2.4.12"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f"
@@ -17138,16 +17159,7 @@ string-length@^4.0.2:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -17256,7 +17268,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -17270,13 +17282,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
strip-ansi@^7.0.0, strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -18664,7 +18669,7 @@ wordwrapjs@^4.0.0:
reduce-flatten "^2.0.0"
typical "^5.2.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18682,15 +18687,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"