Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ ktlint_standard_no-empty-first-line-in-class-body = disabled
ktlint_standard_annotation = disabled
ktlint_standard_multiline-expression-wrapping = disabled
ktlint_standard_string-template-indent = disabled
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=1
ktlint_standard_chain-method-continuation = disabled
ktlint_standard_function-expression-body = disabled
ktlint_standard_statement-wrapping = enabled
ktlint_standard_class-signature = disabled

[composeApp/build/generated/**]
ktlint = disabled
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ plugins {
alias(libs.plugins.composeCompiler) apply false
alias(libs.plugins.kotlinMultiplatform) apply false
alias(libs.plugins.serialization) apply false
alias(libs.plugins.jetbrainsKotlinJvm) apply false
}
23 changes: 20 additions & 3 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ plugins {
}

ktlint {
version.set("1.3.0")
android = true
ignoreFailures = false
reporters {
Expand Down Expand Up @@ -145,14 +146,19 @@ android {

dependencies {
debugImplementation(compose.uiTooling)
ktlint(project(":custom-ktlint-rules"))
}

compose.desktop {
application {
mainClass = "com.developersbreach.kotlindictionarymultiplatform.MainKt"

nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
targetFormats(
TargetFormat.Dmg,
TargetFormat.Msi,
TargetFormat.Deb,
)
packageName = "com.developersbreach.kotlindictionarymultiplatform"
packageVersion = "1.0.0"
}
Expand All @@ -162,13 +168,24 @@ compose.desktop {
fun ApplicationDefaultConfig.setupBuildConfigFields(
properties: Properties,
) {
fun secret(key: String): String = System.getenv(key) ?: properties.getProperty(key, "")
fun secret(
key: String,
): String {
return System.getenv(key) ?: properties.getProperty(
key,
"",
)
}

if (secret("OPEN_API_KEY").isEmpty()) {
error("OPEN_API_KEY not set in local.properties")
}

buildConfigField(type = "String", name = "OPEN_API_KEY", value = "\"${secret("OPEN_API_KEY")}\"")
buildConfigField(
type = "String",
name = "OPEN_API_KEY",
value = "\"${secret("OPEN_API_KEY")}\"",
)
}

fun getLocalProperties(): Properties {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
override fun onCreate(
savedInstanceState: Bundle?,
) {
super.onCreate(savedInstanceState)

startKoin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class AndroidPlatform : Platform {
override val name: String = "Android ${Build.VERSION.SDK_INT}"
}

actual fun getPlatform(): Platform = AndroidPlatform()
actual fun getPlatform(): Platform {
return AndroidPlatform()
}

actual fun getOpenApiKey() = BuildConfig.OPEN_API_KEY
actual fun getOpenApiKey(): String {
return BuildConfig.OPEN_API_KEY
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,74 @@ import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Synt
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.TopicUi

fun sampleCodeSnippet(): String = """
fun greet(name: String): String {
return "Hello, Sam!"
}
""".trimIndent()
fun sampleCodeSnippet(): String {
return """
fun greet(name: String): String {
return "Hello, Sam!"
}
""".trimIndent()
}

fun topic() = "Smart Casts"
fun topic(): String {
return "Smart Casts"
}

fun subtitle() = "Automatic casting of immutable values"
fun subtitle(): String {
return "Automatic casting of immutable values"
}

fun fakeTopicDetails() = KotlinTopicDetails(
topicId = "smart-cast",
topicName = "Smart Cast",
intro = "Smart casting allows the compiler to automatically cast types.",
syntax = Syntax(
signature = "if (x is String) println(x.length)",
notes = "Works only with immutable vars",
),
sections = listOf(
Section(
heading = "Why Use It?",
content = "Because it’s safer and reduces boilerplate.",
codeExamples = listOf(
CodeExample(
description = "Basic usage of smart cast",
code = """
fun printLength(obj: Any) {
if (obj is String) {
println(obj.length) // Smart cast
}
}
""".trimIndent(),
fun fakeTopicDetails(): KotlinTopicDetails {
return KotlinTopicDetails(
topicId = "smart-cast",
topicName = "Smart Cast",
intro = "Smart casting allows the compiler to automatically cast types.",
syntax =
Syntax(
signature = "if (x is String) println(x.length)",
notes = "Works only with immutable vars",
),
sections =
listOf(
Section(
heading = "Why Use It?",
content = "Because it’s safer and reduces boilerplate.",
codeExamples =
listOf(
CodeExample(
description = "Basic usage of smart cast",
code =
"""
fun printLength(obj: Any) {
if (obj is String) {
println(obj.length) // Smart cast
}
}
""".trimIndent(),
),
),
),
),
),
),
pitfalls = listOf("Doesn't work with mutable vars."),
relatedTopics = listOf("Type Checking", "Safe Casts"),
)
pitfalls = listOf("Doesn't work with mutable vars."),
relatedTopics = listOf("Type Checking", "Safe Casts"),
)
}

fun sampleTopicList(): List<Topic> = listOf(
Topic("Smart Casts"),
Topic("Null Safety"),
Topic("Coroutines"),
Topic("Lambdas"),
Topic("Sealed Classes"),
)
fun sampleTopicList(): List<Topic> {
return listOf(
Topic("Smart Casts"),
Topic("Null Safety"),
Topic("Coroutines"),
Topic("Lambdas"),
Topic("Sealed Classes"),
)
}

fun sampleTopicUiList(): List<TopicUi> =
sampleTopicList().map { topic ->
fun sampleTopicUiList(): List<TopicUi> {
return sampleTopicList().map { topic ->
TopicUi(
name = topic.name,
initial = topic.name.firstOrNull()?.uppercase() ?: "",
isBookmarked = true,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ class FakeTopicViewModel : TopicViewModelFakeBase() {
)
override val bookmarkedStates = MutableStateFlow(List(sampleTopicList().size) { true })

override fun updateSearchQuery(newQuery: String) {}
override fun updateSearchQuery(
newQuery: String,
) {}

override fun toggleBookmark(index: Int) {}
override fun toggleBookmark(
index: Int,
) {}
}

// Base class to avoid needing Android ViewModel
Expand All @@ -41,9 +45,13 @@ abstract class TopicViewModelFakeBase {
abstract val filteredTopics: StateFlow<List<TopicUi>>
abstract val bookmarkedStates: StateFlow<List<Boolean>>

abstract fun updateSearchQuery(newQuery: String)
abstract fun updateSearchQuery(
newQuery: String,
)

abstract fun toggleBookmark(index: Int)
abstract fun toggleBookmark(
index: Int,
)
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,41 @@ object Log {
tag: String,
message: String,
) {
Logger.d(message, tag = tag)
Logger.d(
messageString = message,
tag = tag,
)
}

fun i(
tag: String,
message: String,
) {
Logger.i(message, tag = tag)
Logger.i(
messageString = message,
tag = tag,
)
}

fun w(
tag: String,
message: String,
) {
Logger.w(message, tag = tag)
Logger.w(
messageString = message,
tag = tag,
)
}

fun e(
tag: String,
message: String,
throwable: Throwable? = null,
) {
Logger.e(message, throwable, tag = tag)
Logger.e(
messageString = message,
throwable = throwable,
tag = tag,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,14 @@ object KtorHttpClient {
): KotlinTopicDetails {
// Prepare messages
val messages = listOf(
ChatMessage("system", "You are a Kotlin documentation generator."),
ChatMessage("user", "Generate full Kotlin documentation for topic \"$topicId\"."),
ChatMessage(
"system",
"You are a Kotlin documentation generator.",
),
ChatMessage(
"user",
"Generate full Kotlin documentation for topic \"$topicId\".",
),
)

// Build request body
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import com.developersbreach.kotlindictionarymultiplatform.getOpenApiKey

class DetailRepository {

suspend fun fetchTopic(topicId: String): Either<Throwable, KotlinTopicDetails> =
Either.catch {
KtorHttpClient.generateTopicDetails(topicId, getOpenApiKey())
suspend fun fetchTopic(
topicId: String,
): Either<Throwable, KotlinTopicDetails> {
return Either.catch {
KtorHttpClient.generateTopicDetails(
topicId = topicId,
apiKey = getOpenApiKey(),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ import arrow.core.Either
import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic

object TopicRepository {
fun getTopics(): Either<Throwable, List<Topic>> = 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"),
)
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"),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ val appModule = module {
single { TopicRepository }

viewModel { (handle: SavedStateHandle) ->
DetailViewModel(handle, get())
DetailViewModel(
savedStateHandle = handle,
repository = get(),
)
}

viewModel {
Expand Down
Loading
Loading