From cda6b01589fb705b3d60adc1d6509adc3eb50306 Mon Sep 17 00:00:00 2001 From: Michael Vieck Date: Tue, 30 Apr 2024 13:55:05 -0400 Subject: [PATCH] Added Compose Previews for NFC, Onboarding & Companion Views (#4239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feature/compose previews (#1) * Compose Preview created for ChooseEntityView * Nfc view previews added * Added onboarding previews * Fixed ktlint errors * Author Test --------- * Using phone view for preview * Using premade preview entities * Renamed preview logs * Review comments --------- Co-authored-by: Joris Pelgröm --- .../android/nfc/views/NfcEditView.kt | 7 +++ .../android/nfc/views/NfcWelcomeView.kt | 7 +++ .../android/nfc/views/NfcWriteView.kt | 13 +++++ .../android/nfc/views/TagReaderView.kt | 7 +++ .../onboarding/discovery/DiscoveryFragment.kt | 2 +- .../onboarding/discovery/DiscoveryView.kt | 31 +++++++++--- .../onboarding/manual/ManualSetupFragment.kt | 4 +- .../onboarding/manual/ManualSetupView.kt | 32 +++++++++--- .../companion/android/util/PreviewData.kt | 6 +++ .../android/views/ChooseEntityView.kt | 50 +++++++++++++++++++ 10 files changed, 144 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcEditView.kt b/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcEditView.kt index fb8e5bc42bb..17923d2d2c2 100644 --- a/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcEditView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcEditView.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import io.homeassistant.companion.android.common.R as commonR @@ -148,3 +149,9 @@ fun NfcTriggerExample( NfcCodeContainer(text = example) } } + +@Preview(showSystemUi = true) +@Composable +fun NfcEditViewPreview() { + NfcEditView(identifier = "identifier", showDeviceSample = true, onDuplicateClicked = {}, onFireEventClicked = {}) +} diff --git a/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWelcomeView.kt b/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWelcomeView.kt index fd05e60a0d9..0d08376e92e 100644 --- a/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWelcomeView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWelcomeView.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import io.homeassistant.companion.android.common.R as commonR @@ -70,3 +71,9 @@ fun NfcWelcomeView( } } } + +@Preview(showSystemUi = true) +@Composable +fun NfcWelcomeViewPreview() { + NfcWelcomeView(isNfcEnabled = true, onReadClicked = { }, onWriteClicked = {}) +} diff --git a/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWriteView.kt b/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWriteView.kt index 2197ea426b0..1a753849ac4 100644 --- a/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWriteView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/nfc/views/NfcWriteView.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.mikepenz.iconics.compose.Image import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial @@ -109,3 +110,15 @@ fun NfcWriteIdentifierDialog( onSave = { onSubmit(inputValue.value) } ) } + +@Preview(showSystemUi = true) +@Composable +fun NfcWriteViewNfcDisabledPreview() { + NfcWriteView(isNfcEnabled = false, identifier = "identifier") +} + +@Preview(showSystemUi = true) +@Composable +fun NfcWriteViewNfcEnabledPreview() { + NfcWriteView(isNfcEnabled = true, identifier = "identifier", onSetIdentifier = {}) +} diff --git a/app/src/main/java/io/homeassistant/companion/android/nfc/views/TagReaderView.kt b/app/src/main/java/io/homeassistant/companion/android/nfc/views/TagReaderView.kt index 600ee6be491..f443c8ac66b 100644 --- a/app/src/main/java/io/homeassistant/companion/android/nfc/views/TagReaderView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/nfc/views/TagReaderView.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import io.homeassistant.companion.android.common.R @@ -34,3 +35,9 @@ fun TagReaderView() { ) } } + +@Preview(showSystemUi = true) +@Composable +fun TagReaderViewPreview() { + TagReaderView() +} diff --git a/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryFragment.kt b/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryFragment.kt index e02744b30d5..eec61724cb2 100644 --- a/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryFragment.kt +++ b/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryFragment.kt @@ -44,7 +44,7 @@ class DiscoveryFragment @Inject constructor() : Fragment() { setContent { HomeAssistantAppTheme { DiscoveryView( - onboardingViewModel = viewModel, + foundInstances = viewModel.foundInstances, manualSetupClicked = { navigateToManualSetup() }, instanceClicked = { onInstanceClicked(it) } ) diff --git a/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryView.kt b/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryView.kt index 2c1d7a94d4f..3dd83935606 100644 --- a/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/onboarding/discovery/DiscoveryView.kt @@ -18,26 +18,32 @@ import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.onboarding.OnboardingHeaderView -import io.homeassistant.companion.android.onboarding.OnboardingViewModel +import io.homeassistant.companion.android.util.homeAssistantInstance1 +import io.homeassistant.companion.android.util.homeAssistantInstance2 @Composable fun DiscoveryView( - onboardingViewModel: OnboardingViewModel, + foundInstances: SnapshotStateList, manualSetupClicked: () -> Unit, instanceClicked: (instance: HomeAssistantInstance) -> Unit ) { Column( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(16.dp) ) { OnboardingHeaderView( @@ -45,7 +51,8 @@ fun DiscoveryView( title = stringResource(id = commonR.string.select_instance) ) LinearProgressIndicator( - modifier = Modifier.fillMaxWidth(0.25f) + modifier = Modifier + .fillMaxWidth(0.25f) .padding(vertical = 16.dp) .height(2.dp) .align(Alignment.CenterHorizontally) @@ -55,8 +62,8 @@ fun DiscoveryView( .fillMaxWidth() .weight(1f) ) { - items(onboardingViewModel.foundInstances.size, { onboardingViewModel.foundInstances[it].url }) { index -> - val instance = onboardingViewModel.foundInstances[index] + items(foundInstances.size, { foundInstances[it].url }) { index -> + val instance = foundInstances[index] Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, @@ -92,3 +99,15 @@ fun DiscoveryView( } } } + +@Preview(showSystemUi = true) +@Composable +fun DiscoveryViewPreview() { + DiscoveryView( + foundInstances = remember { + mutableStateListOf(homeAssistantInstance1, homeAssistantInstance2) + }, + manualSetupClicked = { }, + instanceClicked = {} + ) +} diff --git a/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupFragment.kt b/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupFragment.kt index 850fda04ef4..0d7a7dee7d7 100644 --- a/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupFragment.kt +++ b/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupFragment.kt @@ -27,7 +27,9 @@ class ManualSetupFragment : Fragment() { setContent { HomeAssistantAppTheme { ManualSetupView( - onboardingViewModel = viewModel, + manualUrl = viewModel.manualUrl, + onManualUrlUpdated = viewModel::onManualUrlUpdated, + manualContinueEnabled = viewModel.manualContinueEnabled, connectedClicked = { connectClicked() } ) } diff --git a/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupView.kt b/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupView.kt index 663f884e913..f5659995ad7 100644 --- a/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/onboarding/manual/ManualSetupView.kt @@ -1,5 +1,6 @@ package io.homeassistant.companion.android.onboarding.manual +import android.content.res.Configuration import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -11,24 +12,27 @@ import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.onboarding.OnboardingHeaderView -import io.homeassistant.companion.android.onboarding.OnboardingViewModel -@OptIn(ExperimentalComposeUiApi::class) @Composable fun ManualSetupView( - onboardingViewModel: OnboardingViewModel, + manualUrl: MutableState, + onManualUrlUpdated: (String) -> Unit, + manualContinueEnabled: Boolean, connectedClicked: () -> Unit ) { val scrollState = rememberScrollState() @@ -54,8 +58,8 @@ fun ManualSetupView( ) TextField( - value = onboardingViewModel.manualUrl.value, - onValueChange = { onboardingViewModel.onManualUrlUpdated(it) }, + value = manualUrl.value, + onValueChange = { onManualUrlUpdated(it) }, modifier = Modifier.align(Alignment.CenterHorizontally), label = { Text(stringResource(id = commonR.string.input_url)) }, singleLine = true, @@ -69,7 +73,7 @@ fun ManualSetupView( ) Button( - enabled = onboardingViewModel.manualContinueEnabled, + enabled = manualContinueEnabled, onClick = connectedClicked, modifier = Modifier .align(Alignment.CenterHorizontally) @@ -79,3 +83,17 @@ fun ManualSetupView( } } } + +@Preview(showSystemUi = true) +@Preview(showSystemUi = true, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +fun ManualSetupViewPreview() { + ManualSetupView( + manualUrl = remember { + mutableStateOf("test") + }, + onManualUrlUpdated = {}, + manualContinueEnabled = true, + connectedClicked = {} + ) +} diff --git a/app/src/main/java/io/homeassistant/companion/android/util/PreviewData.kt b/app/src/main/java/io/homeassistant/companion/android/util/PreviewData.kt index f0f39078277..95ddbbfc62e 100755 --- a/app/src/main/java/io/homeassistant/companion/android/util/PreviewData.kt +++ b/app/src/main/java/io/homeassistant/companion/android/util/PreviewData.kt @@ -1,7 +1,10 @@ package io.homeassistant.companion.android.util +import io.homeassistant.companion.android.common.data.HomeAssistantVersion import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.database.notification.NotificationItem +import io.homeassistant.companion.android.onboarding.discovery.HomeAssistantInstance +import java.net.URL import java.util.Calendar val notificationItem = NotificationItem(1, 1636389288682, "testing", "{\"message\":\"test\"}", "FCM", null) @@ -26,3 +29,6 @@ val previewEntityList = mapOf( ) val previewFavoritesList = listOf("light.test") + +val homeAssistantInstance1 = HomeAssistantInstance(name = "Home", url = URL("https://google.com"), version = HomeAssistantVersion(year = 2024, month = 1, release = 1)) +val homeAssistantInstance2 = HomeAssistantInstance(name = "Vacation Home", url = URL("http://localhost"), version = HomeAssistantVersion(year = 2024, month = 1, release = 1)) diff --git a/wear/src/main/java/io/homeassistant/companion/android/views/ChooseEntityView.kt b/wear/src/main/java/io/homeassistant/companion/android/views/ChooseEntityView.kt index 958555f1c36..ef858a3ce82 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/views/ChooseEntityView.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/views/ChooseEntityView.kt @@ -5,7 +5,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshots.SnapshotStateList @@ -16,11 +19,13 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.wear.compose.foundation.lazy.items import androidx.wear.compose.material3.Button import androidx.wear.compose.material3.ButtonDefaults import androidx.wear.compose.material3.Text +import androidx.wear.tooling.preview.devices.WearDevices import com.mikepenz.iconics.compose.Image import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import io.homeassistant.companion.android.common.R as commonR @@ -30,6 +35,8 @@ import io.homeassistant.companion.android.common.util.capitalize import io.homeassistant.companion.android.data.SimplifiedEntity import io.homeassistant.companion.android.theme.WearAppTheme import io.homeassistant.companion.android.theme.getFilledTonalButtonColors +import io.homeassistant.companion.android.util.playPreviewEntityScene1 +import io.homeassistant.companion.android.util.playPreviewEntityScene2 import io.homeassistant.companion.android.util.stringForDomain import java.util.Locale @@ -150,3 +157,46 @@ private fun ChooseEntityChip( colors = getFilledTonalButtonColors() ) } + +@Preview(device = WearDevices.LARGE_ROUND) +@Composable +fun ChooseEntityViewEmptyPreview() { + ChooseEntityView( + entitiesByDomainOrder = remember { + mutableStateListOf() + }, + entitiesByDomain = remember { + mutableStateMapOf() + }, + favoriteEntityIds = remember { mutableStateOf(listOf()) }, + onNoneClicked = {}, + onEntitySelected = {}, + allowNone = true + ) +} + +@Preview(device = WearDevices.LARGE_ROUND) +@Composable +fun ChooseEntityViewWithDataPreview() { + ChooseEntityView( + entitiesByDomainOrder = remember { + mutableStateListOf(playPreviewEntityScene1.entityId, playPreviewEntityScene2.entityId) + }, + entitiesByDomain = remember { + mutableStateMapOf( + Pair( + playPreviewEntityScene1.entityId, + mutableStateListOf(playPreviewEntityScene1) + ), + Pair( + playPreviewEntityScene2.entityId, + mutableStateListOf(playPreviewEntityScene2) + ) + ) + }, + favoriteEntityIds = remember { mutableStateOf(listOf(playPreviewEntityScene1.entityId)) }, + onNoneClicked = {}, + onEntitySelected = {}, + allowNone = false + ) +}