From 771cae8a9a9dd62441644e02f182a46abe348151 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 18 Aug 2026 07:40:05 -0400 Subject: [PATCH] Add nopni capability detection when linking a device. --- .../linkdevice/LinkDeviceQrScanScreen.kt | 10 ++++++++ .../linkdevice/LinkDeviceSettingsState.kt | 2 +- .../linkdevice/LinkDeviceViewModel.kt | 24 +++++++++++++++---- app/src/main/res/values/strings.xml | 2 ++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceQrScanScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceQrScanScreen.kt index 50165564dc..bc28975100 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceQrScanScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceQrScanScreen.kt @@ -84,6 +84,16 @@ fun LinkDeviceQrScanScreen( onDismiss = onQrCodeDismissed ) } + + LinkDeviceSettingsState.QrCodeState.OUTDATED_DEVICE -> { + Dialogs.SimpleAlertDialog( + title = stringResource(id = R.string.AddLinkDeviceFragment__linking_device_failed), + body = stringResource(id = R.string.AddLinkDeviceFragment__the_device_you_are_trying_to_link_is_out_of_date), + confirm = stringResource(id = android.R.string.ok), + onConfirm = { }, + onDismiss = onQrCodeDismissed + ) + } } LaunchedEffect(linkDeviceResult) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt index db2e75b0ac..5b4728fbb0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt @@ -51,7 +51,7 @@ data class LinkDeviceSettingsState( } enum class QrCodeState { - NONE, VALID_WITH_SYNC, VALID_WITHOUT_SYNC, INVALID + NONE, VALID_WITH_SYNC, VALID_WITHOUT_SYNC, INVALID, OUTDATED_DEVICE } enum class SyncFailType { diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt index bc2a1dd6b1..6bc917d0f0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt @@ -171,9 +171,15 @@ class LinkDeviceViewModel : ViewModel() { val uri = Uri.parse(url) if (LinkDeviceRepository.isValidQr(uri)) { + val capabilities = uri.getCapabilities() + val qrCodeState = when { + Capability.Numberless !in capabilities && SignalStore.account.pni == null -> QrCodeState.OUTDATED_DEVICE + Capability.LinkAndSync in capabilities -> QrCodeState.VALID_WITH_SYNC + else -> QrCodeState.VALID_WITHOUT_SYNC + } _state.update { it.copy( - qrCodeState = if (uri.supportsLinkAndSync()) QrCodeState.VALID_WITH_SYNC else QrCodeState.VALID_WITHOUT_SYNC, + qrCodeState = qrCodeState, linkUri = uri ) } @@ -215,7 +221,7 @@ class LinkDeviceViewModel : ViewModel() { Log.i(TAG, "Adding device with sync.") addDeviceWithSync(linkUri) } else { - Log.i(TAG, "Adding device without sync. (uri: ${linkUri.supportsLinkAndSync()})") + Log.i(TAG, "Adding device without sync. (backup5: ${Capability.LinkAndSync in linkUri.getCapabilities()})") addDeviceWithoutSync(linkUri) } } @@ -413,9 +419,17 @@ class LinkDeviceViewModel : ViewModel() { LinkedDeviceInactiveCheckJob.enqueue() } - private fun Uri.supportsLinkAndSync(): Boolean { - val capabilities = this.getQueryParameter("capabilities")?.split(",")?.toSet() ?: emptySet() - return "backup5" in capabilities + private fun Uri.getCapabilities(): Set { + return this.getQueryParameter("capabilities") + ?.split(",") + ?.mapNotNull { value -> Capability.entries.firstOrNull { it.value == value } } + ?.toSet() + ?: emptySet() + } + + private enum class Capability(val value: String) { + LinkAndSync("backup5"), + Numberless("nopni") } fun onSyncErrorIgnored() = viewModelScope.launch(Dispatchers.IO) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ec3c3f0680..805270c7a1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1192,6 +1192,8 @@ This QR code is not valid. Please make sure you are scanning the QR code that is displayed on the device you want to link. Retry + + The device you\'re trying to link is out of date. Please upgrade and try again.