mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 10:46:12 -04:00
feat(screenshots): Set up localized Play Store screenshot pipeline
- Add Compose screenshot test infrastructure (build config, screenshotTest source set) - Add 7 localized screenshots covering all key app screens - Device spec set to Pixel 8 (1080x2400, 428dpi); batch size 4 for 1080p memory budget - Add screen title heading and fix appearance card header layout in WidgetConfigurationScreen - Balance padding on requires-Pro notice in widget config bottom bar
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
package eu.darken.capod.screenshots
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import eu.darken.capod.main.ui.widget.WidgetConfigurationScreen
|
||||
import eu.darken.capod.main.ui.widget.WidgetConfigurationViewModel
|
||||
import eu.darken.capod.main.ui.widget.WidgetTheme
|
||||
import eu.darken.capod.common.compose.preview.MOCK_NOW
|
||||
import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import eu.darken.capod.common.theming.CapodTheme
|
||||
import eu.darken.capod.main.ui.overview.OverviewScreen
|
||||
import eu.darken.capod.main.ui.overview.OverviewViewModel
|
||||
import eu.darken.capod.main.ui.settings.SettingsScreen
|
||||
import eu.darken.capod.main.ui.settings.SettingsViewModel
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.profiles.ui.DeviceManagerScreen
|
||||
import eu.darken.capod.profiles.ui.DeviceManagerViewModel
|
||||
import eu.darken.capod.profiles.ui.creation.DeviceProfileCreationScreen
|
||||
import eu.darken.capod.profiles.ui.creation.DeviceProfileCreationViewModel
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import eu.darken.capod.reaction.ui.ReactionSettingsScreen
|
||||
import eu.darken.capod.reaction.ui.ReactionSettingsViewModel
|
||||
|
||||
internal const val DS = "spec:width=1080px,height=2400px,dpi=428"
|
||||
|
||||
@Composable
|
||||
internal fun DashboardContent() = PreviewWrapper {
|
||||
OverviewScreen(
|
||||
state = OverviewViewModel.State(
|
||||
now = MOCK_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.gplayInfo(isPro = true),
|
||||
showUnmatchedDevices = false,
|
||||
),
|
||||
onRequestPermission = {},
|
||||
onManageDevices = {},
|
||||
onSettings = {},
|
||||
onUpgrade = {},
|
||||
onToggleUnmatched = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun DeviceProfilesContent() = 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 = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun AddProfileContent() = 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 = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SettingsIndexContent() = PreviewWrapper {
|
||||
SettingsScreen(
|
||||
state = SettingsViewModel.State(sponsorUrl = "https://example.com"),
|
||||
onNavigateUp = {},
|
||||
onGeneralSettings = {},
|
||||
onDeviceManager = {},
|
||||
onReactions = {},
|
||||
onSupport = {},
|
||||
onChangelog = {},
|
||||
onHelpTranslate = {},
|
||||
onAcknowledgements = {},
|
||||
onPrivacyPolicy = {},
|
||||
onSponsor = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun ReactionSettingsContent() = 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 = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun WidgetConfigurationContent() = 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 = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun HomescreenWidgetContent() {
|
||||
CapodTheme {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
Color(0xFF1A237E),
|
||||
Color(0xFF0D47A1),
|
||||
Color(0xFF006064),
|
||||
)
|
||||
)
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
WidgetDualCompact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WidgetDualCompact() {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
tonalElevation = 2.dp,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
WidgetPodRow(
|
||||
icon = R.drawable.device_airpods_pro2_left,
|
||||
percent = 85,
|
||||
charging = false,
|
||||
inEar = true,
|
||||
)
|
||||
WidgetPodRow(
|
||||
icon = R.drawable.device_airpods_pro2_right,
|
||||
percent = 92,
|
||||
charging = true,
|
||||
inEar = false,
|
||||
)
|
||||
WidgetCaseRow(
|
||||
icon = R.drawable.device_airpods_pro2_case,
|
||||
percent = 100,
|
||||
charging = false,
|
||||
)
|
||||
Text(
|
||||
text = "My AirPods Pro",
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WidgetPodRow(
|
||||
@DrawableRes icon: Int,
|
||||
percent: Int,
|
||||
charging: Boolean,
|
||||
inEar: Boolean,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.padding(vertical = 2.dp),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(icon),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
Text(
|
||||
text = "$percent%",
|
||||
fontSize = 12.sp,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.padding(horizontal = 4.dp),
|
||||
)
|
||||
if (charging) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_baseline_power_24),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
}
|
||||
if (inEar) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_baseline_hearing_24),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WidgetCaseRow(
|
||||
@DrawableRes icon: Int,
|
||||
percent: Int,
|
||||
charging: Boolean,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.padding(vertical = 2.dp),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(icon),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
Text(
|
||||
text = "$percent%",
|
||||
fontSize = 12.sp,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.padding(horizontal = 4.dp),
|
||||
)
|
||||
if (charging) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_baseline_power_24),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "1 - Dashboard Light", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewDashboardLight() = DashboardContent()
|
||||
|
||||
@Preview(name = "2 - Dashboard Dark", locale = "en", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewDashboardDark() = DashboardContent()
|
||||
|
||||
@Preview(name = "3 - Device Profiles", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewDeviceProfiles() = DeviceProfilesContent()
|
||||
|
||||
@Preview(name = "4 - Add Profile", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewAddProfile() = AddProfileContent()
|
||||
|
||||
@Preview(name = "5 - Settings", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewSettingsIndex() = SettingsIndexContent()
|
||||
|
||||
@Preview(name = "6 - Reaction Settings", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewReactionSettings() = ReactionSettingsContent()
|
||||
|
||||
@Preview(name = "7 - Homescreen Widget", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewHomescreenWidget() = HomescreenWidgetContent()
|
||||
|
||||
@Preview(name = "7 - Widget Configuration", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewWidgetConfiguration() = WidgetConfigurationContent()
|
||||
@@ -18,10 +18,13 @@ import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import java.time.Instant
|
||||
|
||||
/** Fixed timestamp for deterministic preview/screenshot rendering. */
|
||||
val MOCK_NOW: Instant = Instant.parse("2025-06-15T10:30:00Z")
|
||||
|
||||
object MockPodDataProvider {
|
||||
|
||||
fun dummyScanResult(rssi: Int = -50): BleScanResult = BleScanResult(
|
||||
receivedAt = Instant.now(),
|
||||
receivedAt = MOCK_NOW,
|
||||
address = "AA:BB:CC:DD:EE:FF",
|
||||
rssi = rssi,
|
||||
generatedAtNanos = 0L,
|
||||
@@ -177,8 +180,8 @@ private class MockDualPodDevice(
|
||||
) : 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 seenLastAt: Instant = MOCK_NOW
|
||||
override val seenFirstAt: Instant = MOCK_NOW
|
||||
override val seenCounter: Int = 5
|
||||
override val scanResult: BleScanResult = MockPodDataProvider.dummyScanResult(rssi)
|
||||
override val reliability: Float = 1.0f
|
||||
@@ -219,8 +222,8 @@ private class MockDualPodDeviceNoCase(
|
||||
) : 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 seenLastAt: Instant = MOCK_NOW
|
||||
override val seenFirstAt: Instant = MOCK_NOW
|
||||
override val seenCounter: Int = 5
|
||||
override val scanResult: BleScanResult = MockPodDataProvider.dummyScanResult(rssi)
|
||||
override val reliability: Float = 1.0f
|
||||
@@ -251,8 +254,8 @@ private class MockSinglePodDevice(
|
||||
) : 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 seenLastAt: Instant = MOCK_NOW
|
||||
override val seenFirstAt: Instant = MOCK_NOW
|
||||
override val seenCounter: Int = 5
|
||||
override val scanResult: BleScanResult = MockPodDataProvider.dummyScanResult(rssi)
|
||||
override val reliability: Float = 1.0f
|
||||
|
||||
@@ -121,6 +121,14 @@ fun WidgetConfigurationScreen(
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = 24.dp, bottom = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.widget_config_screen_title),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = screenHPad, end = screenHPad, bottom = 16.dp),
|
||||
)
|
||||
|
||||
// Card A — Select Device
|
||||
Card(
|
||||
modifier = Modifier
|
||||
@@ -170,16 +178,15 @@ fun WidgetConfigurationScreen(
|
||||
) {
|
||||
Column(modifier = Modifier.padding(cardPad)) {
|
||||
// Appearance header + reset
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
text = stringResource(R.string.widget_config_appearance_label),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
TextButton(onClick = onReset) {
|
||||
TextButton(
|
||||
onClick = onReset,
|
||||
modifier = Modifier.align(Alignment.End),
|
||||
) {
|
||||
Text(text = stringResource(R.string.widget_config_reset_label))
|
||||
}
|
||||
}
|
||||
@@ -327,7 +334,7 @@ fun WidgetConfigurationScreen(
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 24.dp, vertical = 12.dp),
|
||||
.padding(start = 24.dp, end = 24.dp, top = 16.dp, bottom = 4.dp),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -496,11 +503,13 @@ private fun WidgetPreview(
|
||||
// Inner preview content
|
||||
LayoutInflater.from(ctx).inflate(R.layout.widget_config_preview, clipWrapper, true)
|
||||
|
||||
container.addView(clipWrapper, android.widget.FrameLayout.LayoutParams(
|
||||
android.widget.FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
android.widget.FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
android.view.Gravity.CENTER,
|
||||
))
|
||||
container.addView(
|
||||
clipWrapper, android.widget.FrameLayout.LayoutParams(
|
||||
android.widget.FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
android.widget.FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
android.view.Gravity.CENTER,
|
||||
)
|
||||
)
|
||||
|
||||
container
|
||||
},
|
||||
@@ -744,7 +753,14 @@ private fun HexColorInput(
|
||||
) {
|
||||
val hexString = color?.let { String.format("%06X", 0xFFFFFF and it) } ?: ""
|
||||
|
||||
var textFieldValue by remember { mutableStateOf(TextFieldValue(text = hexString, selection = TextRange(hexString.length))) }
|
||||
var textFieldValue by remember {
|
||||
mutableStateOf(
|
||||
TextFieldValue(
|
||||
text = hexString,
|
||||
selection = TextRange(hexString.length)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Sync from external color changes (e.g. swatch clicks) only when content genuinely differs
|
||||
LaunchedEffect(hexString) {
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
<string name="translators_thanks_description">darken</string>
|
||||
|
||||
<string name="widget_description">A widget showing the last known device status.</string>
|
||||
<string name="widget_config_screen_title">Widget Configuration</string>
|
||||
<string name="widget_configuration_title">Select Device</string>
|
||||
<string name="widget_configuration_description">Choose which device profile this widget should display.</string>
|
||||
<string name="common_feature_requires_pro_msg">This feature requires CAPod Pro.</string>
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package eu.darken.capod.screenshots
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
/**
|
||||
* Multi-preview annotation generating one preview per Play Store-supported locale (light mode).
|
||||
* Each [name] is the fastlane metadata directory name for direct use in the copy script.
|
||||
*/
|
||||
@Preview(locale = "en", name = "en-US", device = DS)
|
||||
@Preview(locale = "af", name = "af", device = DS)
|
||||
@Preview(locale = "am", name = "am", device = DS)
|
||||
@Preview(locale = "ar", name = "ar", device = DS)
|
||||
@Preview(locale = "az", name = "az-AZ", device = DS)
|
||||
@Preview(locale = "be", name = "be", device = DS)
|
||||
@Preview(locale = "bg", name = "bg", device = DS)
|
||||
@Preview(locale = "bn-BD", name = "bn-BD", device = DS)
|
||||
@Preview(locale = "ca", name = "ca", device = DS)
|
||||
@Preview(locale = "cs", name = "cs-CZ", device = DS)
|
||||
@Preview(locale = "da", name = "da-DK", device = DS)
|
||||
@Preview(locale = "de", name = "de-DE", device = DS)
|
||||
@Preview(locale = "el", name = "el-GR", device = DS)
|
||||
@Preview(locale = "es", name = "es-ES", device = DS)
|
||||
@Preview(locale = "es-MX", name = "es-419", device = DS)
|
||||
@Preview(locale = "et-EE", name = "et", device = DS)
|
||||
@Preview(locale = "eu-ES", name = "eu-ES", device = DS)
|
||||
@Preview(locale = "fa", name = "fa", device = DS)
|
||||
@Preview(locale = "fi", name = "fi-FI", device = DS)
|
||||
@Preview(locale = "fil", name = "fil", device = DS)
|
||||
@Preview(locale = "fr", name = "fr-FR", device = DS)
|
||||
@Preview(locale = "gl-ES", name = "gl-ES", device = DS)
|
||||
@Preview(locale = "hi-IN", name = "hi-IN", device = DS)
|
||||
@Preview(locale = "hr", name = "hr", device = DS)
|
||||
@Preview(locale = "hu", name = "hu-HU", device = DS)
|
||||
@Preview(locale = "hy-AM", name = "hy-AM", device = DS)
|
||||
@Preview(locale = "in", name = "id", device = DS)
|
||||
@Preview(locale = "is", name = "is-IS", device = DS)
|
||||
@Preview(locale = "it", name = "it-IT", device = DS)
|
||||
@Preview(locale = "iw", name = "iw-IL", device = DS)
|
||||
@Preview(locale = "ja", name = "ja-JP", device = DS)
|
||||
@Preview(locale = "ka-GE", name = "ka-GE", device = DS)
|
||||
@Preview(locale = "km-KH", name = "km-KH", device = DS)
|
||||
@Preview(locale = "kn-IN", name = "kn-IN", device = DS)
|
||||
@Preview(locale = "ko", name = "ko-KR", device = DS)
|
||||
@Preview(locale = "ky-KG", name = "ky-KG", device = DS)
|
||||
@Preview(locale = "lo-LA", name = "lo-LA", device = DS)
|
||||
@Preview(locale = "lt", name = "lt", device = DS)
|
||||
@Preview(locale = "lv", name = "lv", device = DS)
|
||||
@Preview(locale = "mk-MK", name = "mk-MK", device = DS)
|
||||
@Preview(locale = "ml-IN", name = "ml-IN", device = DS)
|
||||
@Preview(locale = "mn-MN", name = "mn-MN", device = DS)
|
||||
@Preview(locale = "mr-IN", name = "mr-IN", device = DS)
|
||||
@Preview(locale = "ms", name = "ms", device = DS)
|
||||
@Preview(locale = "my-MM", name = "my-MM", device = DS)
|
||||
@Preview(locale = "nb", name = "no-NO", device = DS)
|
||||
@Preview(locale = "ne-NP", name = "ne-NP", device = DS)
|
||||
@Preview(locale = "nl", name = "nl-NL", device = DS)
|
||||
@Preview(locale = "pl", name = "pl-PL", device = DS)
|
||||
@Preview(locale = "pt", name = "pt-PT", device = DS)
|
||||
@Preview(locale = "pt-BR", name = "pt-BR", device = DS)
|
||||
@Preview(locale = "rm", name = "rm", device = DS)
|
||||
@Preview(locale = "ro", name = "ro", device = DS)
|
||||
@Preview(locale = "ru", name = "ru-RU", device = DS)
|
||||
@Preview(locale = "sk", name = "sk", device = DS)
|
||||
@Preview(locale = "sl", name = "sl", device = DS)
|
||||
@Preview(locale = "sr", name = "sr", device = DS)
|
||||
@Preview(locale = "sv", name = "sv-SE", device = DS)
|
||||
@Preview(locale = "sw", name = "sw", device = DS)
|
||||
@Preview(locale = "ta-IN", name = "ta-IN", device = DS)
|
||||
@Preview(locale = "te-IN", name = "te-IN", device = DS)
|
||||
@Preview(locale = "th", name = "th", device = DS)
|
||||
@Preview(locale = "tr", name = "tr-TR", device = DS)
|
||||
@Preview(locale = "uk", name = "uk", device = DS)
|
||||
@Preview(locale = "vi", name = "vi", device = DS)
|
||||
@Preview(locale = "zh-CN", name = "zh-CN", device = DS)
|
||||
@Preview(locale = "zh-HK", name = "zh-HK", device = DS)
|
||||
@Preview(locale = "zh-TW", name = "zh-TW", device = DS)
|
||||
annotation class PlayStoreLocales
|
||||
|
||||
/**
|
||||
* Same locales but with night mode enabled for dark theme screenshots.
|
||||
*/
|
||||
@Preview(locale = "en", name = "en-US", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "af", name = "af", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "am", name = "am", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ar", name = "ar", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "az", name = "az-AZ", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "be", name = "be", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "bg", name = "bg", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "bn-BD", name = "bn-BD", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ca", name = "ca", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "cs", name = "cs-CZ", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "da", name = "da-DK", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "de", name = "de-DE", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "el", name = "el-GR", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "es", name = "es-ES", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "es-MX", name = "es-419", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "et-EE", name = "et", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "eu-ES", name = "eu-ES", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "fa", name = "fa", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "fi", name = "fi-FI", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "fil", name = "fil", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "fr", name = "fr-FR", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "gl-ES", name = "gl-ES", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "hi-IN", name = "hi-IN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "hr", name = "hr", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "hu", name = "hu-HU", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "hy-AM", name = "hy-AM", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "in", name = "id", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "is", name = "is-IS", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "it", name = "it-IT", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "iw", name = "iw-IL", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ja", name = "ja-JP", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ka-GE", name = "ka-GE", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "km-KH", name = "km-KH", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "kn-IN", name = "kn-IN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ko", name = "ko-KR", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ky-KG", name = "ky-KG", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "lo-LA", name = "lo-LA", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "lt", name = "lt", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "lv", name = "lv", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "mk-MK", name = "mk-MK", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ml-IN", name = "ml-IN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "mn-MN", name = "mn-MN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "mr-IN", name = "mr-IN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ms", name = "ms", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "my-MM", name = "my-MM", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "nb", name = "no-NO", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ne-NP", name = "ne-NP", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "nl", name = "nl-NL", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "pl", name = "pl-PL", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "pt", name = "pt-PT", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "pt-BR", name = "pt-BR", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "rm", name = "rm", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ro", name = "ro", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ru", name = "ru-RU", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "sk", name = "sk", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "sl", name = "sl", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "sr", name = "sr", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "sv", name = "sv-SE", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "sw", name = "sw", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "ta-IN", name = "ta-IN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "te-IN", name = "te-IN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "th", name = "th", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "tr", name = "tr-TR", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "uk", name = "uk", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "vi", name = "vi", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "zh-CN", name = "zh-CN", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "zh-HK", name = "zh-HK", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(locale = "zh-TW", name = "zh-TW", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
annotation class PlayStoreLocalesDark
|
||||
|
||||
/**
|
||||
* Smoke test subset for fast iteration (6 locales covering LTR, RTL, CJK).
|
||||
*/
|
||||
@Preview(locale = "en", name = "en-US", device = DS)
|
||||
@Preview(locale = "de", name = "de-DE", device = DS)
|
||||
@Preview(locale = "ja", name = "ja-JP", device = DS)
|
||||
@Preview(locale = "ar", name = "ar", device = DS)
|
||||
@Preview(locale = "zh-CN", name = "zh-CN", device = DS)
|
||||
@Preview(locale = "pt-BR", name = "pt-BR", device = DS)
|
||||
annotation class PlayStoreLocalesSmoke
|
||||
@@ -0,0 +1,40 @@
|
||||
// For IDE design preview, open ScreenshotPreviews.kt instead.
|
||||
package eu.darken.capod.screenshots
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.android.tools.screenshot.PreviewTest
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocales
|
||||
@Composable
|
||||
fun DashboardLight() = DashboardContent()
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocalesDark
|
||||
@Composable
|
||||
fun DashboardDark() = DashboardContent()
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocales
|
||||
@Composable
|
||||
fun DeviceProfiles() = DeviceProfilesContent()
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocales
|
||||
@Composable
|
||||
fun AddProfile() = AddProfileContent()
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocales
|
||||
@Composable
|
||||
fun SettingsIndex() = SettingsIndexContent()
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocales
|
||||
@Composable
|
||||
fun ReactionSettings() = ReactionSettingsContent()
|
||||
|
||||
@PreviewTest
|
||||
@PlayStoreLocales
|
||||
@Composable
|
||||
fun WidgetConfiguration() = WidgetConfigurationContent()
|
||||
Reference in New Issue
Block a user