Skip to content

Commit

Permalink
Develop (#36)
Browse files Browse the repository at this point in the history
* Increase line height on the text items

* Style the question card

* Lesson UI fixes

* Fix broken Lesson card scaling

* WIP: Lesson 1 content

* Add support for question clarification

* WIP: Lesson 1 + fixes

* Fix stuff

* Fix broken server test
  • Loading branch information
ILIYANGERMANOV authored Jun 4, 2024
1 parent 2d6f71d commit 1613993
Show file tree
Hide file tree
Showing 17 changed files with 375 additions and 83 deletions.
10 changes: 7 additions & 3 deletions composeApp/src/commonMain/kotlin/component/text/Body.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.sp

Expand All @@ -18,7 +19,8 @@ fun BodyBig(
modifier = modifier,
text = text,
style = MaterialTheme.typography.body1.copy(
fontSize = 18.sp
fontSize = 18.sp,
lineHeight = 24.sp,
),
textAlign = textAlign,
)
Expand All @@ -41,12 +43,14 @@ fun Body(
fun BodySmall(
text: String,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colors.onBackground
color: Color = MaterialTheme.colors.onBackground,
fontWeight: FontWeight? = null,
) {
Text(
modifier = modifier,
text = text,
color = color,
style = MaterialTheme.typography.body2
style = MaterialTheme.typography.body2,
fontWeight = fontWeight,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import component.isLargeScreen
Expand Down Expand Up @@ -45,17 +47,23 @@ fun LessonCard(
onClick = onLessonClick
) {
Row {
val height = 148.dp
var height by remember { mutableStateOf(132.dp) }
LessonImage(
modifier = Modifier.height(height),
imageUrl = lesson.imageUrl
)
val density = LocalDensity.current
Column(
modifier = Modifier.height(height)
modifier = Modifier
.onSizeChanged {
height = minOf(with(density) { it.height.toDp() }, height)
}
.defaultMinSize(minHeight = height)
.padding(
start = if (isLargeScreen()) 24.dp else 20.dp,
end = if (isLargeScreen()) 16.dp else 12.dp
),
)
.padding(vertical = 16.dp),
verticalArrangement = Arrangement.Center,
) {
Title(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ data class TextItemViewState(

@Immutable
enum class TextStyleViewState {
Heading, Body, BodyBigSpacing
Heading,
Body,
BodyMediumSpacing,
BodyBigSpacing,
}

@Immutable
data class QuestionItemViewState(
override val id: LessonItemIdViewState,
val question: String,
val clarification: String?,
val type: QuestionTypeViewState,
val answers: ImmutableList<AnswerViewState>,
val answered: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ui.screen.lesson.*
import ui.screen.lesson.composable.item.*

val ItemSpacing = 12.dp
val ItemSpacingMedium = 24.dp
val ItemSpacingBig = 48.dp

@Composable
Expand Down Expand Up @@ -73,8 +74,9 @@ private fun LessonItemsLazyColum(
}
val listState = rememberLazyListState()

LaunchedEffect(viewState.items.size) {
if (viewState.items.size > 1) {
val itemsCount = viewState.items.size
LaunchedEffect(itemsCount) {
if (itemsCount >= 2 && !viewState.items[itemsCount - 2].isQuestion()) {
// ensure auto scrolls works for images that are loading
repeat(4) {
listState.animateScrollToItem(viewState.items.lastIndex)
Expand Down Expand Up @@ -171,4 +173,9 @@ private fun LessonItemsLazyColum(
)
}
}
}

private fun LessonItemViewState.isQuestion(): Boolean = when (this) {
is QuestionItemViewState, is OpenQuestionItemViewState -> true
else -> false
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import ui.theme.Gray
fun LessonProgressBar(
viewState: LessonProgressViewState,
modifier: Modifier = Modifier,
progressBarWidth: Dp = 124.dp,
progressBarWidth: Dp = 164.dp,
) {
Box(modifier = modifier) {
val progressPercent by animateFloatAsState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import androidx.compose.ui.unit.dp
import io.kamel.image.KamelImage
import io.kamel.image.asyncPainterResource
import ui.screen.lesson.ImageItemViewState
import ui.screen.lesson.composable.ItemSpacing
import ui.screen.lesson.composable.ItemSpacingMedium

@Composable
fun ImageLessonItem(
Expand All @@ -19,7 +19,7 @@ fun ImageLessonItem(
) {
KamelImage(
modifier = modifier
.padding(top = ItemSpacing)
.padding(top = ItemSpacingMedium)
.size(264.dp)
.clip(RoundedCornerShape(16.dp)),
resource = asyncPainterResource(viewState.imageUrl),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ fun QuestionLessonItem(
modifier = modifier.padding(top = ItemSpacingBig),
) {
QuestionText(text = viewState.question)
if (viewState.clarification != null) {
Spacer(Modifier.height(4.dp))
ClarificationText(clarification = viewState.clarification)
}
if (viewState.type == QuestionTypeViewState.MultipleChoice) {
Spacer(Modifier.height(4.dp))
SelectAllThatApplyText()
Expand All @@ -58,14 +62,25 @@ fun QuestionLessonItem(
}
}

@Composable
private fun ClarificationText(
clarification: String,
modifier: Modifier = Modifier,
) {
BodySmall(
modifier = modifier,
text = clarification,
color = MaterialTheme.colors.secondary,
)
}

@Composable
private fun SelectAllThatApplyText(
modifier: Modifier = Modifier,
) {
BodySmall(
modifier = modifier,
text = "Select all that apply:"
text = "Select all that apply:",
)
}

Expand All @@ -77,14 +92,18 @@ private fun AnswerItem(
modifier: Modifier = Modifier,
onCheckedChange: (Boolean) -> Unit
) {
val correct = viewState.correct.takeIf { questionAnswered }
Row(
modifier = modifier.clickable { onCheckedChange(!viewState.selected) },
modifier = modifier.clickable(
enabled = correct == null,
onClick = { onCheckedChange(!viewState.selected) }
),
verticalAlignment = Alignment.CenterVertically
) {
AnswerCheckbox(
questionType = questionType,
selected = viewState.selected,
correct = viewState.correct.takeIf { questionAnswered },
correct = correct,
onCheckedChange = onCheckedChange
)
Spacer(modifier = Modifier.width(12.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ui.screen.lesson.TextItemViewState
import ui.screen.lesson.TextStyleViewState
import ui.screen.lesson.composable.ItemSpacing
import ui.screen.lesson.composable.ItemSpacingBig
import ui.screen.lesson.composable.ItemSpacingMedium

@Composable
fun TextLessonItem(
Expand All @@ -22,20 +23,31 @@ fun TextLessonItem(
text = viewState.text
)

TextStyleViewState.Body -> BodyBig(
modifier = modifier.padding(
top = ItemSpacing
),
TextStyleViewState.Body -> BodyText(
modifier = modifier.padding(top = ItemSpacing),
text = viewState.text,
textAlign = TextAlign.Start,
)

TextStyleViewState.BodyBigSpacing -> BodyBig(
modifier = modifier.padding(
top = ItemSpacingBig
),
TextStyleViewState.BodyMediumSpacing -> BodyText(
modifier = modifier.padding(top = ItemSpacingMedium),
text = viewState.text,
)

TextStyleViewState.BodyBigSpacing -> BodyText(
modifier = modifier.padding(top = ItemSpacingBig),
text = viewState.text,
textAlign = TextAlign.Start,
)
}
}

@Composable
private fun BodyText(
text: String,
modifier: Modifier = Modifier,
) {
BodyBig(
modifier = modifier,
text = text,
textAlign = TextAlign.Start,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import androidx.compose.material.Card
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import component.ScreenType.*
import component.screenType

@Composable
fun QuestionCard(
Expand All @@ -19,8 +21,20 @@ fun QuestionCard(
shape = RoundedCornerShape(16.dp),
elevation = 4.dp
) {
val screenType = screenType()
Column(
modifier = Modifier.padding(16.dp),
modifier = Modifier.padding(
horizontal = when (screenType) {
Mobile -> 16.dp
Tablet -> 24.dp
Desktop -> 24.dp
},
vertical = when (screenType) {
Mobile -> 16.dp
Tablet -> 16.dp
Desktop -> 24.dp
},
),
content = content,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class LessonViewStateMapper(
}
val total = (content.items.size - unreachablePaths - 1) // -1 for the finish item
.coerceAtLeast(0)
platform.log(LogLevel.Debug, "done = $done, $unreachablePaths = $unreachablePaths, total = $total")
return LessonProgressViewState(done, total)
}

Expand Down Expand Up @@ -128,6 +129,7 @@ class LessonViewStateMapper(
): QuestionItemViewState = QuestionItemViewState(
id = id.toViewState(),
question = question,
clarification = clarification,
type = if (correct.size == 1) QuestionTypeViewState.SingleChoice else QuestionTypeViewState.MultipleChoice,
answers = answers.map { it.toViewState(this, localState) }
.toImmutableList(),
Expand All @@ -151,6 +153,7 @@ class LessonViewStateMapper(
style = when (style) {
Heading -> TextStyleViewState.Heading
Body -> TextStyleViewState.Body
BodyMediumSpacing -> TextStyleViewState.BodyMediumSpacing
BodyBigSpacing -> TextStyleViewState.BodyBigSpacing
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ object ProgrammingFundamentals : CourseDsl({
imageUrl = "https://i.ibb.co/PTXn42F/fundamentals.webp"
lesson(
name = "Programming: Math in disguise",
tagline = "Mathematical functions and formulas can do much more than you think.",
tagline = "Mathematical functions and your calculator can do much more than you think." +
" Goal: learn to create and compose pure math functions.",
imageUrl = LessonImage
)
})
3 changes: 2 additions & 1 deletion shared/src/commonMain/kotlin/ivy/content/LottieUrls.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package ivy.content

object LottieUrls {
val HarrySunglases = lottieJsonUrl("harry-hi-v1")
val HarrySunglasses = lottieJsonUrl("harry-hi-v1")
val SpaceshipFly = lottieJsonUrl("spaceship-fly")
val SpaceshipFixed = lottieJsonUrl("spaceship-fixed-v2")

fun lottieJsonUrl(animationName: String): String =
"https://raw.githubusercontent.com/ILIYANGERMANOV/ivy-resources/master/ivy-learn/lottie/$animationName.json"
Expand Down
Loading

0 comments on commit 1613993

Please sign in to comment.