Skip to content

Commit 41caec7

Browse files
committed
Add home screen long-press shortcuts for iOS and Android
Add two static quick actions visible on long-press of the app icon: 1. "Save 2FA First!" - warns users to preserve credentials before uninstalling, links to the support article on getting a new phone. 2. "Contact Support" - opens the support chat page. On iOS, shortcuts are defined in Info.plist with localized titles via InfoPlist.strings, and handled in AppDelegate with the canonical return-false pattern to prevent double-delivery on cold start. On Android, shortcuts are declared in res/xml/shortcuts.xml and referenced from AndroidManifest.xml. URLs that aren't registered deep link hosts are routed to the default browser via maybeOpenInBrowser. Made-with: Cursor
1 parent 20715bd commit 41caec7

8 files changed

Lines changed: 150 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased (develop)
44

5+
- added: Home screen long-press shortcut to contact support
6+
- added: Home screen long-press shortcut warning about 2FA and credentials needed after uninstall
7+
58
## 4.47.0 (staging)
69

710
- added: Include Zano sweep private key support for ZANO and tokens.

android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
<category android:name="android.intent.category.BROWSABLE" />
9393
<data android:scheme="wc" />
9494
</intent-filter>
95+
<meta-data
96+
android:name="android.app.shortcuts"
97+
android:resource="@xml/shortcuts" />
9598
</activity>
9699

97100
<!-- To disable the activity lifecycle breadcrumbs integration -->

android/app/src/main/java/co/edgesecure/app/MainActivity.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package co.edgesecure.app
22

3+
import android.content.Intent
34
import android.content.pm.ActivityInfo
45
import android.os.Build
56
import android.os.Bundle
@@ -38,6 +39,43 @@ class MainActivity : ReactActivity() {
3839
if (resources.getBoolean(R.bool.portrait_only)) {
3940
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
4041
}
42+
43+
if (maybeOpenInBrowser(intent)) {
44+
intent.data = null
45+
}
46+
}
47+
48+
override fun onNewIntent(intent: Intent) {
49+
if (!maybeOpenInBrowser(intent)) {
50+
super.onNewIntent(intent)
51+
}
52+
}
53+
54+
/**
55+
* Opens https/http URLs in the default browser when they aren't
56+
* registered deep link hosts handled by React Native. This prevents
57+
* shortcut intents from being misrouted through the deep link handler.
58+
* Returns true if the URL was opened in the browser.
59+
*/
60+
private fun maybeOpenInBrowser(intent: Intent?): Boolean {
61+
val data = intent?.data ?: return false
62+
val scheme = data.scheme
63+
if (scheme != "https" && scheme != "http") return false
64+
65+
val host = data.host
66+
if (DEEP_LINK_HOSTS.contains(host)) return false
67+
68+
val browserIntent = Intent(Intent.ACTION_VIEW, data)
69+
startActivity(browserIntent)
70+
return true
71+
}
72+
73+
companion object {
74+
private val DEEP_LINK_HOSTS = setOf(
75+
"deep.edge.app",
76+
"dl.edge.app",
77+
"return.edge.app"
78+
)
4179
}
4280

4381
// Edge addition
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
<resources>
22
<string name="app_name">Edge</string>
3+
<string name="shortcut_contact_support_short">Contact Support</string>
4+
<string name="shortcut_contact_support_long">Contact support for help from a live agent</string>
5+
<string name="shortcut_do_not_uninstall_short">⚠️ Save 2FA First!</string>
6+
<string name="shortcut_do_not_uninstall_long">⚠️ Login requires 2FA &amp; credentials!</string>
37
</resources>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
3+
<shortcut
4+
android:shortcutId="do_not_uninstall"
5+
android:enabled="true"
6+
android:icon="@android:drawable/ic_dialog_alert"
7+
android:shortcutShortLabel="@string/shortcut_do_not_uninstall_short"
8+
android:shortcutLongLabel="@string/shortcut_do_not_uninstall_long">
9+
<intent
10+
android:action="android.intent.action.VIEW"
11+
android:data="https://support.edge.app/en/articles/14439418-warning-don-t-uninstall-edge-without-your-login-credentials" />
12+
</shortcut>
13+
<shortcut
14+
android:shortcutId="contact_support"
15+
android:enabled="true"
16+
android:icon="@android:drawable/ic_menu_help"
17+
android:shortcutShortLabel="@string/shortcut_contact_support_short"
18+
android:shortcutLongLabel="@string/shortcut_contact_support_long">
19+
<intent
20+
android:action="android.intent.action.VIEW"
21+
android:data="https://support.edge.app/en/articles/14054649-need-help-reach-out-via-our-chat-bubble?chat=open" />
22+
</shortcut>
23+
</shortcuts>

