diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index b4b8247df2..da6c68ab76 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -270,11 +270,15 @@ class SimplexApp: Application(), LifecycleEventObserver { // Prevents from showing "Enable notifications" alert when onboarding wasn't complete yet if (chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete) { SimplexService.showBackgroundServiceNoticeIfNeeded() - PushManager.initStart(context) - if (appPrefs.notificationsMode.get() == NotificationsMode.SERVICE) - withBGApi { + when (appPrefs.notificationsMode.get()) { + NotificationsMode.SERVICE -> withBGApi { platform.androidServiceStart() } + NotificationsMode.INSTANT -> withBGApi { + PushManager.initStart(context) + } + else -> {} + } } } diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/platform/PushManager.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/platform/PushManager.kt index f1534cb1db..7d0a573489 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/platform/PushManager.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/platform/PushManager.kt @@ -24,12 +24,14 @@ import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.* import org.unifiedpush.android.connector.UnifiedPush +import androidx.core.net.toUri /** * Object with functions to interact with push services */ object PushManager { private const val TAG = "PushManager" + private val VAPID_REGEX = Regex("^[A-Za-z0-9_-]{87}(=+)?$") /** * Check if a NTF server is setup and ask user's push distributor @@ -42,12 +44,20 @@ object PushManager { suspend fun initUnifiedPush(context: Context, scope: CoroutineScope, onSuccess: () -> Unit) { val rh = chatModel.remoteHostId() val userServers = getUserServers(rh) ?: listOf() - if (!userServers.hasNtfServer()) { + val userNtfServer = userServers.userNtfServer() + ?: run { Log.d(TAG, "User doesn't have any NTF server") showMissingNTFDialog(scope, rh, userServers) // After coming back from the server view, users will have to click on "Instant" again return } + val vapid = userNtfServer.vapid() + ?: run { + Log.d(TAG, "User NTF Server doesn't have any VAPID FP") + showNTFNoVAPIDDialog(scope, rh, userServers) + // After coming back from the server view, users will have to click on "Instant" again + return + } val distributors = UnifiedPush.getDistributors(context) when (distributors.size) { 0 -> { @@ -57,7 +67,7 @@ object PushManager { 1 -> { Log.d(TAG, "Found only one distributor installed") UnifiedPush.saveDistributor(context, distributors.first()) - register(context) + register(context, vapid) onSuccess() } else -> { @@ -65,7 +75,7 @@ object PushManager { showSelectPushServiceIntroDialog { showSelectPushServiceDialog(context, distributors) { UnifiedPush.saveDistributor(context, it) - register(context) + register(context, vapid) onSuccess() } } @@ -79,27 +89,40 @@ object PushManager { * To run when the app starts; call [chat.simplex.app.PushService.onUnregistered] * if the distributor is uninstalled */ - fun initStart(context: Context) { + suspend fun initStart(context: Context) { Log.d(TAG, "Init UnifiedPush during app startup") //TODO: limit to once a day to reduce registrations to ntf server ? UnifiedPush.getAckDistributor(context)?.let { - register(context) + val vapid = getUserServers(chatModel.remoteHostId()) + ?.userNtfServer() + ?.vapid() + // Unregister if the user deleted the ntf server or change it with one without vapid + ?: return UnifiedPush.unregister(context) + register(context, vapid) } } - private fun register(context: Context) { - // TODO: add VAPID - UnifiedPush.register(context) + private fun register(context: Context, vapid: String) { + UnifiedPush.register(context, vapid = vapid) } /** - * Check if any NTF server is recorded + * Get user NTF server */ - private fun List.hasNtfServer(): Boolean { - // TODO: check if ntf server has a VAPID key - return this.any { it.ntfServers.any { s -> s.enabled } } + private fun List.userNtfServer(): UserServer? { + return this.firstNotNullOfOrNull { + it.ntfServers.firstOrNull { s -> s.enabled } + } } + /** + * Get vapid fingerprint from the URI + */ + private fun UserServer.vapid(): String ? = server + .toUri() + .getQueryParameter("vapid") + ?.takeIf { VAPID_REGEX.matches(it) } + /** * Show a dialog to inform about missing NTF server */ @@ -136,6 +159,41 @@ object PushManager { ) } + /** + * Show a dialog to inform about missing VAPID with the NTF server + */ + private fun showNTFNoVAPIDDialog(scope: CoroutineScope, rh: Long?, userServers: List) = AlertManager.shared.showAlert { + AlertDialog( + onDismissRequest = AlertManager.shared::hideAlert, + title = { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + Icon( + painterResource(MR.images.ic_warning), + contentDescription = null, // The icon doesn't add any meaning and must not be transcripted with screen readers + ) + Text( + stringResource(MR.strings.icon_descr_instant_notifications), + fontWeight = FontWeight.Bold + ) + } + }, + text = { + Text(stringResource(MR.strings.warning_push_needs_ntf_server_with_vapid)) + }, + // Go to user's servers settings + confirmButton = { + TextButton(onClick = { + AlertManager.shared.hideAlert() + showAddServerDialog(scope, rh, userServers) + }) { Text(stringResource(MR.strings.smp_servers_add)) } + }, + // Ignore + dismissButton = { + TextButton(onClick = AlertManager.shared::hideAlert) { Text(stringResource(android.R.string.cancel)) } + }, + shape = RoundedCornerShape(corner = CornerSize(25.dp)) + ) + } /** * Dialog to add a server, manually or with a QR code */ diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index 5879f49218..2987ff9aca 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -277,7 +277,9 @@ Connected Error showing notification, contact developers. You first need to set a NTF server to get push notifications.\n\nIt will send the notifications to your push provider. + Your NTF server doesn\'t support VAPID, which is required to get push notifications. You don\'t have any push service installed on your device.\n\nPlease installed one and try again.\n\nFor more information, visit\ + Your NTF server has been removed or has changed and doesn\'t support VAPID, which is required to get push notifications. Select Push Service Multiple push services are installed on your system, please select the service you wish to use. SimpleX is no longer registered with your UnifiedPush distributor. The distributor may have been uninstalled or been logged out. You should reset your notifications settings. diff --git a/cabal.project b/cabal.project index 9c1b8a8c8d..3eb7d516f8 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://codeberg.org/s1m/sxmq.git - tag: a9ef465c0af3829c58fb5e45627d9673aa5b1ee7 + tag: f28a2052ae88c59653993ca0e409231b5ed00b11 -- source-repository-package -- type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index d4dfe1e5c2..e4a0d027b2 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://codeberg.org/s1m/sxmq.git"."a9ef465c0af3829c58fb5e45627d9673aa5b1ee7" = "5921e554cd08372335a415d7c6edcb8d83893f77fffcf5370edaaff7fe47bea6"; + "https://codeberg.org/s1m/sxmq.git"."f28a2052ae88c59653993ca0e409231b5ed00b11" = "86128d5cdb952e28460b4450042622807e0b683de5598817cac80e85ecee8c3f"; "https://github.com/simplex-chat/simplexmq.git"."d352d518c2b3a42bc7a298954dde799422e1457f" = "1rha84pfpaqx3mf218szkfra334vhijqf17hanxqmp1sicfbf1x3"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";