From b7e15933062ea22563dea40fe8a700b4c05ed1cd Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 30 Apr 2026 11:52:10 -0500 Subject: [PATCH] feat(android): update notification handling and UI responsiveness with new audio settings permission and improved back navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Credit: thanks to Sergey B (Samara Telegram - Reticulum Самара) for testing and providing solutions. --- android/app/src/main/AndroidManifest.xml | 3 +- .../meshchatx/AndroidNotificationBridge.java | 29 ++++--- .../main/java/com/meshchatx/MainActivity.java | 82 +++++++++++++------ .../com/meshchatx/MeshChatApplication.java | 2 +- 4 files changed, 77 insertions(+), 39 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index fb0160a..c3dc9d1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + @@ -43,7 +44,7 @@ android:name=".MainActivity" android:exported="true" android:launchMode="singleTask" - android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|density|uiMode|keyboard|keyboardHidden|navigation"> + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|density|fontScale|keyboard|keyboardHidden|navigation|uiMode|colorMode|layoutDirection"> diff --git a/android/app/src/main/java/com/meshchatx/AndroidNotificationBridge.java b/android/app/src/main/java/com/meshchatx/AndroidNotificationBridge.java index f721832..ebaec61 100644 --- a/android/app/src/main/java/com/meshchatx/AndroidNotificationBridge.java +++ b/android/app/src/main/java/com/meshchatx/AndroidNotificationBridge.java @@ -229,6 +229,22 @@ public final class AndroidNotificationBridge { PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); + int id = NOTIFY_BASE_ID; + if (dedupeHex != null && dedupeHex.length() >= 8) { + try { + id = NOTIFY_BASE_ID + + (int) (Long.parseLong( + dedupeHex.substring(0, Math.min(8, dedupeHex.length())), 16) & 0x7fff_ffff); + } catch (NumberFormatException ignored) { + id = NOTIFY_BASE_ID + (dedupeHex.hashCode() & 0x7fff_ffff); + } + } + + try { + nm.cancel(id); + } catch (Exception ignored) { + } + NotificationCompat.Builder b = new NotificationCompat.Builder(ctx, MeshChatApplication.CHANNEL_ID_MESSAGES) .setSmallIcon(R.drawable.ic_stat_meshchatx) .setContentTitle(title) @@ -237,16 +253,9 @@ public final class AndroidNotificationBridge { .setContentIntent(pi) .setAutoCancel(true) .setCategory(NotificationCompat.CATEGORY_MESSAGE) - .setVisibility(NotificationCompat.VISIBILITY_PRIVATE); - - int id = NOTIFY_BASE_ID; - if (dedupeHex != null && dedupeHex.length() >= 8) { - try { - id = NOTIFY_BASE_ID + (int) (Long.parseLong(dedupeHex.substring(0, Math.min(8, dedupeHex.length())), 16) & 0x7fff_ffff); - } catch (NumberFormatException ignored) { - id = NOTIFY_BASE_ID + (dedupeHex.hashCode() & 0x7fff_ffff); - } - } + .setVisibility(NotificationCompat.VISIBILITY_PRIVATE) + .setDefaults(NotificationCompat.DEFAULT_ALL) + .setOnlyAlertOnce(false); try { nm.notify(id, b.build()); diff --git a/android/app/src/main/java/com/meshchatx/MainActivity.java b/android/app/src/main/java/com/meshchatx/MainActivity.java index 9f9acab..371d312 100644 --- a/android/app/src/main/java/com/meshchatx/MainActivity.java +++ b/android/app/src/main/java/com/meshchatx/MainActivity.java @@ -32,6 +32,7 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import androidx.activity.OnBackPressedCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.core.app.ActivityCompat; @@ -196,33 +197,35 @@ public class MainActivity extends AppCompatActivity { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); - if (!isStartupRequest(url)) { + if (!startupPageLoaded) { + if (!isStartupRequest(url)) { + return; + } + if (startupRequestHadLoadError) { + return; + } + startupPageLoaded = true; + mainHandler.removeCallbacksAndMessages(null); + hideStartupLoadingOverlay(); + dispatchPendingIntentUri(); + dispatchCallNotificationAction(); return; } - if (startupRequestHadLoadError) { - return; - } - startupPageLoaded = true; - mainHandler.removeCallbacksAndMessages(null); - webView.setVisibility(android.view.View.VISIBLE); - loadingLogo.setVisibility(android.view.View.GONE); - progressBar.setVisibility(android.view.View.GONE); - loadingText.setVisibility(android.view.View.GONE); - errorText.setVisibility(android.view.View.GONE); - dispatchPendingIntentUri(); - dispatchCallNotificationAction(); + hideStartupLoadingOverlay(); } @Override public void onPageStarted(WebView view, String url, android.graphics.Bitmap favicon) { super.onPageStarted(view, url, favicon); - if (isStartupRequest(url)) { + if (!startupPageLoaded && isStartupRequest(url)) { startupRequestHadLoadError = false; - if (!startupPageLoaded) { - webView.setVisibility(android.view.View.INVISIBLE); - } + webView.setVisibility(android.view.View.INVISIBLE); + progressBar.setVisibility(android.view.View.VISIBLE); + return; + } + if (!startupPageLoaded) { + progressBar.setVisibility(android.view.View.VISIBLE); } - progressBar.setVisibility(android.view.View.VISIBLE); } @Override @@ -371,6 +374,22 @@ public class MainActivity extends AppCompatActivity { handleIncomingIntent(getIntent()); consumeCallIntentForPending(getIntent()); + getOnBackPressedDispatcher().addCallback( + this, + new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + if (webView != null && webView.canGoBack()) { + webView.goBack(); + } else { + setEnabled(false); + MainActivity.this.getOnBackPressedDispatcher().onBackPressed(); + setEnabled(true); + } + } + } + ); + startMeshChatServer(); scheduleConnectionRetry("Connecting to local server..."); } @@ -674,6 +693,24 @@ public class MainActivity extends AppCompatActivity { return sw.toString(); } + private void hideStartupLoadingOverlay() { + if (webView != null) { + webView.setVisibility(android.view.View.VISIBLE); + } + if (loadingLogo != null) { + loadingLogo.setVisibility(android.view.View.GONE); + } + if (progressBar != null) { + progressBar.setVisibility(android.view.View.GONE); + } + if (loadingText != null) { + loadingText.setVisibility(android.view.View.GONE); + } + if (errorText != null && !backendFailed) { + errorText.setVisibility(android.view.View.GONE); + } + } + private void showStartupError(String message) { runOnUiThread(() -> { mainHandler.removeCallbacksAndMessages(null); @@ -718,15 +755,6 @@ public class MainActivity extends AppCompatActivity { return phase + " (" + connectionAttempts + "/" + MAX_CONNECTION_ATTEMPTS + ")"; } - @Override - public void onBackPressed() { - if (webView.canGoBack()) { - webView.goBack(); - } else { - super.onBackPressed(); - } - } - @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); diff --git a/android/app/src/main/java/com/meshchatx/MeshChatApplication.java b/android/app/src/main/java/com/meshchatx/MeshChatApplication.java index 371df98..9702a4b 100644 --- a/android/app/src/main/java/com/meshchatx/MeshChatApplication.java +++ b/android/app/src/main/java/com/meshchatx/MeshChatApplication.java @@ -51,7 +51,7 @@ public class MeshChatApplication extends PyApplication { NotificationChannel messages = new NotificationChannel( CHANNEL_ID_MESSAGES, getString(R.string.notification_channel_messages_name), - NotificationManager.IMPORTANCE_DEFAULT + NotificationManager.IMPORTANCE_HIGH ); messages.setDescription(getString(R.string.notification_channel_messages_desc)); nm.createNotificationChannel(messages);