Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve AppHelperNodeStatus #1827

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 31 additions & 15 deletions datalayer/core/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -93,31 +93,47 @@ package com.google.android.horologist.data {
package com.google.android.horologist.data.apphelper {

public final class AppHelperNodeStatus {
ctor public AppHelperNodeStatus(String id, String displayName, boolean isAppInstalled, com.google.android.horologist.data.apphelper.AppHelperNodeType nodeType, optional error.NonExistentClass surfacesInfo);
ctor public AppHelperNodeStatus(String id, String displayName, com.google.android.horologist.data.apphelper.AppInstallationStatus appInstallationStatus, optional error.NonExistentClass surfacesInfo);
method public String component1();
method public String component2();
method public boolean component3();
method public com.google.android.horologist.data.apphelper.AppHelperNodeType component4();
method public error.NonExistentClass! component5();
method public com.google.android.horologist.data.apphelper.AppHelperNodeStatus copy(String id, String displayName, boolean isAppInstalled, com.google.android.horologist.data.apphelper.AppHelperNodeType nodeType, error.NonExistentClass! surfacesInfo);
method public com.google.android.horologist.data.apphelper.AppInstallationStatus component3();
method public error.NonExistentClass! component4();
method public com.google.android.horologist.data.apphelper.AppHelperNodeStatus copy(String id, String displayName, com.google.android.horologist.data.apphelper.AppInstallationStatus appInstallationStatus, error.NonExistentClass! surfacesInfo);
method public com.google.android.horologist.data.apphelper.AppInstallationStatus getAppInstallationStatus();
method public String getDisplayName();
method public String getId();
method public com.google.android.horologist.data.apphelper.AppHelperNodeType getNodeType();
method public error.NonExistentClass! getSurfacesInfo();
method public boolean isAppInstalled();
property public final com.google.android.horologist.data.apphelper.AppInstallationStatus appInstallationStatus;
property public final String displayName;
property public final String id;
property public final boolean isAppInstalled;
property public final com.google.android.horologist.data.apphelper.AppHelperNodeType nodeType;
property public final error.NonExistentClass! surfacesInfo;
}

public enum AppHelperNodeType {
method public static com.google.android.horologist.data.apphelper.AppHelperNodeType valueOf(String name) throws java.lang.IllegalArgumentException;
method public static com.google.android.horologist.data.apphelper.AppHelperNodeType[] values();
enum_constant public static final com.google.android.horologist.data.apphelper.AppHelperNodeType PHONE;
enum_constant public static final com.google.android.horologist.data.apphelper.AppHelperNodeType UNKNOWN;
enum_constant public static final com.google.android.horologist.data.apphelper.AppHelperNodeType WATCH;
public final class AppHelperNodeStatusKt {
method public static boolean getAppInstalled(com.google.android.horologist.data.apphelper.AppHelperNodeStatus);
}

public abstract sealed class AppInstallationStatus {
}

public static final class AppInstallationStatus.Installed extends com.google.android.horologist.data.apphelper.AppInstallationStatus {
ctor public AppInstallationStatus.Installed(com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType nodeType);
method public com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType component1();
method public com.google.android.horologist.data.apphelper.AppInstallationStatus.Installed copy(com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType nodeType);
method public com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType getNodeType();
property public final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType nodeType;
}

public static final class AppInstallationStatus.NotInstalled extends com.google.android.horologist.data.apphelper.AppInstallationStatus {
field public static final com.google.android.horologist.data.apphelper.AppInstallationStatus.NotInstalled INSTANCE;
}

public enum AppInstallationStatusNodeType {
method public static com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType valueOf(String name) throws java.lang.IllegalArgumentException;
method public static com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType[] values();
enum_constant public static final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType PHONE;
enum_constant public static final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType UNKNOWN;
enum_constant public static final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType WATCH;
}

public abstract class DataLayerAppHelper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,28 @@ import com.google.android.horologist.data.SurfacesInfo
public data class AppHelperNodeStatus(
val id: String,
val displayName: String,
val isAppInstalled: Boolean,
val nodeType: AppHelperNodeType,
val appInstallationStatus: AppInstallationStatus,
val surfacesInfo: SurfacesInfo = SurfacesInfo.getDefaultInstance(),
)

public enum class AppHelperNodeType {
UNKNOWN,
public sealed class AppInstallationStatus {
data object NotInstalled : AppInstallationStatus()

data class Installed(
val nodeType: AppInstallationStatusNodeType,
) : AppInstallationStatus()
}

public enum class AppInstallationStatusNodeType {
WATCH,
PHONE,

/**
* This case should not happen, but it's here in order to keep the node listed even in a
* scenario where there were issues retrieving the capability of the node.
*/
UNKNOWN,
}

public val AppHelperNodeStatus.appInstalled: Boolean
get() = this.appInstallationStatus is AppInstallationStatus.Installed
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,22 @@ abstract class DataLayerAppHelper(
val allInstalledNodes = installedPhoneNodes + installedWatchNodes

return nearbyNodes.map {
val appInstallationStatus = if (allInstalledNodes.contains(it.id)) {
val nodeType = when (it.id) {
in installedPhoneNodes -> AppInstallationStatusNodeType.PHONE
in installedWatchNodes -> AppInstallationStatusNodeType.WATCH
else -> AppInstallationStatusNodeType.UNKNOWN
}
AppInstallationStatus.Installed(nodeType = nodeType)
} else {
AppInstallationStatus.NotInstalled
}

AppHelperNodeStatus(
id = it.id,
displayName = it.displayName,
isAppInstalled = allInstalledNodes.contains(it.id),
appInstallationStatus = appInstallationStatus,
surfacesInfo = getSurfaceStatus(it.id),
nodeType = when (it.id) {
in installedPhoneNodes -> AppHelperNodeType.PHONE
in installedWatchNodes -> AppHelperNodeType.WATCH
else -> AppHelperNodeType.UNKNOWN
},
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.android.horologist.data.UsageStatus
import com.google.android.horologist.data.apphelper.AppHelperNodeStatus
import com.google.android.horologist.data.apphelper.AppHelperNodeType
import com.google.android.horologist.data.apphelper.AppInstallationStatus
import com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType
import com.google.android.horologist.data.apphelper.appInstalled
import com.google.android.horologist.data.complicationInfo
import com.google.android.horologist.data.surfacesInfo
import com.google.android.horologist.data.tileInfo
Expand Down Expand Up @@ -68,17 +70,22 @@ fun AppHelperNodeStatusCard(
style = MaterialTheme.typography.labelMedium,
text = stringResource(R.string.app_helper_node_id_label, nodeStatus.id),
)
Text(
style = MaterialTheme.typography.labelMedium,
text = stringResource(R.string.app_helper_node_type_label, nodeStatus.nodeType),
)
Text(
style = MaterialTheme.typography.labelMedium,
text = stringResource(
R.string.app_helper_is_app_installed_label,
nodeStatus.isAppInstalled,
nodeStatus.appInstalled,
),
)
val nodeType = if (nodeStatus.appInstalled) {
(nodeStatus.appInstallationStatus as AppInstallationStatus.Installed).nodeType
} else {
stringResource(id = R.string.app_helper_node_type_unknown_label)
}
Text(
style = MaterialTheme.typography.labelMedium,
text = stringResource(R.string.app_helper_node_type_label, nodeType),
)
if (nodeStatus.surfacesInfo.complicationsList.isNotEmpty()) {
Text(
style = MaterialTheme.typography.labelMedium,
Expand Down Expand Up @@ -140,8 +147,9 @@ fun NodeCardPreview() {
val nodeStatus = AppHelperNodeStatus(
displayName = "Pixel Watch",
id = "a1b2c3",
isAppInstalled = true,
nodeType = AppHelperNodeType.WATCH,
appInstallationStatus = AppInstallationStatus.Installed(
nodeType = AppInstallationStatusNodeType.WATCH,
),
surfacesInfo = surfacesInfo {
tiles.add(
tileInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ import com.google.android.horologist.data.ProtoDataStoreHelper.protoDataStore
import com.google.android.horologist.data.WearDataLayerRegistry
import com.google.android.horologist.data.WearableApiAvailability
import com.google.android.horologist.data.apphelper.AppHelperNodeStatus
import com.google.android.horologist.data.apphelper.AppHelperNodeType
import com.google.android.horologist.data.apphelper.AppInstallationStatus
import com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType
import com.google.android.horologist.data.complicationInfo
import com.google.android.horologist.data.surfacesInfo
import com.google.android.horologist.data.tileInfo
Expand Down Expand Up @@ -96,7 +97,8 @@ class MainActivity : ComponentActivity() {
LaunchedEffect(Unit) {
coroutineScope.launch {
apiAvailable = WearableApiAvailability.isAvailable(registry.dataClient)
nodeList = if (apiAvailable) phoneDataLayerAppHelper.connectedNodes() else listOf()
nodeList =
if (apiAvailable) phoneDataLayerAppHelper.connectedNodes() else listOf()
}
}

Expand Down Expand Up @@ -202,8 +204,9 @@ fun MainPreview() {
AppHelperNodeStatus(
id = "a1b2c3d4",
displayName = "Pixel Watch",
isAppInstalled = true,
nodeType = AppHelperNodeType.WATCH,
appInstallationStatus = AppInstallationStatus.Installed(
nodeType = AppInstallationStatusNodeType.WATCH,
),
surfacesInfo = surfacesInfo {
tiles.add(
tileInfo {
Expand Down
3 changes: 2 additions & 1 deletion datalayer/sample/phone/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
<string name="wearable_message_api_unavailable">This device does not have capability to communicate to Wearable Data Layer API</string>
<string name="app_helper_node_name_label">Node: %1$s</string>
<string name="app_helper_node_id_label">ID: %1$s</string>
<string name="app_helper_node_type_label">Type: %1$s</string>
<string name="app_helper_is_app_installed_label">App installed: %1$s</string>
<string name="app_helper_node_type_label">Type: %1$s</string>
<string name="app_helper_node_type_unknown_label">UNKNOWN (app not installed)</string>
<string name="app_helper_complications_label">Complications: %1$s</string>
<string name="app_helper_tiles_label">Tiles: %1$s</string>
<string name="app_helper_usage_status">Usage: %1$s</string>
Expand Down
3 changes: 1 addition & 2 deletions docs/datalayer-helpers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ phone.
AppHelperNodeStatus(
id=7cd1c38a,
displayName=Google Pixel Watch,
isAppInstalled=true,
nodeType=WATCH,
appInstallationStatus=Installed(nodeType=WATCH),
surfacesInfo=# SurfacesInfo@125fcbff
complications {
instance_id: 1234
Expand Down