Skip to content

Commit

Permalink
move LessonToolCard to it's own source file
Browse files Browse the repository at this point in the history
  • Loading branch information
frett committed Nov 21, 2024
1 parent 4e2212d commit 70727e3
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 54 deletions.
82 changes: 82 additions & 0 deletions app/src/main/kotlin/org/cru/godtools/ui/tools/LessonToolCard.kt
Original file line number Diff line number Diff line change
@@ -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 }
)
}
}
}
}
}
54 changes: 0 additions & 54 deletions app/src/main/kotlin/org/cru/godtools/ui/tools/ToolCardLayouts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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))
}
}

0 comments on commit 70727e3

Please sign in to comment.