mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
home: reveal new front items and brick-pack genre chips
Scroll a recently played row back to the front when a new first item appears while it is already at/near the start; the lazy layout otherwise anchors the old first item and hides the new one. Balance the three genre rows by estimated width and tighten their gap.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package com.subtracks.ui.home
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class GenreRowsTest {
|
||||
private fun weight(genre: String) = genre.length + 6
|
||||
|
||||
@Test
|
||||
fun everyGenreIsPlacedExactlyOnce() {
|
||||
val genres = listOf("Electronic", "Rock", "Pop", "Jazz", "Classical", "Ambient")
|
||||
|
||||
val rows = brickRows(genres, 3)
|
||||
|
||||
assertEquals(3, rows.size)
|
||||
assertEquals(genres.sorted(), rows.flatten().sorted())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rowsBalanceByWidthNotCount() {
|
||||
val genres =
|
||||
listOf(
|
||||
"VeryLongGenreName1",
|
||||
"A",
|
||||
"B",
|
||||
"VeryLongGenreName2",
|
||||
"C",
|
||||
"D",
|
||||
"VeryLongGenreName3",
|
||||
"E",
|
||||
"F",
|
||||
)
|
||||
|
||||
val rows = brickRows(genres, 3)
|
||||
|
||||
val widths = rows.map { row -> row.sumOf(::weight) }
|
||||
val largestChip = genres.maxOf(::weight)
|
||||
assertTrue(widths.max() - widths.min() <= largestChip)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.subtracks.ui.home
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers
|
||||
import com.subtracks.ui.theme.SubtracksTheme
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.GraphicsMode
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
||||
@Config(qualifiers = RobolectricDeviceQualifiers.PixelXL)
|
||||
class HomeRevealScrollTest {
|
||||
@get:Rule
|
||||
val composeRule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
@Test
|
||||
fun aNewFrontItemAtTheStartScrollsBack() {
|
||||
val labels = mutableStateOf(listOf("a", "b", "c", "d", "e"))
|
||||
lateinit var state: LazyListState
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
state = rememberLazyListState()
|
||||
RevealNewFrontItem(labels.value, state) { it }
|
||||
LazyRow(state = state, modifier = Modifier.fillMaxSize()) {
|
||||
items(labels.value, key = { it }) { label ->
|
||||
Text(label, modifier = Modifier.width(200.dp).height(80.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
composeRule.waitForIdle()
|
||||
assertEquals(0, state.firstVisibleItemIndex)
|
||||
|
||||
composeRule.runOnIdle { labels.value = listOf("z") + labels.value }
|
||||
|
||||
composeRule.waitForIdle()
|
||||
assertEquals(0, state.firstVisibleItemIndex)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.subtracks.ui.home
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class HomeRevealTest {
|
||||
@Test
|
||||
fun noPreviousFrontDoesNotReveal() {
|
||||
assertFalse(shouldRevealNewFront(previousKey = null, firstKey = "a", firstVisibleItemIndex = 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun noFrontItemDoesNotReveal() {
|
||||
assertFalse(shouldRevealNewFront(previousKey = "a", firstKey = null, firstVisibleItemIndex = 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun anUnchangedFrontDoesNotReveal() {
|
||||
assertFalse(shouldRevealNewFront(previousKey = "a", firstKey = "a", firstVisibleItemIndex = 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aChangedFrontRevealsAtTheStart() {
|
||||
assertTrue(shouldRevealNewFront(previousKey = "a", firstKey = "b", firstVisibleItemIndex = 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aChangedFrontRevealsOneRowIn() {
|
||||
assertTrue(shouldRevealNewFront(previousKey = "a", firstKey = "b", firstVisibleItemIndex = 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aChangedFrontDoesNotRevealWhenScrolledAway() {
|
||||
assertFalse(shouldRevealNewFront(previousKey = "a", firstKey = "b", firstVisibleItemIndex = 2))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user