diff --git a/datalayer/phone-ui/api/current.api b/datalayer/phone-ui/api/current.api
index 5bd6437fc8..be0b85995f 100644
--- a/datalayer/phone-ui/api/current.api
+++ b/datalayer/phone-ui/api/current.api
@@ -16,7 +16,7 @@ package com.google.android.horologist.datalayer.phone.ui.prompt.installapp {
@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class InstallAppPrompt {
ctor public InstallAppPrompt(com.google.android.horologist.datalayer.phone.PhoneDataLayerAppHelper phoneDataLayerAppHelper);
method public android.content.Intent getIntent(android.content.Context context, String appPackageName, @DrawableRes int image, String topMessage, String bottomMessage);
- method public suspend Object? shouldDisplayPrompt(kotlin.coroutines.Continuation super com.google.android.horologist.data.apphelper.AppHelperNodeStatus>);
+ method public suspend Object? shouldDisplayPrompt(optional kotlin.jvm.functions.Function1 super com.google.android.horologist.data.apphelper.AppHelperNodeStatus,java.lang.Boolean>? predicate, optional kotlin.coroutines.Continuation super com.google.android.horologist.data.apphelper.AppHelperNodeStatus>);
}
}
diff --git a/datalayer/phone-ui/src/main/java/com/google/android/horologist/datalayer/phone/ui/prompt/installapp/InstallAppPrompt.kt b/datalayer/phone-ui/src/main/java/com/google/android/horologist/datalayer/phone/ui/prompt/installapp/InstallAppPrompt.kt
index 5af28720f6..d4e41dd8e3 100644
--- a/datalayer/phone-ui/src/main/java/com/google/android/horologist/datalayer/phone/ui/prompt/installapp/InstallAppPrompt.kt
+++ b/datalayer/phone-ui/src/main/java/com/google/android/horologist/datalayer/phone/ui/prompt/installapp/InstallAppPrompt.kt
@@ -29,13 +29,25 @@ import com.google.android.horologist.datalayer.phone.PhoneDataLayerAppHelper
@ExperimentalHorologistApi
public class InstallAppPrompt(private val phoneDataLayerAppHelper: PhoneDataLayerAppHelper) {
-
/**
* Returns a [AppHelperNodeStatus] that meets the criteria to show this prompt, otherwise
* returns null.
+ *
+ * @param predicate augments the criteria applying a [filter][List.filter] with this predicate.
*/
- public suspend fun shouldDisplayPrompt(): AppHelperNodeStatus? =
- phoneDataLayerAppHelper.connectedNodes().firstOrNull { !it.appInstalled }
+ public suspend fun shouldDisplayPrompt(
+ predicate: ((AppHelperNodeStatus) -> Boolean)? = null,
+ ): AppHelperNodeStatus? =
+ phoneDataLayerAppHelper.connectedNodes()
+ .filter { !it.appInstalled }
+ .let {
+ if (predicate != null) {
+ it.filter(predicate)
+ } else {
+ it
+ }
+ }
+ .firstOrNull()
/**
* Returns the [Intent] to display an install app prompt to the user.
diff --git a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoScreen.kt b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoScreen.kt
index 3c20a83cf6..b2f9ca4728 100644
--- a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoScreen.kt
+++ b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoScreen.kt
@@ -21,13 +21,18 @@ import android.content.Intent
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
+import androidx.compose.material3.Checkbox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -75,7 +80,7 @@ fun InstallAppPromptDemoScreen(
@Composable
fun InstallAppPromptDemoScreen(
state: InstallAppPromptDemoScreenState,
- onRunDemoClick: () -> Unit,
+ onRunDemoClick: (shouldFilterByNearby: Boolean) -> Unit,
getInstallPromptIntent: () -> Intent,
onInstallPromptLaunched: () -> Unit,
onInstallPromptInstallClick: () -> Unit,
@@ -92,13 +97,23 @@ fun InstallAppPromptDemoScreen(
}
}
+ var shouldFilterByNearby by remember { mutableStateOf(false) }
+
Column(
modifier = modifier.padding(all = 10.dp),
) {
Text(text = stringResource(id = R.string.install_app_prompt_api_call_demo_message))
+ Row(
+ modifier = Modifier.padding(top = 10.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Checkbox(checked = shouldFilterByNearby, onCheckedChange = { shouldFilterByNearby = it })
+ Text(text = stringResource(id = R.string.install_app_prompt_checkbox_label))
+ }
+
Button(
- onClick = onRunDemoClick,
+ onClick = { onRunDemoClick(shouldFilterByNearby) },
modifier = Modifier
.padding(top = 10.dp)
.align(Alignment.CenterHorizontally),
diff --git a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoViewModel.kt b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoViewModel.kt
index 8dccca6441..b40f6e1afc 100644
--- a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoViewModel.kt
+++ b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/screens/inappprompts/installapp/InstallAppPromptDemoViewModel.kt
@@ -19,6 +19,7 @@ package com.google.android.horologist.datalayer.sample.screens.inappprompts.inst
import androidx.annotation.MainThread
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import com.google.android.horologist.data.apphelper.AppHelperNodeStatus
import com.google.android.horologist.datalayer.phone.PhoneDataLayerAppHelper
import com.google.android.horologist.datalayer.phone.ui.prompt.installapp.InstallAppPrompt
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -57,11 +58,16 @@ class InstallAppPromptDemoViewModel
}
}
- fun onRunDemoClick() {
+ fun onRunDemoClick(shouldFilterByNearby: Boolean) {
_uiState.value = InstallAppPromptDemoScreenState.Loading
viewModelScope.launch {
- val node = installAppPrompt.shouldDisplayPrompt()
+ val filter = if (shouldFilterByNearby) {
+ { node: AppHelperNodeStatus -> node.isNearby }
+ } else {
+ null
+ }
+ val node = installAppPrompt.shouldDisplayPrompt(filter)
_uiState.value = if (node != null) {
InstallAppPromptDemoScreenState.WatchFound
diff --git a/datalayer/sample/phone/src/main/res/values/strings.xml b/datalayer/sample/phone/src/main/res/values/strings.xml
index 7e64025c58..6e881e1ed5 100644
--- a/datalayer/sample/phone/src/main/res/values/strings.xml
+++ b/datalayer/sample/phone/src/main/res/values/strings.xml
@@ -63,6 +63,7 @@
This demo calls the Horologist API to show the install app prompt for the watch demo app. The API will only display the prompt if there is a watch connected and the watch does not have the app installed.\n\nGoogle Play won\'t find this app as it is not published.
+ Filter by nearby watches
Run demo
Test the interactions between the phone and the watch with the demo app.
Install the demo app on your Wear OS watch.