Skip to content

Commit 825df3e

Browse files
authored
Merge pull request #6 from DevelopersBreach/yuga/detail-topic-ui
Updated `TopicScreen` and `Detail Screen` with changed UI
2 parents 3a041c0 + 509deea commit 825df3e

File tree

23 files changed

+861
-84
lines changed

23 files changed

+861
-84
lines changed

composeApp/build.gradle.kts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,17 @@ kotlin {
6969
val desktopMain by getting
7070

7171
androidMain.dependencies {
72-
implementation(compose.preview)
7372
implementation(libs.androidx.activity.compose)
7473
implementation(libs.koin.android)
7574
implementation(libs.koin.androidx.compose)
76-
implementation(compose.components.uiToolingPreview)
7775
}
7876
commonMain.dependencies {
7977
implementation(compose.runtime)
8078
implementation(compose.foundation)
81-
implementation(compose.material)
79+
implementation(compose.material3)
8280
implementation(compose.ui)
8381
implementation(compose.components.resources)
82+
implementation(compose.materialIconsExtended)
8483
implementation(libs.androidx.lifecycle.viewmodel)
8584
implementation(libs.androidx.lifecycle.runtime.compose)
8685
implementation(libs.androidx.navigation.compose)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.developersbreach.kotlindictionarymultiplatform.previews
2+
3+
import androidx.compose.foundation.layout.padding
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.ui.Modifier
6+
import androidx.compose.ui.tooling.preview.PreviewLightDark
7+
import androidx.compose.ui.unit.dp
8+
import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.CodeExampleBox
9+
import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme
10+
11+
@PreviewLightDark
12+
@Composable
13+
fun CodeExampleBoxPreview() {
14+
KotlinDictionaryTheme {
15+
CodeExampleBox(
16+
code = sampleCodeSnippet(),
17+
modifier = Modifier.padding(16.dp),
18+
)
19+
}
20+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.developersbreach.kotlindictionarymultiplatform.previews
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.ui.tooling.preview.PreviewLightDark
5+
import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.DetailScreenContent
6+
import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme
7+
8+
@PreviewLightDark
9+
@Composable
10+
fun DetailScreenPreview() {
11+
KotlinDictionaryTheme {
12+
DetailScreenContent(topic = fakeTopicDetails())
13+
}
14+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.developersbreach.kotlindictionarymultiplatform.previews
2+
3+
import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.CodeExample
4+
import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails
5+
import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Section
6+
import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Syntax
7+
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic
8+
9+
fun sampleCodeSnippet(): String = """
10+
fun greet(name: String): String {
11+
return "Hello, Sam!"
12+
}
13+
""".trimIndent()
14+
15+
fun topic() = "Smart Casts"
16+
17+
fun subtitle() = "Automatic casting of immutable values"
18+
19+
fun fakeTopicDetails() = KotlinTopicDetails(
20+
topicId = "smart-cast",
21+
topicName = "Smart Cast",
22+
intro = "Smart casting allows the compiler to automatically cast types.",
23+
syntax = Syntax(
24+
signature = "if (x is String) println(x.length)",
25+
notes = "Works only with immutable vars",
26+
),
27+
sections = listOf(
28+
Section(
29+
heading = "Why Use It?",
30+
content = "Because it’s safer and reduces boilerplate.",
31+
codeExamples = listOf(
32+
CodeExample(
33+
description = "Basic usage of smart cast",
34+
code = """
35+
fun printLength(obj: Any) {
36+
if (obj is String) {
37+
println(obj.length) // Smart cast
38+
}
39+
}
40+
""".trimIndent(),
41+
),
42+
),
43+
),
44+
),
45+
pitfalls = listOf("Doesn't work with mutable vars."),
46+
relatedTopics = listOf("Type Checking", "Safe Casts"),
47+
)
48+
49+
fun sampleTopicList(): List<Topic> = listOf(
50+
Topic("Smart Casts"),
51+
Topic("Null Safety"),
52+
Topic("Coroutines"),
53+
Topic("Lambdas"),
54+
Topic("Sealed Classes"),
55+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.developersbreach.kotlindictionarymultiplatform.previews
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.getValue
5+
import androidx.compose.runtime.mutableStateOf
6+
import androidx.compose.runtime.remember
7+
import androidx.compose.runtime.setValue
8+
import androidx.compose.ui.tooling.preview.PreviewLightDark
9+
import com.developersbreach.kotlindictionarymultiplatform.ui.screens.topic.SearchField
10+
import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme
11+
12+
@PreviewLightDark
13+
@Composable
14+
fun SearchFieldPreview() {
15+
KotlinDictionaryTheme {
16+
var searchQuery by remember { mutableStateOf("") }
17+
SearchField(
18+
searchQuery = searchQuery,
19+
onQueryChange = { searchQuery = it },
20+
)
21+
}
22+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.developersbreach.kotlindictionarymultiplatform.previews
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.ui.tooling.preview.PreviewLightDark
5+
import com.developersbreach.kotlindictionarymultiplatform.ui.screens.topic.TopicCard
6+
import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme
7+
8+
@PreviewLightDark
9+
@Composable
10+
fun TopicCardPreview() {
11+
KotlinDictionaryTheme {
12+
TopicCard(
13+
topic = topic(),
14+
subtitle = subtitle(),
15+
isBookmarked = false,
16+
onBookmarkClick = {},
17+
onCardClick = {},
18+
)
19+
}
20+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.developersbreach.kotlindictionarymultiplatform.previews
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.collectAsState
5+
import androidx.compose.runtime.getValue
6+
import androidx.compose.ui.tooling.preview.PreviewLightDark
7+
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic
8+
import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiState
9+
import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiStateHandler
10+
import com.developersbreach.kotlindictionarymultiplatform.ui.screens.topic.TopicScreenLayout
11+
import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme
12+
import kotlinx.coroutines.flow.MutableStateFlow
13+
import kotlinx.coroutines.flow.StateFlow
14+
15+
// Fake ViewModel for previews
16+
class FakeTopicViewModel : TopicViewModelFakeBase() {
17+
override val topics = MutableStateFlow<UiState<List<Topic>>>(UiState.Success(sampleTopicList()))
18+
override val searchQuery = MutableStateFlow("")
19+
override val filteredTopics = MutableStateFlow(sampleTopicList())
20+
override val bookmarkedStates = MutableStateFlow(List(sampleTopicList().size) { true })
21+
22+
override fun updateSearchQuery(newQuery: String) {}
23+
24+
override fun toggleBookmark(index: Int) {}
25+
}
26+
27+
// Base class to avoid needing Android ViewModel
28+
abstract class TopicViewModelFakeBase {
29+
abstract val topics: StateFlow<UiState<List<Topic>>>
30+
abstract val searchQuery: StateFlow<String>
31+
abstract val filteredTopics: StateFlow<List<Topic>>
32+
abstract val bookmarkedStates: StateFlow<List<Boolean>>
33+
34+
abstract fun updateSearchQuery(newQuery: String)
35+
36+
abstract fun toggleBookmark(index: Int)
37+
}
38+
39+
@Composable
40+
fun TopicScreenContent(
41+
viewModel: TopicViewModelFakeBase,
42+
onTopicClick: (String) -> Unit = {},
43+
) {
44+
val topicState by viewModel.topics.collectAsState()
45+
val filteredTopics by viewModel.filteredTopics.collectAsState()
46+
val searchQuery by viewModel.searchQuery.collectAsState()
47+
val bookmarkedStates by viewModel.bookmarkedStates.collectAsState()
48+
49+
UiStateHandler(uiState = topicState) {
50+
TopicScreenLayout(
51+
topics = filteredTopics,
52+
bookmarkedStates = bookmarkedStates,
53+
searchQuery = searchQuery,
54+
onQueryChange = viewModel::updateSearchQuery,
55+
onBookmarkClick = viewModel::toggleBookmark,
56+
onTopicClick = onTopicClick,
57+
)
58+
}
59+
}
60+
61+
@PreviewLightDark
62+
@Composable
63+
fun TopicScreenPreview() {
64+
KotlinDictionaryTheme {
65+
TopicScreenContent(viewModel = FakeTopicViewModel())
66+
}
67+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)