mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 02:36:12 -04:00
feat(ui): Add Compose previews for all UI components and screens
Add @Preview2 multi-preview annotation (light/dark), mock data provider with realistic device scenarios, and ~45 preview functions across cards, screens, popup, and settings components.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package eu.darken.capod.common.compose
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Preview(showBackground = true, name = "Light", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
annotation class Preview2
|
||||
@@ -1,11 +1,15 @@
|
||||
package eu.darken.capod.common.compose
|
||||
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import eu.darken.capod.common.theming.CapodTheme
|
||||
|
||||
@Composable
|
||||
fun PreviewWrapper(content: @Composable () -> Unit) {
|
||||
CapodTheme {
|
||||
content()
|
||||
CapodTheme(dynamicColor = false) {
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
package eu.darken.capod.common.compose.preview
|
||||
|
||||
import android.content.Context
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||
import eu.darken.capod.common.upgrade.UpgradeRepo
|
||||
import eu.darken.capod.pods.core.DualPodDevice
|
||||
import eu.darken.capod.pods.core.HasCase
|
||||
import eu.darken.capod.pods.core.HasChargeDetection
|
||||
import eu.darken.capod.pods.core.HasChargeDetectionDual
|
||||
import eu.darken.capod.pods.core.HasDualMicrophone
|
||||
import eu.darken.capod.pods.core.HasEarDetection
|
||||
import eu.darken.capod.pods.core.HasEarDetectionDual
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.SinglePodDevice
|
||||
import eu.darken.capod.pods.core.unknown.UnknownDevice
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import java.time.Instant
|
||||
|
||||
object MockPodDataProvider {
|
||||
|
||||
fun dummyScanResult(rssi: Int = -50): BleScanResult = BleScanResult(
|
||||
receivedAt = Instant.now(),
|
||||
address = "AA:BB:CC:DD:EE:FF",
|
||||
rssi = rssi,
|
||||
generatedAtNanos = 0L,
|
||||
manufacturerSpecificData = mapOf(
|
||||
76 to byteArrayOf(0x07, 0x19, 0x01, 0x02, 0x20, 0x75, 0xAA.toByte(), 0x30, 0x01, 0x00, 0x00, 0x2D)
|
||||
),
|
||||
)
|
||||
|
||||
// --- Dual pod scenarios ---
|
||||
|
||||
fun airPodsProFullCharge(): DualPodDevice = MockDualPodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_PRO2,
|
||||
_label = "Work AirPods",
|
||||
batteryLeftPodPercent = 1.0f,
|
||||
batteryRightPodPercent = 1.0f,
|
||||
_batteryCasePercent = 1.0f,
|
||||
leftPodIcon = R.drawable.device_airpods_pro2_left,
|
||||
rightPodIcon = R.drawable.device_airpods_pro2_right,
|
||||
_caseIcon = R.drawable.device_airpods_pro2_case,
|
||||
)
|
||||
|
||||
fun airPodsProMixed(): DualPodDevice = MockDualPodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_PRO2,
|
||||
_label = "My AirPods Pro",
|
||||
batteryLeftPodPercent = 0.80f,
|
||||
batteryRightPodPercent = 0.45f,
|
||||
_batteryCasePercent = 0.60f,
|
||||
_isLeftPodCharging = true,
|
||||
leftPodIcon = R.drawable.device_airpods_pro2_left,
|
||||
rightPodIcon = R.drawable.device_airpods_pro2_right,
|
||||
_caseIcon = R.drawable.device_airpods_pro2_case,
|
||||
)
|
||||
|
||||
fun airPodsProLowBattery(): DualPodDevice = MockDualPodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_PRO2,
|
||||
_label = "My AirPods Pro",
|
||||
batteryLeftPodPercent = 0.10f,
|
||||
batteryRightPodPercent = 0.05f,
|
||||
_batteryCasePercent = null,
|
||||
_isLeftPodInEar = true,
|
||||
_isRightPodInEar = true,
|
||||
leftPodIcon = R.drawable.device_airpods_pro2_left,
|
||||
rightPodIcon = R.drawable.device_airpods_pro2_right,
|
||||
_caseIcon = R.drawable.device_airpods_pro2_case,
|
||||
)
|
||||
|
||||
fun airPodsProInCase(): DualPodDevice = MockDualPodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_PRO2,
|
||||
_label = "My AirPods Pro",
|
||||
batteryLeftPodPercent = null,
|
||||
batteryRightPodPercent = null,
|
||||
_batteryCasePercent = 0.90f,
|
||||
leftPodIcon = R.drawable.device_airpods_pro2_left,
|
||||
rightPodIcon = R.drawable.device_airpods_pro2_right,
|
||||
_caseIcon = R.drawable.device_airpods_pro2_case,
|
||||
)
|
||||
|
||||
fun airPodsGen1Wearing(): DualPodDevice = MockDualPodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_GEN1,
|
||||
_label = "Old AirPods",
|
||||
batteryLeftPodPercent = 0.70f,
|
||||
batteryRightPodPercent = 0.65f,
|
||||
_batteryCasePercent = 0.50f,
|
||||
_isLeftPodInEar = true,
|
||||
_isRightPodInEar = true,
|
||||
_isLeftPodMicrophone = true,
|
||||
leftPodIcon = R.drawable.device_airpods_gen1_left,
|
||||
rightPodIcon = R.drawable.device_airpods_gen1_right,
|
||||
_caseIcon = R.drawable.device_airpods_gen1_case,
|
||||
)
|
||||
|
||||
fun powerBeatsPro(): DualPodDevice = MockDualPodDeviceNoCase(
|
||||
_model = PodDevice.Model.POWERBEATS_PRO,
|
||||
_label = "PowerBeats Pro",
|
||||
batteryLeftPodPercent = 0.55f,
|
||||
batteryRightPodPercent = 0.60f,
|
||||
leftPodIcon = R.drawable.device_powerbeats_pro_left,
|
||||
rightPodIcon = R.drawable.device_powerbeats_pro_right,
|
||||
)
|
||||
|
||||
// --- Single pod scenarios ---
|
||||
|
||||
fun airPodsMax(): SinglePodDevice = MockSinglePodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_MAX,
|
||||
_label = "AirPods Max",
|
||||
batteryHeadsetPercent = 0.85f,
|
||||
_isBeingWorn = true,
|
||||
)
|
||||
|
||||
fun airPodsMaxCharging(): SinglePodDevice = MockSinglePodDevice(
|
||||
_model = PodDevice.Model.AIRPODS_MAX,
|
||||
_label = "AirPods Max",
|
||||
batteryHeadsetPercent = 0.40f,
|
||||
_isHeadsetBeingCharged = true,
|
||||
)
|
||||
|
||||
fun beatsSolo3(): SinglePodDevice = MockSinglePodDevice(
|
||||
_model = PodDevice.Model.BEATS_SOLO_3,
|
||||
_label = "Beats Solo 3",
|
||||
batteryHeadsetPercent = 0.70f,
|
||||
)
|
||||
|
||||
// --- Unknown device ---
|
||||
|
||||
fun unknownDevice(): PodDevice = UnknownDevice(
|
||||
scanResult = dummyScanResult(rssi = -70),
|
||||
)
|
||||
|
||||
// --- Profile helpers ---
|
||||
|
||||
fun profile(label: String, model: PodDevice.Model): AppleDeviceProfile = AppleDeviceProfile(
|
||||
label = label,
|
||||
model = model,
|
||||
)
|
||||
|
||||
// --- UpgradeInfo ---
|
||||
|
||||
fun fossInfo(isPro: Boolean = false): UpgradeRepo.Info = MockUpgradeInfo(
|
||||
type = UpgradeRepo.Type.FOSS,
|
||||
isPro = isPro,
|
||||
)
|
||||
|
||||
fun gplayInfo(isPro: Boolean = false): UpgradeRepo.Info = MockUpgradeInfo(
|
||||
type = UpgradeRepo.Type.GPLAY,
|
||||
isPro = isPro,
|
||||
)
|
||||
}
|
||||
|
||||
private data class MockUpgradeInfo(
|
||||
override val type: UpgradeRepo.Type,
|
||||
override val isPro: Boolean,
|
||||
override val upgradedAt: Instant? = null,
|
||||
override val error: Throwable? = null,
|
||||
) : UpgradeRepo.Info
|
||||
|
||||
private class MockDualPodDevice(
|
||||
private val _model: PodDevice.Model,
|
||||
private val _label: String,
|
||||
override val batteryLeftPodPercent: Float?,
|
||||
override val batteryRightPodPercent: Float?,
|
||||
private val _batteryCasePercent: Float?,
|
||||
private val _isCaseCharging: Boolean = false,
|
||||
private val _isLeftPodCharging: Boolean = false,
|
||||
private val _isRightPodCharging: Boolean = false,
|
||||
private val _isLeftPodInEar: Boolean = false,
|
||||
private val _isRightPodInEar: Boolean = false,
|
||||
private val _isLeftPodMicrophone: Boolean = false,
|
||||
private val _isRightPodMicrophone: Boolean = false,
|
||||
override val leftPodIcon: Int = R.drawable.device_airpods_gen1_left,
|
||||
override val rightPodIcon: Int = R.drawable.device_airpods_gen1_right,
|
||||
private val _caseIcon: Int = R.drawable.device_airpods_gen1_case,
|
||||
rssi: Int = -50,
|
||||
) : DualPodDevice, HasCase, HasChargeDetectionDual, HasEarDetectionDual, HasDualMicrophone {
|
||||
override val identifier: PodDevice.Id = PodDevice.Id()
|
||||
override val model: PodDevice.Model = _model
|
||||
override val seenLastAt: Instant = Instant.now()
|
||||
override val seenFirstAt: Instant = Instant.now()
|
||||
override val seenCounter: Int = 5
|
||||
override val scanResult: BleScanResult = MockPodDataProvider.dummyScanResult(rssi)
|
||||
override val reliability: Float = 1.0f
|
||||
override val signalQuality: Float = 0.75f
|
||||
override val iconRes: Int = _model.iconRes
|
||||
override val meta: PodDevice.Meta = object : PodDevice.Meta {
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = _label, model = _model)
|
||||
}
|
||||
|
||||
override fun getLabel(context: Context): String = _model.label
|
||||
|
||||
// HasCase
|
||||
override val batteryCasePercent: Float? = _batteryCasePercent
|
||||
override val isCaseCharging: Boolean = _isCaseCharging
|
||||
override val caseIcon: Int = _caseIcon
|
||||
|
||||
// HasChargeDetectionDual
|
||||
override val isLeftPodCharging: Boolean = _isLeftPodCharging
|
||||
override val isRightPodCharging: Boolean = _isRightPodCharging
|
||||
|
||||
// HasEarDetectionDual
|
||||
override val isLeftPodInEar: Boolean = _isLeftPodInEar
|
||||
override val isRightPodInEar: Boolean = _isRightPodInEar
|
||||
|
||||
// HasDualMicrophone
|
||||
override val isLeftPodMicrophone: Boolean = _isLeftPodMicrophone
|
||||
override val isRightPodMicrophone: Boolean = _isRightPodMicrophone
|
||||
}
|
||||
|
||||
private class MockDualPodDeviceNoCase(
|
||||
private val _model: PodDevice.Model,
|
||||
private val _label: String,
|
||||
override val batteryLeftPodPercent: Float?,
|
||||
override val batteryRightPodPercent: Float?,
|
||||
override val leftPodIcon: Int = R.drawable.device_airpods_gen1_left,
|
||||
override val rightPodIcon: Int = R.drawable.device_airpods_gen1_right,
|
||||
rssi: Int = -50,
|
||||
) : DualPodDevice, HasChargeDetectionDual, HasEarDetectionDual {
|
||||
override val identifier: PodDevice.Id = PodDevice.Id()
|
||||
override val model: PodDevice.Model = _model
|
||||
override val seenLastAt: Instant = Instant.now()
|
||||
override val seenFirstAt: Instant = Instant.now()
|
||||
override val seenCounter: Int = 5
|
||||
override val scanResult: BleScanResult = MockPodDataProvider.dummyScanResult(rssi)
|
||||
override val reliability: Float = 1.0f
|
||||
override val signalQuality: Float = 0.70f
|
||||
override val iconRes: Int = _model.iconRes
|
||||
override val meta: PodDevice.Meta = object : PodDevice.Meta {
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = _label, model = _model)
|
||||
}
|
||||
|
||||
override fun getLabel(context: Context): String = _model.label
|
||||
|
||||
// HasChargeDetectionDual
|
||||
override val isLeftPodCharging: Boolean = false
|
||||
override val isRightPodCharging: Boolean = false
|
||||
|
||||
// HasEarDetectionDual
|
||||
override val isLeftPodInEar: Boolean = false
|
||||
override val isRightPodInEar: Boolean = false
|
||||
}
|
||||
|
||||
private class MockSinglePodDevice(
|
||||
private val _model: PodDevice.Model,
|
||||
private val _label: String,
|
||||
override val batteryHeadsetPercent: Float?,
|
||||
private val _isHeadsetBeingCharged: Boolean = false,
|
||||
private val _isBeingWorn: Boolean = false,
|
||||
rssi: Int = -50,
|
||||
) : SinglePodDevice, HasChargeDetection, HasEarDetection {
|
||||
override val identifier: PodDevice.Id = PodDevice.Id()
|
||||
override val model: PodDevice.Model = _model
|
||||
override val seenLastAt: Instant = Instant.now()
|
||||
override val seenFirstAt: Instant = Instant.now()
|
||||
override val seenCounter: Int = 5
|
||||
override val scanResult: BleScanResult = MockPodDataProvider.dummyScanResult(rssi)
|
||||
override val reliability: Float = 1.0f
|
||||
override val signalQuality: Float = 0.80f
|
||||
override val iconRes: Int = _model.iconRes
|
||||
override val meta: PodDevice.Meta = object : PodDevice.Meta {
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = _label, model = _model)
|
||||
}
|
||||
|
||||
override fun getLabel(context: Context): String = _model.label
|
||||
|
||||
// HasChargeDetection
|
||||
override val isHeadsetBeingCharged: Boolean = _isHeadsetBeingCharged
|
||||
|
||||
// HasEarDetection
|
||||
override val isBeingWorn: Boolean = _isBeingWorn
|
||||
}
|
||||
@@ -13,12 +13,16 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.twotone.Settings
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@@ -94,3 +98,14 @@ fun SettingsBaseItem(
|
||||
trailingContent?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsBaseItemPreview() = PreviewWrapper {
|
||||
SettingsBaseItem(
|
||||
title = "General Settings",
|
||||
subtitle = "Monitor mode, scanner, notifications",
|
||||
icon = Icons.TwoTone.Settings,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun SettingsCategoryHeader(
|
||||
@@ -21,3 +23,9 @@ fun SettingsCategoryHeader(
|
||||
modifier = modifier.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsCategoryHeaderPreview() = PreviewWrapper {
|
||||
SettingsCategoryHeader(text = "Other")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun SettingsDivider(
|
||||
@@ -16,3 +18,9 @@ fun SettingsDivider(
|
||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.12f)
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsDividerPreview() = PreviewWrapper {
|
||||
SettingsDivider()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.twotone.Tune
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -22,6 +24,8 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun <T> SettingsListPreferenceItem(
|
||||
@@ -89,3 +93,16 @@ fun <T> SettingsListPreferenceItem(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsListPreferenceItemPreview() = PreviewWrapper {
|
||||
SettingsListPreferenceItem(
|
||||
icon = Icons.TwoTone.Tune,
|
||||
title = "Mode",
|
||||
entries = listOf("Manual", "Automatic", "Always"),
|
||||
selectedEntry = "Automatic",
|
||||
onEntrySelected = {},
|
||||
entryLabel = { it },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,10 +6,14 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.twotone.VolumeUp
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun SettingsSliderItem(
|
||||
@@ -55,3 +59,16 @@ fun SettingsSliderItem(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsSliderItemPreview() = PreviewWrapper {
|
||||
SettingsSliderItem(
|
||||
icon = Icons.AutoMirrored.TwoTone.VolumeUp,
|
||||
title = "Volume",
|
||||
subtitle = "Adjust volume level",
|
||||
value = 0.6f,
|
||||
onValueChange = {},
|
||||
valueLabel = { "${(it * 100).toInt()}%" },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@ package eu.darken.capod.common.settings
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.twotone.Notifications
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun SettingsSwitchItem(
|
||||
@@ -34,3 +38,27 @@ fun SettingsSwitchItem(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsSwitchItemOnPreview() = PreviewWrapper {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.Notifications,
|
||||
title = "Show notifications",
|
||||
subtitle = "Display connection notifications",
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsSwitchItemOffPreview() = PreviewWrapper {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.Notifications,
|
||||
title = "Show notifications",
|
||||
subtitle = "Display connection notifications",
|
||||
checked = false,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
@@ -121,3 +123,9 @@ fun OnboardingScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun OnboardingScreenPreview() = PreviewWrapper {
|
||||
OnboardingScreen(onPrivacyPolicy = {}, onContinue = {})
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.compose.LifecycleEventEffect
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
@@ -276,6 +279,101 @@ private fun PodDeviceCard(device: PodDevice, showDebug: Boolean, now: Instant) {
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun OverviewScreenWithDevicesPreview() = PreviewWrapper {
|
||||
OverviewScreen(
|
||||
state = OverviewViewModel.State(
|
||||
now = Instant.now(),
|
||||
permissions = emptySet(),
|
||||
devices = listOf(
|
||||
MockPodDataProvider.airPodsProMixed(),
|
||||
MockPodDataProvider.airPodsMax(),
|
||||
MockPodDataProvider.unknownDevice(),
|
||||
),
|
||||
isDebugMode = false,
|
||||
isBluetoothEnabled = true,
|
||||
profiles = listOf(
|
||||
MockPodDataProvider.profile("My AirPods Pro", PodDevice.Model.AIRPODS_PRO2),
|
||||
MockPodDataProvider.profile("AirPods Max", PodDevice.Model.AIRPODS_MAX),
|
||||
),
|
||||
upgradeInfo = MockPodDataProvider.fossInfo(),
|
||||
showUnmatchedDevices = false,
|
||||
),
|
||||
onRequestPermission = {},
|
||||
onManageDevices = {},
|
||||
onSettings = {},
|
||||
onUpgrade = {},
|
||||
onToggleUnmatched = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun OverviewScreenEmptyPreview() = PreviewWrapper {
|
||||
OverviewScreen(
|
||||
state = OverviewViewModel.State(
|
||||
now = Instant.now(),
|
||||
permissions = emptySet(),
|
||||
devices = emptyList(),
|
||||
isDebugMode = false,
|
||||
isBluetoothEnabled = true,
|
||||
profiles = listOf(MockPodDataProvider.profile("My AirPods", PodDevice.Model.AIRPODS_PRO2)),
|
||||
upgradeInfo = MockPodDataProvider.fossInfo(),
|
||||
showUnmatchedDevices = false,
|
||||
),
|
||||
onRequestPermission = {},
|
||||
onManageDevices = {},
|
||||
onSettings = {},
|
||||
onUpgrade = {},
|
||||
onToggleUnmatched = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun OverviewScreenNoProfilesPreview() = PreviewWrapper {
|
||||
OverviewScreen(
|
||||
state = OverviewViewModel.State(
|
||||
now = Instant.now(),
|
||||
permissions = emptySet(),
|
||||
devices = emptyList(),
|
||||
isDebugMode = false,
|
||||
isBluetoothEnabled = true,
|
||||
profiles = emptyList(),
|
||||
upgradeInfo = MockPodDataProvider.gplayInfo(),
|
||||
showUnmatchedDevices = false,
|
||||
),
|
||||
onRequestPermission = {},
|
||||
onManageDevices = {},
|
||||
onSettings = {},
|
||||
onUpgrade = {},
|
||||
onToggleUnmatched = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun OverviewScreenBluetoothOffPreview() = PreviewWrapper {
|
||||
OverviewScreen(
|
||||
state = OverviewViewModel.State(
|
||||
now = Instant.now(),
|
||||
permissions = emptySet(),
|
||||
devices = emptyList(),
|
||||
isDebugMode = false,
|
||||
isBluetoothEnabled = false,
|
||||
profiles = listOf(MockPodDataProvider.profile("My AirPods", PodDevice.Model.AIRPODS_PRO2)),
|
||||
upgradeInfo = MockPodDataProvider.fossInfo(isPro = true),
|
||||
showUnmatchedDevices = false,
|
||||
),
|
||||
onRequestPermission = {},
|
||||
onManageDevices = {},
|
||||
onSettings = {},
|
||||
onUpgrade = {},
|
||||
onToggleUnmatched = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ToolbarTitle(upgradeInfo: UpgradeRepo.Info) {
|
||||
val appName = stringResource(R.string.app_name)
|
||||
|
||||
@@ -13,6 +13,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun BluetoothDisabledCard() {
|
||||
@@ -38,3 +40,9 @@ fun BluetoothDisabledCard() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun BluetoothDisabledCardPreview() = PreviewWrapper {
|
||||
BluetoothDisabledCard()
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ import eu.darken.capod.pods.core.firstSeenFormatted
|
||||
import eu.darken.capod.pods.core.formatBatteryPercent
|
||||
import eu.darken.capod.pods.core.getSignalQuality
|
||||
import eu.darken.capod.pods.core.lastSeenFormatted
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@@ -246,6 +249,42 @@ fun DualPodsCard(
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DualPodsCardFullChargePreview() = PreviewWrapper {
|
||||
DualPodsCard(device = MockPodDataProvider.airPodsProFullCharge(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DualPodsCardMixedBatteryPreview() = PreviewWrapper {
|
||||
DualPodsCard(device = MockPodDataProvider.airPodsProMixed(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DualPodsCardLowBatteryPreview() = PreviewWrapper {
|
||||
DualPodsCard(device = MockPodDataProvider.airPodsProLowBattery(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DualPodsCardInCasePreview() = PreviewWrapper {
|
||||
DualPodsCard(device = MockPodDataProvider.airPodsProInCase(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DualPodsCardDebugPreview() = PreviewWrapper {
|
||||
DualPodsCard(device = MockPodDataProvider.airPodsProMixed(), showDebug = true, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DualPodsCardNoCasePreview() = PreviewWrapper {
|
||||
DualPodsCard(device = MockPodDataProvider.powerBeatsPro(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BatteryRow(
|
||||
label: String,
|
||||
|
||||
@@ -13,6 +13,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun MonitoringActiveCard() {
|
||||
@@ -38,3 +40,9 @@ fun MonitoringActiveCard() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun MonitoringActiveCardPreview() = PreviewWrapper {
|
||||
MonitoringActiveCard()
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import androidx.compose.material.icons.twotone.DevicesOther
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun NoProfilesCard(onManageDevices: () -> Unit) {
|
||||
@@ -57,3 +59,9 @@ fun NoProfilesCard(onManageDevices: () -> Unit) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun NoProfilesCardPreview() = PreviewWrapper {
|
||||
NoProfilesCard(onManageDevices = {})
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.permissions.Permission
|
||||
|
||||
@Composable
|
||||
@@ -53,3 +55,9 @@ fun PermissionCard(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun PermissionCardPreview() = PreviewWrapper {
|
||||
PermissionCard(permission = Permission.BLUETOOTH_SCAN, onRequest = {})
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ import eu.darken.capod.pods.core.firstSeenFormatted
|
||||
import eu.darken.capod.pods.core.formatBatteryPercent
|
||||
import eu.darken.capod.pods.core.getSignalQuality
|
||||
import eu.darken.capod.pods.core.lastSeenFormatted
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@@ -173,3 +176,21 @@ fun SinglePodsCard(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SinglePodsCardWearingPreview() = PreviewWrapper {
|
||||
SinglePodsCard(device = MockPodDataProvider.airPodsMax(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SinglePodsCardChargingPreview() = PreviewWrapper {
|
||||
SinglePodsCard(device = MockPodDataProvider.airPodsMaxCharging(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SinglePodsCardDebugPreview() = PreviewWrapper {
|
||||
SinglePodsCard(device = MockPodDataProvider.beatsSolo3(), showDebug = true, now = Instant.now())
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.apple.ApplePods
|
||||
import eu.darken.capod.pods.core.getSignalQuality
|
||||
import eu.darken.capod.pods.core.lastSeenFormatted
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import java.time.Instant
|
||||
|
||||
@Composable
|
||||
@@ -103,3 +106,15 @@ fun UnknownPodDeviceCard(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun UnknownPodDeviceCardPreview() = PreviewWrapper {
|
||||
UnknownPodDeviceCard(device = MockPodDataProvider.unknownDevice(), showDebug = false, now = Instant.now())
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun UnknownPodDeviceCardDebugPreview() = PreviewWrapper {
|
||||
UnknownPodDeviceCard(device = MockPodDataProvider.unknownDevice(), showDebug = true, now = Instant.now())
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
|
||||
@Composable
|
||||
fun UnmatchedDevicesCard(
|
||||
@@ -52,3 +54,15 @@ fun UnmatchedDevicesCard(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun UnmatchedDevicesCardCollapsedPreview() = PreviewWrapper {
|
||||
UnmatchedDevicesCard(count = 3, isExpanded = false, onToggle = {})
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun UnmatchedDevicesCardExpandedPreview() = PreviewWrapper {
|
||||
UnmatchedDevicesCard(count = 3, isExpanded = true, onToggle = {})
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.BuildConfigWrap
|
||||
import eu.darken.capod.common.PrivacyPolicy
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
@@ -172,3 +174,21 @@ fun SettingsScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SettingsScreenPreview() = PreviewWrapper {
|
||||
SettingsScreen(
|
||||
state = SettingsViewModel.State(sponsorUrl = "https://example.com"),
|
||||
onNavigateUp = {},
|
||||
onGeneralSettings = {},
|
||||
onDeviceManager = {},
|
||||
onReactions = {},
|
||||
onSupport = {},
|
||||
onChangelog = {},
|
||||
onHelpTranslate = {},
|
||||
onAcknowledgements = {},
|
||||
onPrivacyPolicy = {},
|
||||
onSponsor = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
import eu.darken.capod.common.settings.SettingsBaseItem
|
||||
@@ -162,3 +164,9 @@ fun AcknowledgementsScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun AcknowledgementsScreenPreview() = PreviewWrapper {
|
||||
AcknowledgementsScreen(onNavigateUp = {}, onOpenUrl = {})
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.bluetooth.ScannerMode
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
@@ -244,6 +246,31 @@ fun GeneralSettingsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun GeneralSettingsScreenPreview() = PreviewWrapper {
|
||||
GeneralSettingsScreen(
|
||||
state = GeneralSettingsViewModel.State(
|
||||
monitorMode = MonitorMode.AUTOMATIC,
|
||||
scannerMode = ScannerMode.BALANCED,
|
||||
showConnectedNotification = true,
|
||||
keepNotificationAfterDisconnect = false,
|
||||
isOffloadedFilteringDisabled = false,
|
||||
isOffloadedBatchingDisabled = false,
|
||||
useIndirectScanResultCallback = false,
|
||||
),
|
||||
onNavigateUp = {},
|
||||
onMonitorModeSelected = {},
|
||||
onScannerModeSelected = {},
|
||||
onShowConnectedNotificationChanged = {},
|
||||
onKeepNotificationAfterDisconnectChanged = {},
|
||||
onDebugSettings = {},
|
||||
onOffloadedFilteringDisabledChanged = {},
|
||||
onOffloadedBatchingDisabledChanged = {},
|
||||
onUseIndirectScanResultCallbackChanged = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun <T> ListPreferenceDialog(
|
||||
title: String,
|
||||
|
||||
+18
@@ -21,6 +21,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
@@ -118,3 +120,19 @@ fun DebugSettingsScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DebugSettingsScreenPreview() = PreviewWrapper {
|
||||
DebugSettingsScreen(
|
||||
state = DebugSettingsViewModel.State(
|
||||
isDebugModeEnabled = true,
|
||||
showFakeData = false,
|
||||
showUnfiltered = false,
|
||||
),
|
||||
onNavigateUp = {},
|
||||
onDebugModeChanged = {},
|
||||
onShowFakeDataChanged = {},
|
||||
onShowUnfilteredChanged = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
@@ -125,3 +127,16 @@ fun SupportScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun SupportScreenPreview() = PreviewWrapper {
|
||||
SupportScreen(
|
||||
state = SupportViewModel.State(isRecording = false, currentLogPath = null),
|
||||
onNavigateUp = {},
|
||||
onDiscord = {},
|
||||
onIssueTracker = {},
|
||||
onTroubleShooter = {},
|
||||
onDebugLogToggle = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,6 +71,9 @@ import androidx.core.graphics.createBitmap
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.core.view.isVisible
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
|
||||
@@ -650,6 +653,68 @@ private fun HexColorInput(
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun WidgetConfigurationScreenPreview() = PreviewWrapper {
|
||||
val profiles = listOf(
|
||||
MockPodDataProvider.profile("My AirPods Pro", PodDevice.Model.AIRPODS_PRO2),
|
||||
MockPodDataProvider.profile("AirPods Max", PodDevice.Model.AIRPODS_MAX),
|
||||
)
|
||||
WidgetConfigurationScreen(
|
||||
state = WidgetConfigurationViewModel.State(
|
||||
profiles = profiles,
|
||||
selectedProfile = profiles.first().id,
|
||||
isPro = true,
|
||||
theme = WidgetTheme.DEFAULT,
|
||||
activePreset = WidgetTheme.Preset.MATERIAL_YOU,
|
||||
isCustomMode = false,
|
||||
),
|
||||
onSelectProfile = {},
|
||||
onSelectPreset = {},
|
||||
onEnterCustomMode = { _, _ -> },
|
||||
onSetBackgroundColor = {},
|
||||
onSetForegroundColor = {},
|
||||
onSetBackgroundAlpha = {},
|
||||
onSetShowDeviceLabel = {},
|
||||
onReset = {},
|
||||
onConfirm = {},
|
||||
onCancel = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun WidgetConfigurationScreenCustomPreview() = PreviewWrapper {
|
||||
val profiles = listOf(
|
||||
MockPodDataProvider.profile("My AirPods Pro", PodDevice.Model.AIRPODS_PRO2),
|
||||
)
|
||||
WidgetConfigurationScreen(
|
||||
state = WidgetConfigurationViewModel.State(
|
||||
profiles = profiles,
|
||||
selectedProfile = profiles.first().id,
|
||||
isPro = true,
|
||||
theme = WidgetTheme(
|
||||
backgroundColor = 0xFF1565C0.toInt(),
|
||||
foregroundColor = 0xFFFFFFFF.toInt(),
|
||||
backgroundAlpha = 200,
|
||||
showDeviceLabel = true,
|
||||
),
|
||||
activePreset = null,
|
||||
isCustomMode = true,
|
||||
),
|
||||
onSelectProfile = {},
|
||||
onSelectPreset = {},
|
||||
onEnterCustomMode = { _, _ -> },
|
||||
onSetBackgroundColor = {},
|
||||
onSetForegroundColor = {},
|
||||
onSetBackgroundAlpha = {},
|
||||
onSetShowDeviceLabel = {},
|
||||
onReset = {},
|
||||
onConfirm = {},
|
||||
onCancel = {},
|
||||
)
|
||||
}
|
||||
|
||||
private val SWATCH_COLORS = intArrayOf(
|
||||
0xFFF44336.toInt(), // Red
|
||||
0xFFE91E63.toInt(), // Pink
|
||||
|
||||
@@ -36,9 +36,13 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
|
||||
@Composable
|
||||
@@ -121,6 +125,34 @@ fun DeviceManagerScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DeviceManagerScreenWithProfilesPreview() = PreviewWrapper {
|
||||
DeviceManagerScreen(
|
||||
state = DeviceManagerViewModel.State(
|
||||
profiles = listOf(
|
||||
MockPodDataProvider.profile("Work AirPods", PodDevice.Model.AIRPODS_PRO2),
|
||||
MockPodDataProvider.profile("AirPods Max", PodDevice.Model.AIRPODS_MAX),
|
||||
MockPodDataProvider.profile("Gym Beats", PodDevice.Model.POWERBEATS_PRO),
|
||||
),
|
||||
),
|
||||
onBack = {},
|
||||
onAddDevice = {},
|
||||
onEditProfile = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DeviceManagerScreenEmptyPreview() = PreviewWrapper {
|
||||
DeviceManagerScreen(
|
||||
state = DeviceManagerViewModel.State(profiles = emptyList()),
|
||||
onBack = {},
|
||||
onAddDevice = {},
|
||||
onEditProfile = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmptyState(
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -48,6 +48,8 @@ import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.bluetooth.BluetoothDevice2
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
@@ -548,6 +550,66 @@ private fun UnsavedChangesDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DeviceProfileCreationScreenNewPreview() = PreviewWrapper {
|
||||
DeviceProfileCreationScreen(
|
||||
state = DeviceProfileCreationViewModel.State(
|
||||
isEditMode = false,
|
||||
name = "",
|
||||
nameError = null,
|
||||
selectedModel = null,
|
||||
availableModels = PodDevice.Model.entries.filter { it != PodDevice.Model.UNKNOWN },
|
||||
identityKey = null,
|
||||
encryptionKey = null,
|
||||
selectedDevice = null,
|
||||
bondedDevices = emptyList(),
|
||||
minimumSignalQuality = 0.15f,
|
||||
canSave = false,
|
||||
),
|
||||
onBack = {},
|
||||
onSave = {},
|
||||
onDelete = {},
|
||||
onNameChange = {},
|
||||
onModelChange = {},
|
||||
onDeviceChange = {},
|
||||
onIdentityKeyChange = {},
|
||||
onEncryptionKeyChange = {},
|
||||
onSignalQualityChange = {},
|
||||
onKeyGuide = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun DeviceProfileCreationScreenEditPreview() = PreviewWrapper {
|
||||
DeviceProfileCreationScreen(
|
||||
state = DeviceProfileCreationViewModel.State(
|
||||
isEditMode = true,
|
||||
name = "My AirPods Pro",
|
||||
nameError = null,
|
||||
selectedModel = PodDevice.Model.AIRPODS_PRO2,
|
||||
availableModels = PodDevice.Model.entries.filter { it != PodDevice.Model.UNKNOWN },
|
||||
identityKey = null,
|
||||
encryptionKey = null,
|
||||
selectedDevice = null,
|
||||
bondedDevices = emptyList(),
|
||||
minimumSignalQuality = 0.25f,
|
||||
canSave = true,
|
||||
),
|
||||
onBack = {},
|
||||
onSave = {},
|
||||
onDelete = {},
|
||||
onNameChange = {},
|
||||
onModelChange = {},
|
||||
onDeviceChange = {},
|
||||
onIdentityKeyChange = {},
|
||||
onEncryptionKeyChange = {},
|
||||
onSignalQualityChange = {},
|
||||
onKeyGuide = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DeleteConfirmationDialog(
|
||||
onDelete: () -> Unit,
|
||||
|
||||
@@ -41,6 +41,8 @@ import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
@@ -267,3 +269,28 @@ fun ReactionSettingsScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun ReactionSettingsScreenPreview() = PreviewWrapper {
|
||||
ReactionSettingsScreen(
|
||||
state = ReactionSettingsViewModel.State(
|
||||
isPro = true,
|
||||
onePodMode = false,
|
||||
autoPlay = true,
|
||||
autoPause = true,
|
||||
autoConnect = false,
|
||||
autoConnectCondition = AutoConnectCondition.WHEN_SEEN,
|
||||
showPopUpOnCaseOpen = true,
|
||||
showPopUpOnConnection = false,
|
||||
),
|
||||
onNavigateUp = {},
|
||||
onOnePodModeChanged = {},
|
||||
onAutoPlayChanged = {},
|
||||
onAutoPauseChanged = {},
|
||||
onAutoConnectChanged = {},
|
||||
onAutoConnectConditionSelected = {},
|
||||
onShowPopUpOnCaseOpenChanged = {},
|
||||
onShowPopUpOnConnectionChanged = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import eu.darken.capod.pods.core.DualPodDevice
|
||||
import eu.darken.capod.pods.core.HasCase
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
@@ -192,3 +195,21 @@ private fun BatteryColumn(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun PopUpContentDualPodPreview() = PreviewWrapper {
|
||||
PopUpContent(device = MockPodDataProvider.airPodsProMixed(), onClose = {})
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun PopUpContentDualPodNoCasePreview() = PreviewWrapper {
|
||||
PopUpContent(device = MockPodDataProvider.powerBeatsPro(), onClose = {})
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun PopUpContentSinglePodPreview() = PreviewWrapper {
|
||||
PopUpContent(device = MockPodDataProvider.airPodsMax(), onClose = {})
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.common.compose.waitForState
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
@@ -214,3 +216,16 @@ private fun ResultContent(
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun TroubleShooterScreenPreview() = PreviewWrapper {
|
||||
TroubleShooterScreen(
|
||||
state = TroubleShooterViewModel.State(
|
||||
bleState = TroubleShooterViewModel.BleState.Intro(),
|
||||
),
|
||||
onStart = {},
|
||||
onRetry = {},
|
||||
onNavigateUp = {},
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user