Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## Download the APK
Access the latest APK for Kotlin Dictionary from the link below.

[![Get APK](https://img.shields.io/badge/Get%20APK-maroon?style=for-the-badge&logo=android&logoColor=white)](https://github.com/DevelopersBreach/kotlin-dictionary-multiplatform/releases/download/v0.1.0/app-release-v0.1.0.apk)
[![Get APK](https://img.shields.io/badge/Get%20APK-%23B125EA?style=for-the-badge&logo=android&logoColor=white)](https://github.com/DevelopersBreach/kotlin-dictionary-multiplatform/releases/download/v0.1.0/app-release-v0.1.0.apk)

---

Expand All @@ -29,12 +29,12 @@ Access the latest APK for Kotlin Dictionary from the link below.

### Roadmap v0.2.0

- [ ] Assign unique IDs to objects and enforce consistent ordering logic
- [x] Assign unique IDs to objects and enforce consistent ordering logic
- [ ] Correct usage of visibility modifiers across the codebase
- [ ] Introduce common `@Preview` annotations for reusable Composable previews
- [x] Add code block for syntax display on the `Detail Screen`
- [ ] Implement caching on the `Detail Screen` to store previously viewed topic data
- [ ] Implement dynamic topic loading in `TopicRepository` to support scalability
- [x] Implement dynamic topic loading in `TopicRepository` to support scalability
- [ ] Integrate Room database to persist bookmark states
- [ ] Add a `Home Page` for navigation
- [ ] Add a `Quiz Page` to host topic-based quizzes
Expand Down
1 change: 1 addition & 0 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ kotlin {
implementation(libs.koin.androidx.compose)
implementation(libs.generativeai)
implementation(compose.uiTooling)
implementation(libs.ktor.client.okhttp)
}
commonMain.dependencies {
implementation(compose.runtime)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,26 @@ internal fun fakeTopicDetails(): KotlinTopicDetails {

private fun sampleTopicList(): List<Topic> {
return listOf(
Topic("Smart Casts"),
Topic("Null Safety"),
Topic("Coroutines"),
Topic("Lambdas"),
Topic("Sealed Classes"),
Topic(
name = "Smart Casts",
description = "Automatic casting by the compiler after type checks.",
),
Topic(
name = "Null Safety",
description = "Kotlin's system to eliminate null pointer exceptions at compile time.",
),
Topic(
name = "Coroutines",
description = "Lightweight threads for asynchronous and non-blocking programming.",
),
Topic(
name = "Lambdas",
description = "Anonymous functions used to pass behavior as data.",
),
Topic(
name = "Sealed Classes",
description = "Classes used to represent restricted class hierarchies for type safety.",
),
)
}

Expand All @@ -67,6 +82,7 @@ internal fun sampleTopicUiList(): List<ItemTopic> {
name = topic.name,
initial = topic.name.firstOrNull()?.uppercase() ?: "",
isBookmarked = true,
description = topic.description,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.developersbreach.kotlindictionarymultiplatform.data.topic.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class FirestoreDocument(
@SerialName("fields") val fields: Map<String, FirestoreField>,
)

@Serializable
data class FirestoreField(
@SerialName("stringValue") val stringValue: String,
)

@Serializable
data class FirestoreResponse(
@SerialName("documents") val documents: List<FirestoreDocument>,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.developersbreach.kotlindictionarymultiplatform.data.topic.model

import kotlinx.serialization.Serializable

@Serializable
data class Topic(
val name: String,
val description: String,
)
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
package com.developersbreach.kotlindictionarymultiplatform.data.topic.repository

import arrow.core.Either
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.FirestoreResponse
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic
import com.developersbreach.kotlindictionarymultiplatform.data.topic.utils.FirestoreConstants
import com.developersbreach.kotlindictionarymultiplatform.data.topic.utils.toTopic
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json

object TopicRepository {
fun getTopics(): Either<Throwable, List<Topic>> {

private val client = HttpClient {
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
}

suspend fun getTopics(): Either<Throwable, List<Topic>> {
return Either.catch {
listOf(
Topic("Variables"),
Topic("Strings"),
Topic("Functions"),
Topic("Coroutines"),
Topic("Classes"),
Topic("Interfaces"),
Topic("Objects"),
Topic("Collections"),
Topic("Null Safety"),
Topic("Lambdas"),
Topic("Higher-Order Functions"),
Topic("Delegation"),
Topic("Sealed Classes"),
Topic("Generics"),
Topic("Annotations"),
)
val response: FirestoreResponse = client.get(FirestoreConstants.TOPICS_URL).body()
response.documents.map { it.toTopic() }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.developersbreach.kotlindictionarymultiplatform.data.topic.utils

object FirestoreConstants {
const val TOPICS_URL =
"https://firestore.googleapis.com/v1/projects/kotlin-dictionary/databases/(default)/documents/topics"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.developersbreach.kotlindictionarymultiplatform.data.topic.utils

import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.FirestoreDocument
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic

fun FirestoreDocument.toTopic(): Topic {
return Topic(
name = fields["name"]?.stringValue.orEmpty(),
description = fields["description"]?.stringValue.orEmpty(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import org.jetbrains.compose.resources.stringResource
fun TopicCard(
itemTopic: ItemTopic,
topic: String,
subtitle: String,
description: String,
isBookmarked: Boolean,
onBookmarkClick: () -> Unit,
onCardClick: () -> Unit,
Expand Down Expand Up @@ -91,7 +91,7 @@ fun TopicCard(
Spacer(modifier = Modifier.height(6.dp))
KdText(
modifier = Modifier,
text = subtitle,
text = description,
style = MaterialTheme.typography.labelMedium.copy(
color = MaterialTheme.colorScheme.onBackground,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlindictionarymultiplatform.composeapp.generated.resources.Res
import kotlindictionarymultiplatform.composeapp.generated.resources.description_subtitle
import org.jetbrains.compose.resources.stringResource

@Composable
fun TopicList(
Expand All @@ -27,7 +24,7 @@ fun TopicList(
TopicCard(
topic = topic.name,
itemTopic = topic,
subtitle = stringResource(Res.string.description_subtitle),
description = topic.description,
isBookmarked = isBookmarked,
onBookmarkClick = { onBookmarkClick(index) },
onCardClick = { onTopicClick(topic.name) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ data class ItemTopic(
val name: String,
val initial: String,
val isBookmarked: Boolean,
val description: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class TopicViewModel(
}
}

private fun fetchTopicList() {
private suspend fun fetchTopicList() {
_uiState.value = UiState.Success(TopicUi(isLoading = true))
repository.getTopics().fold(
ifLeft = { UiState.Error(it) },
Expand Down Expand Up @@ -67,6 +67,7 @@ class TopicViewModel(
name = topic.name,
initial = topic.name.first().uppercase(),
isBookmarked = bookmarks.getOrNull(index) ?: false,
description = topic.description,
)
}

Expand Down
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jetbrainsKotlinJvm = "2.1.10"
kotlinStdlib = "2.1.10"
runner = "1.6.2"
core = "1.6.1"
uiToolingPreviewAndroid = "1.8.2"

[libraries]
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
Expand Down Expand Up @@ -56,6 +57,7 @@ ktor-client-android = { module = "io.ktor:ktor-client-android" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation" }
ktor-client-logging = { module = "io.ktor:ktor-client-logging" }
ktor-client-mock = { module = "io.ktor:ktor-client-mock" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor-bom" }
ktor-client-serialization = { module = "io.ktor:ktor-client-serialization" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json" }
koin-android = { module = "io.insert-koin:koin-android" }
Expand All @@ -67,6 +69,7 @@ koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlinStdlib" }
androidx-runner = { group = "androidx.test", name = "runner", version.ref = "runner" }
androidx-core = { group = "androidx.test", name = "core", version.ref = "core" }
androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
Expand Down
Loading