diff --git a/android/app/src/main/java/com/robosats/MainActivity.kt b/android/app/src/main/java/com/robosats/MainActivity.kt index 41e02b56..3fdc0cfd 100644 --- a/android/app/src/main/java/com/robosats/MainActivity.kt +++ b/android/app/src/main/java/com/robosats/MainActivity.kt @@ -19,6 +19,8 @@ import android.webkit.WebSettings import android.webkit.WebStorage import android.webkit.WebView import android.webkit.WebViewClient +import android.content.Intent +import android.net.Uri import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout @@ -186,6 +188,38 @@ class MainActivity : AppCompatActivity() { runOnUiThread { updateStatus("Secure connection established. Loading app...") + // Set up WebViewClient that allows external links and deep links to be opened + webView.webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { + val url = request.url.toString() + val uri = request.url + + if (url.startsWith("file:///android_asset/")) return false + + try { + Log.d("ExternalLink", "Attempting to open: $url") + + val intent = Intent(Intent.ACTION_VIEW, uri) + if (intent.resolveActivity(packageManager) != null) { + startActivity(intent) + Log.d("ExternalLink", "Successfully opened link in external app") + } else { + Log.w("ExternalLink", "No app found to handle: $url") + if (url.startsWith("http://") || url.startsWith("https://")) { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + startActivity(browserIntent) + Log.d("ExternalLink", "Opened http/https link in browser") + } + } + + return true + } catch (e: Exception) { + Log.e("ExternalLink", "Failed to open external link: ${e.message}", e) + return true + } + } + } + // Set up WebChromeClient with restricted permissions webView.webChromeClient = object : WebChromeClient() { override fun onGeolocationPermissionsShowPrompt( diff --git a/android/app/src/main/java/com/robosats/WebAppInterface.kt b/android/app/src/main/java/com/robosats/WebAppInterface.kt index bd32caf3..dddfd2ea 100644 --- a/android/app/src/main/java/com/robosats/WebAppInterface.kt +++ b/android/app/src/main/java/com/robosats/WebAppInterface.kt @@ -319,7 +319,14 @@ class WebAppInterface(private val context: Context, private val webView: WebView } private fun onWsMessage(path: String?, message: String?) { - safeEvaluateJavascript("javascript:window.AndroidRobosats.onWSMessage('$path', '$message')") + val escapedMessage = message + ?.replace("\\", "\\\\") + ?.replace("'", "\\'") + ?.replace("\"", "\\\"") + ?.replace("\n", "\\n") + ?.replace("\r", "\\r") + ?.replace("\t", "\\t") + safeEvaluateJavascript("javascript:window.AndroidRobosats.onWSMessage('$path', '$escapedMessage')") } private fun onWsError(path: String?) { diff --git a/frontend/src/basic/TopBar/NotificationsDrawer/index.tsx b/frontend/src/basic/TopBar/NotificationsDrawer/index.tsx index 68ee7583..6b890e5d 100644 --- a/frontend/src/basic/TopBar/NotificationsDrawer/index.tsx +++ b/frontend/src/basic/TopBar/NotificationsDrawer/index.tsx @@ -23,7 +23,7 @@ import arraysAreDifferent from '../../../utils/array'; import getSettings from '../../../utils/settings'; const path = - getSettings().client == 'mobile' + getSettings().client === 'mobile' ? 'file:///android_asset/static/assets/sounds' : '/static/assets/sounds'; @@ -98,12 +98,18 @@ const NotificationsDrawer = ({ const soundType = soundByStatus[orderStatus] ?? 'ding'; const sound = audio[soundType]; + + void sound.play(); + void sound.play(); void sound.play(); }; const loadNotifciationsNostr = (): void => { const tokens = Object.keys(garage.slots); - if (!arraysAreDifferent(subscribedTokens, tokens)) return; + if (!arraysAreDifferent(subscribedTokens, tokens)) { + setLoading(false); + return; + } cleanUpNotifications(); setSubscribedTokens(tokens); diff --git a/frontend/src/components/TradeBox/EncryptedChat/EncryptedSocketChat/index.tsx b/frontend/src/components/TradeBox/EncryptedChat/EncryptedSocketChat/index.tsx index cb4a2b9c..55c62ed6 100644 --- a/frontend/src/components/TradeBox/EncryptedChat/EncryptedSocketChat/index.tsx +++ b/frontend/src/components/TradeBox/EncryptedChat/EncryptedSocketChat/index.tsx @@ -21,7 +21,7 @@ import { Send } from '@mui/icons-material'; const audioPath = getSettings().client == 'mobile' - ? 'file:///android_asset//static/assets/sounds' + ? 'file:///android_asset/static/assets/sounds' : '/static/assets/sounds'; interface Props { @@ -135,7 +135,7 @@ const EncryptedSocketChat: React.FC = ({ ); connection.onMessage((message) => { - setServerMessages((prev) => [...prev, message]); + setServerMessages((prev) => [...prev, message as ServerMessage]); }); connection.onClose(() => { setConnected(false);