feat: Add support for sharing contacts via deeplink (#2336)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2025-07-03 12:42:04 +00:00 committed by GitHub
parent 91dd6dbef4
commit 25111552eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 4 deletions

View file

@ -69,6 +69,7 @@ import com.geeksville.mesh.ui.MainMenuAction
import com.geeksville.mesh.ui.MainScreen
import com.geeksville.mesh.ui.common.theme.AppTheme
import com.geeksville.mesh.ui.common.theme.MODE_DYNAMIC
import com.geeksville.mesh.ui.sharing.toSharedContact
import com.geeksville.mesh.ui.intro.AppIntroductionScreen
import com.geeksville.mesh.util.Exceptions
import com.geeksville.mesh.util.LanguageUtils
@ -186,6 +187,12 @@ class MainActivity : AppCompatActivity(), Logging {
) {
debug("App link data is a channel set")
model.requestChannelUrl(it)
} else if (it.path?.startsWith("/v/") == true ||
it.path?.startsWith("/V/") == true
) {
val sharedContact = it.toSharedContact()
debug("App link data is a shared contact: ${sharedContact.user.longName}")
model.setSharedContactRequested(sharedContact)
} else {
debug("App link data is not a channel set")
}

View file

@ -623,6 +623,15 @@ class UIViewModel @Inject constructor(
radioConfigRepository.onServiceAction(ServiceAction.Reaction(emoji, replyId, contactKey))
}
private val _sharedContactRequested: MutableStateFlow<AdminProtos.SharedContact?> =
MutableStateFlow(null)
val sharedContactRequested: StateFlow<AdminProtos.SharedContact?> get() = _sharedContactRequested.asStateFlow()
fun setSharedContactRequested(sharedContact: AdminProtos.SharedContact?) {
viewModelScope.launch {
_sharedContactRequested.value = sharedContact
}
}
fun addSharedContact(sharedContact: AdminProtos.SharedContact) = viewModelScope.launch {
radioConfigRepository.onServiceAction(ServiceAction.AddSharedContact(sharedContact))
}

View file

@ -53,6 +53,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.AdminProtos
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.R
@ -82,7 +83,7 @@ fun AddContactFAB(
onSharedContactImport: (AdminProtos.SharedContact) -> Unit = {},
) {
val context = LocalContext.current
var contactToImport: AdminProtos.SharedContact? by remember { mutableStateOf(null) }
val contactToImport: AdminProtos.SharedContact? by model.sharedContactRequested.collectAsStateWithLifecycle(null)
val barcodeLauncher = rememberLauncherForActivityResult(ScanContract()) { result ->
if (result.contents != null) {
@ -94,7 +95,7 @@ fun AddContactFAB(
null
}
if (sharedContact != null) {
contactToImport = sharedContact
model.setSharedContactRequested(sharedContact)
}
}
}
@ -134,12 +135,12 @@ fun AddContactFAB(
},
dismissText = stringResource(R.string.cancel),
onDismiss = {
contactToImport = null
model.setSharedContactRequested(null)
},
confirmText = stringResource(R.string.import_label),
onConfirm = {
onSharedContactImport(contactToImport!!)
contactToImport = null
model.setSharedContactRequested(null)
}
)
}