ios/edge/AppDelegate.swift

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1212
var window: UIWindow?
1313
var securityView: UIView?
1414

15+
// Deferred until React Native is fully initialized in didFinishLaunchingWithOptions
16+
private var pendingShortcutItem: UIApplicationShortcutItem?
17+
1518
var reactNativeDelegate: ReactNativeDelegate?
1619
var reactNativeFactory: RCTReactNativeFactory?
1720

@@ -49,6 +52,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
4952
_ application: UIApplication,
5053
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
5154
) -> Bool {
55+
let launchedFromShortcut = launchOptions?[.shortcutItem] is UIApplicationShortcutItem
56+
if let shortcutItem = launchOptions?[.shortcutItem] as? UIApplicationShortcutItem {
57+
pendingShortcutItem = shortcutItem
58+
}
59+
5260
// Initialize SDK's:
5361
initializeSentry()
5462
FirebaseApp.configure()
@@ -72,7 +80,37 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
7280
launchOptions: launchOptions
7381
)
7482

75-
return true
83+
if let shortcutItem = pendingShortcutItem {
84+
_ = handleShortcutItem(shortcutItem)
85+
pendingShortcutItem = nil
86+
}
87+
88+
return !launchedFromShortcut
89+
}
90+
91+
func application(
92+
_ application: UIApplication,
93+
performActionFor shortcutItem: UIApplicationShortcutItem,
94+
completionHandler: @escaping (Bool) -> Void
95+
) {
96+
let handled = handleShortcutItem(shortcutItem)
97+
completionHandler(handled)
98+
}
99+
100+
private func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) -> Bool {
101+
guard let urlString = shortcutItem.userInfo?["url"] as? String,
102+
let url = URL(string: urlString) else { return false }
103+
104+
if url.scheme == "https" || url.scheme == "http" {
105+
UIApplication.shared.open(url, options: [:]) { success in
106+
if !success {
107+
print("Failed to open shortcut URL: \(urlString)")
108+
}
109+
}
110+
return true
111+
}
112+
113+
return RCTLinkingManager.application(UIApplication.shared, open: url, options: [:])
76114
}
77115

78116
/**

ios/edge/Info.plist

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,39 @@
5757
</array>
5858
<key>CFBundleVersion</key>
5959
<string>99999999</string>
60+
<key>UIApplicationShortcutItems</key>
61+
<array>
62+
<dict>
63+
<key>UIApplicationShortcutItemTitle</key>
64+
<string>SHORTCUT_UNINSTALL_TITLE</string>
65+
<key>UIApplicationShortcutItemSubtitle</key>
66+
<string>SHORTCUT_UNINSTALL_SUBTITLE</string>
67+
<key>UIApplicationShortcutItemIconSymbolName</key>
68+
<string>nosign</string>
69+
<key>UIApplicationShortcutItemType</key>
70+
<string>co.edgesecure.app.do_not_uninstall</string>
71+
<key>UIApplicationShortcutItemUserInfo</key>
72+
<dict>
73+
<key>url</key>
74+
<string>https://support.edge.app/en/articles/14439418-warning-don-t-uninstall-edge-without-your-login-credentials</string>
75+
</dict>
76+
</dict>
77+
<dict>
78+
<key>UIApplicationShortcutItemTitle</key>
79+
<string>SHORTCUT_SUPPORT_TITLE</string>
80+
<key>UIApplicationShortcutItemSubtitle</key>
81+
<string>SHORTCUT_SUPPORT_SUBTITLE</string>
82+
<key>UIApplicationShortcutItemIconSymbolName</key>
83+
<string>message.fill</string>
84+
<key>UIApplicationShortcutItemType</key>
85+
<string>co.edgesecure.app.contact_support</string>
86+
<key>UIApplicationShortcutItemUserInfo</key>
87+
<dict>
88+
<key>url</key>
89+
<string>https://support.edge.app/en/articles/14054649-need-help-reach-out-via-our-chat-bubble?chat=open</string>
90+
</dict>
91+
</dict>
92+
</array>
6093
<key>LSApplicationQueriesSchemes</key>
6194
<array>
6295
<string>https</string>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* Home screen shortcut: uninstall warning */
2+
"SHORTCUT_UNINSTALL_TITLE" = "⚠️ Save 2FA First!";
3+
"SHORTCUT_UNINSTALL_SUBTITLE" = "Login requires 2FA & credentials!";
4+
5+
/* Home screen shortcut: contact support */
6+
"SHORTCUT_SUPPORT_TITLE" = "Contact Support";
7+
"SHORTCUT_SUPPORT_SUBTITLE" = "Get help from our live support agents";

0 commit comments

Comments
 (0)