Measure native Discover typography and focus boundaries
This commit is contained in:
parent
6f430439a6
commit
90e956b157
7 changed files with 87 additions and 11 deletions
|
|
@ -73,7 +73,13 @@ private fun RequestSheet(state: DiscoverState, sheet: RequestSheetState) {
|
|||
RequestPhase.Choose, RequestPhase.Sending -> RequestChoices(state, sheet)
|
||||
RequestPhase.LoadingRecipients -> {
|
||||
Text("For", color = C.dim, style = WolfskinTokens.Type.label)
|
||||
repeat(3) { Box(Modifier.fillMaxWidth().height(L.sheetRow).background(C.listRowRest, RoundedCornerShape(WolfskinTokens.Radius.listRow))) }
|
||||
repeat(3) {
|
||||
Row(Modifier.fillMaxWidth().height(L.sheetRow).background(C.listRowRest, RoundedCornerShape(WolfskinTokens.Radius.listRow)).padding(horizontal = D.sheetRowPadding),
|
||||
horizontalArrangement = Arrangement.spacedBy(D.sheetPersonGap), verticalAlignment = Alignment.CenterVertically) {
|
||||
Box(Modifier.size(D.sheetAvatar).background(C.surface2, CircleShape))
|
||||
Box(Modifier.width(D.skeletonNameWidth).height(D.skeletonNameHeight).background(C.surface2, RoundedCornerShape(WolfskinTokens.Shell.skeletonRadius)))
|
||||
}
|
||||
}
|
||||
DiscoverButton("Close", true) { state.overlay = null }
|
||||
}
|
||||
else -> RequestOutcome(state, sheet)
|
||||
|
|
@ -89,13 +95,13 @@ private fun RequestChoices(state: DiscoverState, sheet: RequestSheetState) {
|
|||
Row(Modifier.fillMaxWidth().height(L.sheetRow).alpha(if (disabled) .5f else 1f)
|
||||
.focusScale(focused, WolfskinTokens.Focus.scaleRow)
|
||||
.background(if (focused) C.fg else C.listRowRest, RoundedCornerShape(WolfskinTokens.Radius.listRow))
|
||||
.clickable(enabled = !disabled) { sheet.selected = index; sheet.focus = sheet.buttonIndex }
|
||||
.clickable(enabled = !disabled && sheet.phase == RequestPhase.Choose) { sheet.selected = index; sheet.focus = sheet.buttonIndex }
|
||||
.padding(horizontal = D.sheetRowPadding), horizontalArrangement = Arrangement.spacedBy(D.sheetPersonGap), verticalAlignment = Alignment.CenterVertically) {
|
||||
Avatar(person, D.sheetAvatar, WolfskinTokens.Type.avatarLetterSheetRow)
|
||||
Text(person.name + if (person.key == sheet.viewer.key) " (you)" else "", Modifier.weight(1f), color = if (focused) C.onFocus else C.fg, style = WolfskinTokens.Type.listTitle)
|
||||
if (disabled) Text("In library", color = if (focused) C.onFocus else C.muted, style = WolfskinTokens.Type.caption)
|
||||
else Box(Modifier.size(D.sheetRadio).background(if (sheet.selected == index) C.accent else C.listRowRest.copy(alpha = 0f), CircleShape)
|
||||
.border(if (sheet.selected == index) WolfskinTokens.Shell.zero else WolfskinTokens.Focus.ringCardRing, if (focused) C.onFocus.copy(alpha = .5f) else C.fg.copy(alpha = .35f), CircleShape), contentAlignment = Alignment.Center) {
|
||||
.border(if (sheet.selected != index || focused) D.sheetRadioRing else WolfskinTokens.Shell.zero, if (focused) C.onFocus.copy(alpha = .5f) else C.fg.copy(alpha = .35f), CircleShape), contentAlignment = Alignment.Center) {
|
||||
if (sheet.selected == index) Box(Modifier.size(D.sheetRadioDot).background(C.onFocus, CircleShape))
|
||||
}
|
||||
}
|
||||
|
|
@ -103,7 +109,7 @@ private fun RequestChoices(state: DiscoverState, sheet: RequestSheetState) {
|
|||
if (sheet.blocked) Text("Season details are unknown right now, so this series can’t be requested yet. Nothing was sent.", color = C.warn, style = WolfskinTokens.Type.caption)
|
||||
else if (sheet.title.type == "tv" && !sheet.held) Text("Whole series: every listed season. Other seasons may download too.", color = C.dim, style = WolfskinTokens.Type.caption)
|
||||
Spacer(Modifier.height(D.sheetButtonTop))
|
||||
DiscoverButton(if (sheet.blocked) "Close" else sheet.buttonLabel, sheet.focus == sheet.buttonIndex) { sheet.focus = sheet.buttonIndex; state.key(ShellKey.Ok, true) }
|
||||
DiscoverButton(if (sheet.blocked) "Close" else sheet.buttonLabel, sheet.focus == sheet.buttonIndex, glyph = if (sheet.blocked) null else "plus") { sheet.focus = sheet.buttonIndex; state.key(ShellKey.Ok, true) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -333,5 +333,8 @@ object WolfskinTokens {
|
|||
val entryPaddingX = 11.0.dp
|
||||
val entryPaddingY = 10.0.dp
|
||||
val entryText = TextStyle(fontSize = 15.0.sp, fontWeight = FontWeight(800), lineHeight = 19.5.sp, letterSpacing = -0.01.em)
|
||||
val sheetRadioRing = 1.5.dp
|
||||
val skeletonNameWidth = 130.0.dp
|
||||
val skeletonNameHeight = 17.0.dp
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ import androidx.compose.ui.graphics.asImageBitmap
|
|||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onRoot
|
||||
import androidx.compose.ui.test.onAllNodesWithText
|
||||
import androidx.compose.ui.semantics.SemanticsActions
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import com.github.takahirom.roborazzi.captureRoboImage
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -41,7 +46,8 @@ class DiscoverCaptureTest {
|
|||
}
|
||||
|
||||
private fun capture(name: String, person: String = "justin", snapshotTransform: (DiscoverSnapshot) -> DiscoverSnapshot = { it }, configure: (DiscoverState) -> Unit = {}) {
|
||||
val shell = ShellState(fixturePeople(), person).apply { pickerVisible = false; enterDestination("discover") }
|
||||
val titleState = name.substringAfter("st-").toInt() in setOf(58, 59, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 87, 110)
|
||||
val shell = ShellState(fixturePeople(), person).apply { pickerVisible = false; enterDestination(if (titleState) "home" else "discover") }
|
||||
val snapshot = snapshotTransform(fixture.snapshot(person))
|
||||
val state = DiscoverState(shell, snapshot, RecordingDiscoverOperations(snapshot, person), CoroutineScope(Dispatchers.Main.immediate),
|
||||
onPush = shell::enterDestination, onPop = { shell.enterDestination("discover") }, serviceLanes = fixture::service)
|
||||
|
|
@ -56,8 +62,28 @@ class DiscoverCaptureTest {
|
|||
}
|
||||
rule.mainClock.advanceTimeBy(1000)
|
||||
rule.waitForIdle()
|
||||
val directory = File(System.getProperty("wolfskin.captureDirectory")).apply { mkdirs() }
|
||||
val directory = File(requireNotNull(System.getProperty("wolfskin.captureDirectory"))).apply { mkdirs() }
|
||||
rule.onRoot().captureRoboImage(File(directory, "$name.png").absolutePath)
|
||||
recordTypography(directory, name, state)
|
||||
}
|
||||
|
||||
private fun recordTypography(directory: File, name: String, state: DiscoverState) {
|
||||
val rows = JSONArray()
|
||||
val labels = listOfNotNull(state.hero?.title, "Request", "For", "Justin (you)", "Hidden picks", "Netflix", "Popular movies")
|
||||
labels.forEach { text ->
|
||||
rule.onAllNodesWithText(text, useUnmergedTree = true).fetchSemanticsNodes().forEach { node ->
|
||||
val layouts = mutableListOf<TextLayoutResult>()
|
||||
node.config[SemanticsActions.GetTextLayoutResult].action?.invoke(layouts)
|
||||
layouts.forEach { layout ->
|
||||
rows.put(JSONObject().put("text", text).put("lines", layout.lineCount)
|
||||
.put("fontSizeSp", layout.layoutInput.style.fontSize.value).put("fontWeight", layout.layoutInput.style.fontWeight?.weight)
|
||||
.put("lineHeightSp", layout.layoutInput.style.lineHeight.value).put("trim", layout.layoutInput.style.lineHeightStyle?.trim.toString())
|
||||
.put("density", layout.layoutInput.density.density).put("fontScale", layout.layoutInput.density.fontScale)
|
||||
.put("left", node.boundsInRoot.left).put("top", node.boundsInRoot.top).put("width", node.boundsInRoot.width).put("height", node.boundsInRoot.height))
|
||||
}
|
||||
}
|
||||
}
|
||||
File(directory, "$name-type-metrics.json").writeText(rows.toString(2))
|
||||
}
|
||||
|
||||
@Test fun st029_discover() = capture("st-029")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue