mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
Fix TV detail playback single-press behavior
This commit is contained in:
@@ -7,11 +7,16 @@ import androidx.compose.ui.test.assertIsDisplayed
|
|||||||
import androidx.compose.ui.test.assertIsFocused
|
import androidx.compose.ui.test.assertIsFocused
|
||||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||||
import androidx.compose.ui.test.onAllNodesWithText
|
import androidx.compose.ui.test.onAllNodesWithText
|
||||||
|
import androidx.compose.ui.test.onRoot
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performKeyInput
|
||||||
|
import androidx.compose.ui.test.pressKey
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
import hu.bbara.purefin.core.model.CastMember
|
import hu.bbara.purefin.core.model.CastMember
|
||||||
import hu.bbara.purefin.core.model.Episode
|
import hu.bbara.purefin.core.model.Episode
|
||||||
import hu.bbara.purefin.ui.theme.AppTheme
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -66,6 +71,32 @@ class EpisodeScreenContentTest {
|
|||||||
composeRule.onAllNodesWithText("Series").assertCountEquals(0)
|
composeRule.onAllNodesWithText("Series").assertCountEquals(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun episodeScreenContent_startsPlaybackOnFirstCenterPress() {
|
||||||
|
var playCount = 0
|
||||||
|
|
||||||
|
composeRule.setContent {
|
||||||
|
AppTheme {
|
||||||
|
EpisodeScreenContent(
|
||||||
|
episode = sampleEpisode(progress = 63.0),
|
||||||
|
seriesTitle = "Severance",
|
||||||
|
onPlay = { playCount++ }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
composeRule.onNodeWithTag(EpisodePlayButtonTag).assertIsFocused()
|
||||||
|
composeRule.onRoot().performKeyInput {
|
||||||
|
pressKey(Key.DirectionCenter)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
assertEquals(1, playCount)
|
||||||
|
}
|
||||||
|
|
||||||
private fun sampleEpisode(progress: Double?): Episode {
|
private fun sampleEpisode(progress: Double?): Episode {
|
||||||
val seriesId = UUID.fromString("11111111-1111-1111-1111-111111111111")
|
val seriesId = UUID.fromString("11111111-1111-1111-1111-111111111111")
|
||||||
val seasonId = UUID.fromString("22222222-2222-2222-2222-222222222222")
|
val seasonId = UUID.fromString("22222222-2222-2222-2222-222222222222")
|
||||||
|
|||||||
@@ -7,11 +7,16 @@ import androidx.compose.ui.test.assertIsDisplayed
|
|||||||
import androidx.compose.ui.test.assertIsFocused
|
import androidx.compose.ui.test.assertIsFocused
|
||||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||||
import androidx.compose.ui.test.onAllNodesWithText
|
import androidx.compose.ui.test.onAllNodesWithText
|
||||||
|
import androidx.compose.ui.test.onRoot
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performKeyInput
|
||||||
|
import androidx.compose.ui.test.pressKey
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
import hu.bbara.purefin.core.model.CastMember
|
import hu.bbara.purefin.core.model.CastMember
|
||||||
import hu.bbara.purefin.core.model.Movie
|
import hu.bbara.purefin.core.model.Movie
|
||||||
import hu.bbara.purefin.ui.theme.AppTheme
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -43,6 +48,31 @@ class MovieScreenContentTest {
|
|||||||
.assertIsFocused()
|
.assertIsFocused()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun movieScreenContent_startsPlaybackOnFirstCenterPress() {
|
||||||
|
var playCount = 0
|
||||||
|
|
||||||
|
composeRule.setContent {
|
||||||
|
AppTheme {
|
||||||
|
MovieScreenContent(
|
||||||
|
movie = sampleMovie(progress = 42.0),
|
||||||
|
onPlay = { playCount++ }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
composeRule.onNodeWithTag(MoviePlayButtonTag).assertIsFocused()
|
||||||
|
composeRule.onRoot().performKeyInput {
|
||||||
|
pressKey(Key.DirectionCenter)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
assertEquals(1, playCount)
|
||||||
|
}
|
||||||
|
|
||||||
private fun sampleMovie(progress: Double?): Movie {
|
private fun sampleMovie(progress: Double?): Movie {
|
||||||
return Movie(
|
return Movie(
|
||||||
id = UUID.fromString("11111111-1111-1111-1111-111111111111"),
|
id = UUID.fromString("11111111-1111-1111-1111-111111111111"),
|
||||||
|
|||||||
@@ -5,13 +5,18 @@ import androidx.compose.ui.test.ExperimentalTestApi
|
|||||||
import androidx.compose.ui.test.assertIsDisplayed
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
import androidx.compose.ui.test.assertIsFocused
|
import androidx.compose.ui.test.assertIsFocused
|
||||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||||
|
import androidx.compose.ui.test.onRoot
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
import androidx.compose.ui.test.performKeyInput
|
||||||
|
import androidx.compose.ui.test.pressKey
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
import hu.bbara.purefin.core.model.CastMember
|
import hu.bbara.purefin.core.model.CastMember
|
||||||
import hu.bbara.purefin.core.model.Episode
|
import hu.bbara.purefin.core.model.Episode
|
||||||
import hu.bbara.purefin.core.model.Season
|
import hu.bbara.purefin.core.model.Season
|
||||||
import hu.bbara.purefin.core.model.Series
|
import hu.bbara.purefin.core.model.Series
|
||||||
import hu.bbara.purefin.ui.theme.AppTheme
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -65,6 +70,31 @@ class SeriesScreenContentTest {
|
|||||||
.assertIsFocused()
|
.assertIsFocused()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun seriesScreenContent_startsPlaybackOnFirstCenterPress() {
|
||||||
|
var playCount = 0
|
||||||
|
|
||||||
|
composeRule.setContent {
|
||||||
|
AppTheme {
|
||||||
|
SeriesScreenContent(
|
||||||
|
series = sampleSeriesWithEpisodes(),
|
||||||
|
onPlayEpisode = { playCount++ }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
composeRule.onNodeWithTag(SeriesPlayButtonTag).assertIsFocused()
|
||||||
|
composeRule.onRoot().performKeyInput {
|
||||||
|
pressKey(Key.DirectionCenter)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
assertEquals(1, playCount)
|
||||||
|
}
|
||||||
|
|
||||||
private fun sampleSeriesWithEpisodes(): Series {
|
private fun sampleSeriesWithEpisodes(): Series {
|
||||||
val seriesId = UUID.fromString("11111111-1111-1111-1111-111111111111")
|
val seriesId = UUID.fromString("11111111-1111-1111-1111-111111111111")
|
||||||
val seasonId = UUID.fromString("22222222-2222-2222-2222-222222222222")
|
val seasonId = UUID.fromString("22222222-2222-2222-2222-222222222222")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.withFrameNanos
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -75,6 +76,7 @@ internal fun EpisodeScreenContent(
|
|||||||
val playFocusRequester = remember { FocusRequester() }
|
val playFocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
LaunchedEffect(episode.id) {
|
LaunchedEffect(episode.id) {
|
||||||
|
withFrameNanos { }
|
||||||
playFocusRequester.requestFocus()
|
playFocusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.withFrameNanos
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -54,6 +55,7 @@ internal fun MovieScreenContent(
|
|||||||
val playFocusRequester = remember { FocusRequester() }
|
val playFocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
LaunchedEffect(movie.id) {
|
LaunchedEffect(movie.id) {
|
||||||
|
withFrameNanos { }
|
||||||
playFocusRequester.requestFocus()
|
playFocusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.withFrameNanos
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -63,6 +64,7 @@ internal fun SeriesScreenContent(
|
|||||||
val firstContentFocusRequester = remember { FocusRequester() }
|
val firstContentFocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
LaunchedEffect(series.id, nextUpEpisode?.id) {
|
LaunchedEffect(series.id, nextUpEpisode?.id) {
|
||||||
|
withFrameNanos { }
|
||||||
if (nextUpEpisode != null) {
|
if (nextUpEpisode != null) {
|
||||||
playFocusRequester.requestFocus()
|
playFocusRequester.requestFocus()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ fun MediaResumeButton(
|
|||||||
.border(3.dp, focusBorderColor, focusShape)
|
.border(3.dp, focusBorderColor, focusShape)
|
||||||
.clip(focusShape)
|
.clip(focusShape)
|
||||||
.onFocusChanged { isFocused = it.isFocused || it.hasFocus }
|
.onFocusChanged { isFocused = it.isFocused || it.hasFocus }
|
||||||
.focusable()
|
|
||||||
.clickable(onClick = onClick)
|
.clickable(onClick = onClick)
|
||||||
|
.focusable()
|
||||||
) {
|
) {
|
||||||
// Bottom layer: inverted colors (visible for the remaining %)
|
// Bottom layer: inverted colors (visible for the remaining %)
|
||||||
Box(
|
Box(
|
||||||
|
|||||||
Reference in New Issue
Block a user