diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt index f17da62..48ea4f9 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt @@ -5,6 +5,7 @@ import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Kotl import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Section import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Syntax import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi fun sampleCodeSnippet(): String = """ fun greet(name: String): String { @@ -52,4 +53,13 @@ fun sampleTopicList(): List = listOf( Topic("Coroutines"), Topic("Lambdas"), Topic("Sealed Classes"), -) \ No newline at end of file +) + +fun sampleTopicUiList(): List = + sampleTopicList().map { topic -> + TopicUi( + name = topic.name, + initial = topic.name.firstOrNull()?.uppercase() ?: "", + isBookmarked = true, + ) + } \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicCardPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicCardPreview.kt index 1a8eb23..7d20bf3 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicCardPreview.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicCardPreview.kt @@ -2,6 +2,7 @@ package com.developersbreach.kotlindictionarymultiplatform.previews.topic import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.PreviewLightDark +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi import com.developersbreach.kotlindictionarymultiplatform.previews.subtitle import com.developersbreach.kotlindictionarymultiplatform.previews.topic import com.developersbreach.kotlindictionarymultiplatform.ui.screens.topic.TopicCard @@ -17,6 +18,11 @@ fun TopicCardPreview() { isBookmarked = false, onBookmarkClick = {}, onCardClick = {}, + topicUi = TopicUi( + name = "Emerson Vega", + initial = "senectus", + isBookmarked = false, + ), ) } } \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicListPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicListPreview.kt index b507f4c..6085226 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicListPreview.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicListPreview.kt @@ -3,6 +3,7 @@ package com.developersbreach.kotlindictionarymultiplatform.previews.topic import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.PreviewLightDark import com.developersbreach.kotlindictionarymultiplatform.previews.sampleTopicList +import com.developersbreach.kotlindictionarymultiplatform.previews.sampleTopicUiList import com.developersbreach.kotlindictionarymultiplatform.ui.screens.topic.TopicList import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme @@ -11,7 +12,7 @@ import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDiction fun TopicListPreview() { KotlinDictionaryTheme { TopicList( - topics = sampleTopicList(), + topics = sampleTopicUiList(), bookmarkedStates = List(sampleTopicList().size) { true }, onBookmarkClick = {}, onTopicClick = {}, diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicScreenPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicScreenPreview.kt index 962a374..764d3a2 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicScreenPreview.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/topic/TopicScreenPreview.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.tooling.preview.PreviewLightDark import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi import com.developersbreach.kotlindictionarymultiplatform.previews.sampleTopicList import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiState import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiStateHandler @@ -17,7 +18,15 @@ import kotlinx.coroutines.flow.StateFlow class FakeTopicViewModel : TopicViewModelFakeBase() { override val topics = MutableStateFlow>>(UiState.Success(sampleTopicList())) override val searchQuery = MutableStateFlow("") - override val filteredTopics = MutableStateFlow(sampleTopicList()) + override val filteredTopics = MutableStateFlow( + sampleTopicList().map { topic -> + TopicUi( + name = topic.name, + initial = topic.name.firstOrNull()?.uppercase() ?: "", + isBookmarked = true, + ) + }, + ) override val bookmarkedStates = MutableStateFlow(List(sampleTopicList().size) { true }) override fun updateSearchQuery(newQuery: String) {} @@ -29,7 +38,7 @@ class FakeTopicViewModel : TopicViewModelFakeBase() { abstract class TopicViewModelFakeBase { abstract val topics: StateFlow>> abstract val searchQuery: StateFlow - abstract val filteredTopics: StateFlow> + abstract val filteredTopics: StateFlow> abstract val bookmarkedStates: StateFlow> abstract fun updateSearchQuery(newQuery: String) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/model/TopicUi.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/model/TopicUi.kt new file mode 100644 index 0000000..2692aa6 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/model/TopicUi.kt @@ -0,0 +1,7 @@ +package com.developersbreach.kotlindictionarymultiplatform.data.topic.model + +data class TopicUi( + val name: String, + val initial: String, + val isBookmarked: Boolean, +) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicCard.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicCard.kt index f5d4e75..d49d6fa 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicCard.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicCard.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bookmark -import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.BookmarkBorder import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -28,14 +27,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi import kotlindictionarymultiplatform.composeapp.generated.resources.Res import kotlindictionarymultiplatform.composeapp.generated.resources.add_bookmark -import kotlindictionarymultiplatform.composeapp.generated.resources.icon import kotlindictionarymultiplatform.composeapp.generated.resources.remove_bookmark import org.jetbrains.compose.resources.stringResource @Composable fun TopicCard( + topicUi: TopicUi, topic: String, subtitle: String, isBookmarked: Boolean, @@ -63,7 +63,7 @@ fun TopicCard( .background(MaterialTheme.colorScheme.primary, CircleShape), contentAlignment = Alignment.Center, ) { - Icon(Icons.Filled.Search, contentDescription = stringResource(Res.string.icon)) + Text(text = topicUi.initial) } Spacer(modifier = Modifier.width(12.dp)) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicList.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicList.kt index 0ca6835..64de599 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicList.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicList.kt @@ -7,14 +7,14 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi import kotlindictionarymultiplatform.composeapp.generated.resources.Res import kotlindictionarymultiplatform.composeapp.generated.resources.description_subtitle import org.jetbrains.compose.resources.stringResource @Composable fun TopicList( - topics: List, + topics: List, bookmarkedStates: List, onBookmarkClick: (Int) -> Unit, onTopicClick: (String) -> Unit, @@ -27,6 +27,7 @@ fun TopicList( val isBookmarked = bookmarkedStates.getOrNull(index) ?: true TopicCard( topic = topic.name, + topicUi = topic, subtitle = stringResource(Res.string.description_subtitle), isBookmarked = isBookmarked, onBookmarkClick = { onBookmarkClick(index) }, diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicScreenUI.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicScreenUI.kt index 5b2cbf7..28212b9 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicScreenUI.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicScreenUI.kt @@ -9,11 +9,11 @@ import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi @Composable fun TopicScreenUI( - topics: List, + topics: List, bookmarkedStates: List, searchQuery: String, onQueryChange: (String) -> Unit, diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicViewModel.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicViewModel.kt index 89d31df..462d06d 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.developersbreach.kotlindictionarymultiplatform.Log import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic +import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi import com.developersbreach.kotlindictionarymultiplatform.data.topic.repository.TopicRepository import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiState import kotlinx.coroutines.flow.MutableStateFlow @@ -28,15 +29,18 @@ class TopicViewModel( private val _bookmarkedStates = MutableStateFlow>(emptyList()) val bookmarkedStates: StateFlow> = _bookmarkedStates - val filteredTopics: StateFlow> = combine(_topics, _searchQuery) { uiState, query -> + val filteredTopics: StateFlow> = combine(_topics, _searchQuery, _bookmarkedStates) { uiState, query, bookmarks -> val allTopics = (uiState as? UiState.Success)?.data ?: return@combine emptyList() - if (query.isBlank()) { - allTopics - } else { - allTopics.filter { - it.name.contains(query, ignoreCase = true) + + allTopics + .withIndex() + .map { (index, topic) -> + TopicUi( + name = topic.name, + initial = topic.name.first().uppercase(), + isBookmarked = bookmarks.getOrNull(index) ?: false, + ) } - } }.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList()) init { @@ -53,9 +57,10 @@ class TopicViewModel( val result = repository.getTopics() _topics.value = result.fold( ifLeft = { UiState.Error(it) }, - ifRight = { - _bookmarkedStates.value = List(it.size) { true } - UiState.Success(it) + ifRight = { list -> + val sortedList = list.sortedBy { it.name.lowercase() } + _bookmarkedStates.value = List(sortedList.size) { true } + UiState.Success(sortedList) }, ) }