From 70727e3ecc833441d38f13a365a144c2ce67d250 Mon Sep 17 00:00:00 2001 From: Daniel Frett Date: Fri, 3 May 2024 08:38:46 -0600 Subject: [PATCH] move LessonToolCard to it's own source file --- .../cru/godtools/ui/tools/LessonToolCard.kt | 82 +++++++++++++++++++ .../cru/godtools/ui/tools/ToolCardLayouts.kt | 54 ------------ .../ui/tools/LessonToolCardPaparazziTest.kt | 73 +++++++++++++++++ 3 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 app/src/main/kotlin/org/cru/godtools/ui/tools/LessonToolCard.kt create mode 100644 app/src/testDebug/kotlin/org/cru/godtools/ui/tools/LessonToolCardPaparazziTest.kt diff --git a/app/src/main/kotlin/org/cru/godtools/ui/tools/LessonToolCard.kt b/app/src/main/kotlin/org/cru/godtools/ui/tools/LessonToolCard.kt new file mode 100644 index 0000000000..01893535ae --- /dev/null +++ b/app/src/main/kotlin/org/cru/godtools/ui/tools/LessonToolCard.kt @@ -0,0 +1,82 @@ +package org.cru.godtools.ui.tools + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ElevatedCard +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.ccci.gto.android.common.androidx.compose.ui.draw.invisibleIf +import org.cru.godtools.base.ui.util.ProvideLayoutDirectionFromLocale +import org.cru.godtools.model.Language + +@Composable +fun LessonToolCard( + toolCode: String, + modifier: Modifier = Modifier, + selectedLanguage: Language? = null, + viewModel: ToolViewModels.ToolViewModel = toolViewModels[toolCode], + onEvent: (ToolCardEvent) -> Unit = {}, +) { + val state = viewModel.toState(language = selectedLanguage) + val tool by rememberUpdatedState(state.tool) + val translation by rememberUpdatedState(state.translation) + + LessonToolCard( + state = remember(state) { + state.copy(eventSink = { + when (it) { + ToolCard.Event.Click -> + onEvent(ToolCardEvent.Click(tool?.code, tool?.type, translation?.languageCode)) + else -> TODO() + } + }) + }, + modifier = modifier, + ) +} + +@Composable +fun LessonToolCard(state: ToolCard.State, modifier: Modifier = Modifier) { + val isLoaded by rememberUpdatedState(state.isLoaded) + val translation by rememberUpdatedState(state.translation) + val language by rememberUpdatedState(state.language) + val languageAvailable by rememberUpdatedState(state.languageAvailable) + val eventSink by rememberUpdatedState(state.eventSink) + + ProvideLayoutDirectionFromLocale(locale = { translation?.languageCode }) { + ElevatedCard( + onClick = { eventSink(ToolCard.Event.Click) }, + elevation = toolCardElevation, + modifier = modifier.fillMaxWidth() + ) { + ToolBanner(state, modifier = Modifier.aspectRatio(335f / 80f)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + ToolName(state, minLines = 2, modifier = Modifier.fillMaxWidth()) + + ToolCardInfoContent { + AvailableInLanguage( + language = language, + available = languageAvailable, + horizontalArrangement = Arrangement.End, + modifier = Modifier + .align(Alignment.End) + .invisibleIf { !isLoaded || language == null } + ) + } + } + } + } +} diff --git a/app/src/main/kotlin/org/cru/godtools/ui/tools/ToolCardLayouts.kt b/app/src/main/kotlin/org/cru/godtools/ui/tools/ToolCardLayouts.kt index 86a3532cc7..75dd70b52a 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/tools/ToolCardLayouts.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/tools/ToolCardLayouts.kt @@ -37,12 +37,10 @@ import coil.compose.AsyncImage import java.util.Locale import org.ccci.gto.android.common.androidx.compose.foundation.layout.widthIn import org.ccci.gto.android.common.androidx.compose.foundation.text.minLinesHeight -import org.ccci.gto.android.common.androidx.compose.ui.draw.invisibleIf import org.cru.godtools.base.ui.theme.GodToolsTheme import org.cru.godtools.base.ui.util.ProvideLayoutDirectionFromLocale import org.cru.godtools.base.ui.util.getCategory import org.cru.godtools.base.ui.util.withCompatFontFamilyFor -import org.cru.godtools.model.Language import org.cru.godtools.model.Tool import org.cru.godtools.model.getName @@ -93,58 +91,6 @@ fun PreloadTool(tool: Tool) { toolViewModels[code, tool] } -@Composable -fun LessonToolCard( - toolCode: String, - modifier: Modifier = Modifier, - selectedLanguage: Language? = null, - viewModel: ToolViewModels.ToolViewModel = toolViewModels[toolCode], - onEvent: (ToolCardEvent) -> Unit = {}, -) { - val state = viewModel.toState(language = selectedLanguage) - val tool by rememberUpdatedState(state.tool) - val language by rememberUpdatedState(state.language) - val languageAvailable by rememberUpdatedState(state.languageAvailable) - val translation by rememberUpdatedState(state.translation) - - ProvideLayoutDirectionFromLocale(locale = { translation?.languageCode }) { - ElevatedCard( - onClick = { - onEvent( - ToolCardEvent.Click( - tool?.code, - tool?.type, - translation?.languageCode - ) - ) - }, - elevation = toolCardElevation, - modifier = modifier.fillMaxWidth() - ) { - ToolBanner(state, modifier = Modifier.aspectRatio(335f / 80f)) - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { - ToolName(state, minLines = 2, modifier = Modifier.fillMaxWidth()) - - ToolCardInfoContent { - AvailableInLanguage( - language = language, - available = languageAvailable, - horizontalArrangement = Arrangement.End, - modifier = Modifier - .align(Alignment.End) - .invisibleIf { !state.isLoaded || !languageAvailable } - ) - } - } - } - } -} - @Composable fun ToolCard( state: ToolCard.State, diff --git a/app/src/testDebug/kotlin/org/cru/godtools/ui/tools/LessonToolCardPaparazziTest.kt b/app/src/testDebug/kotlin/org/cru/godtools/ui/tools/LessonToolCardPaparazziTest.kt new file mode 100644 index 0000000000..49db77e643 --- /dev/null +++ b/app/src/testDebug/kotlin/org/cru/godtools/ui/tools/LessonToolCardPaparazziTest.kt @@ -0,0 +1,73 @@ +package org.cru.godtools.ui.tools + +import android.graphics.drawable.Drawable +import coil.Coil +import coil.ImageLoader +import coil.annotation.ExperimentalCoilApi +import coil.test.FakeImageLoaderEngine +import com.android.resources.NightMode +import com.google.testing.junit.testparameterinjector.TestParameter +import com.google.testing.junit.testparameterinjector.TestParameterInjector +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import org.cru.godtools.model.randomTranslation +import org.cru.godtools.ui.BasePaparazziTest +import org.junit.runner.RunWith + +@RunWith(TestParameterInjector::class) +class LessonToolCardPaparazziTest( + @TestParameter nightMode: NightMode, + @TestParameter accessibilityMode: AccessibilityMode, +) : BasePaparazziTest(nightMode = nightMode, accessibilityMode = accessibilityMode) { + private val toolState = ToolCardStateTestData.tool + + @BeforeTest + @OptIn(ExperimentalCoilApi::class, ExperimentalCoroutinesApi::class) + fun setup() { + Dispatchers.setMain(UnconfinedTestDispatcher()) + val file = Drawable.createFromStream(javaClass.getResourceAsStream("banner.jpg"), "banner.jpg")!! + Coil.setImageLoader( + ImageLoader.Builder(paparazzi.context) + .components { + add( + FakeImageLoaderEngine.Builder() + .intercept(ToolCardStateTestData.banner, file) + .build() + ) + } + .build() + ) + } + + @AfterTest + @OptIn(ExperimentalCoroutinesApi::class) + fun cleanup() { + Coil.reset() + Dispatchers.resetMain() + } + + @Test + fun `LessonToolCard() - Default`() = centerInSnapshot { LessonToolCard(toolState) } + + @Test + fun `LessonToolCard() - Long Title`() = centerInSnapshot { + LessonToolCard( + toolState.copy( + translation = randomTranslation( + name = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" + ) + ) + ) + } + + @Test + fun `LessonToolCard() - Not Available`() = centerInSnapshot { + LessonToolCard(toolState.copy(appLanguageAvailable = false)) + } +}