diff --git a/.editorconfig b/.editorconfig index 20eeb4d..3befb8b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -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 \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 1b5110a..da790f8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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 } \ No newline at end of file diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index ecf2e0d..adc9d32 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -17,6 +17,7 @@ plugins { } ktlint { + version.set("1.3.0") android = true ignoreFailures = false reporters { @@ -145,6 +146,7 @@ android { dependencies { debugImplementation(compose.uiTooling) + ktlint(project(":custom-ktlint-rules")) } compose.desktop { @@ -152,7 +154,11 @@ compose.desktop { 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" } @@ -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 { diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/MainActivity.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/MainActivity.kt index 9d2e6eb..a5eac55 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/MainActivity.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/MainActivity.kt @@ -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 { diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.android.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.android.kt index 23a9971..b44e136 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.android.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.android.kt @@ -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 \ No newline at end of file +actual fun getOpenApiKey(): String { + return BuildConfig.OPEN_API_KEY +} \ No newline at end of file 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 48ea4f9..3dd353f 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt @@ -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 = listOf( - Topic("Smart Casts"), - Topic("Null Safety"), - Topic("Coroutines"), - Topic("Lambdas"), - Topic("Sealed Classes"), -) +fun sampleTopicList(): List { + return listOf( + Topic("Smart Casts"), + Topic("Null Safety"), + Topic("Coroutines"), + Topic("Lambdas"), + Topic("Sealed Classes"), + ) +} -fun sampleTopicUiList(): List = - sampleTopicList().map { topic -> +fun sampleTopicUiList(): List { + return sampleTopicList().map { topic -> TopicUi( name = topic.name, initial = topic.name.firstOrNull()?.uppercase() ?: "", isBookmarked = true, ) - } \ No newline at end of file + } +} \ No newline at end of file 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 764d3a2..14b8ba2 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 @@ -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 @@ -41,9 +45,13 @@ abstract class TopicViewModelFakeBase { abstract val filteredTopics: StateFlow> abstract val bookmarkedStates: StateFlow> - abstract fun updateSearchQuery(newQuery: String) + abstract fun updateSearchQuery( + newQuery: String, + ) - abstract fun toggleBookmark(index: Int) + abstract fun toggleBookmark( + index: Int, + ) } @Composable diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Log.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Log.kt index 031ea49..74500fb 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Log.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Log.kt @@ -7,21 +7,30 @@ 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( @@ -29,6 +38,10 @@ object Log { message: String, throwable: Throwable? = null, ) { - Logger.e(message, throwable, tag = tag) + Logger.e( + messageString = message, + throwable = throwable, + tag = tag, + ) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/core/network/KtorHttpClient.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/core/network/KtorHttpClient.kt index 32a4a10..d7f0132 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/core/network/KtorHttpClient.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/core/network/KtorHttpClient.kt @@ -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 diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/detail/repository/DetailRepository.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/detail/repository/DetailRepository.kt index f618f10..a36ce7e 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/detail/repository/DetailRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/detail/repository/DetailRepository.kt @@ -7,8 +7,14 @@ import com.developersbreach.kotlindictionarymultiplatform.getOpenApiKey class DetailRepository { - suspend fun fetchTopic(topicId: String): Either = - Either.catch { - KtorHttpClient.generateTopicDetails(topicId, getOpenApiKey()) + suspend fun fetchTopic( + topicId: String, + ): Either { + return Either.catch { + KtorHttpClient.generateTopicDetails( + topicId = topicId, + apiKey = getOpenApiKey(), + ) } + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/repository/TopicRepository.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/repository/TopicRepository.kt index 8d0e2d9..85462f4 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/repository/TopicRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/data/topic/repository/TopicRepository.kt @@ -4,23 +4,25 @@ import arrow.core.Either import com.developersbreach.kotlindictionarymultiplatform.data.topic.model.Topic object TopicRepository { - fun getTopics(): Either> = 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> { + 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"), + ) + } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/di/AppModule.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/di/AppModule.kt index 8426ff9..410916b 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/di/AppModule.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/di/AppModule.kt @@ -13,7 +13,10 @@ val appModule = module { single { TopicRepository } viewModel { (handle: SavedStateHandle) -> - DetailViewModel(handle, get()) + DetailViewModel( + savedStateHandle = handle, + repository = get(), + ) } viewModel { diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/ShowAlertDialog.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/ShowAlertDialog.kt index 2e75a12..678b3af 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/ShowAlertDialog.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/ShowAlertDialog.kt @@ -18,8 +18,8 @@ fun ShowAlertDialog( ) { AlertDialog( onDismissRequest = onButtonClick, - title = { Text(title) }, - text = { Text(description) }, + title = { Text(text = title) }, + text = { Text(text = description) }, confirmButton = { TextButton(onClick = onButtonClick) { Text(text = stringResource(Res.string.ok)) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/UiState.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/UiState.kt index 5e67f67..0fb57f4 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/UiState.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/components/UiState.kt @@ -3,7 +3,11 @@ package com.developersbreach.kotlindictionarymultiplatform.ui.components sealed class UiState { data object Loading : UiState() - data class Success(val data: T) : UiState() + data class Success( + val data: T, + ) : UiState() - data class Error(val throwable: Throwable) : UiState() + data class Error( + val throwable: Throwable, + ) : UiState() } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppDestinations.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppDestinations.kt index 752b2f8..d5674b3 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppDestinations.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppDestinations.kt @@ -9,5 +9,7 @@ sealed interface AppDestinations { data object TopicList : AppDestinations @Serializable - data class Detail(val topicId: String) : AppDestinations + data class Detail( + val topicId: String, + ) : AppDestinations } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/NavigationAction.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/NavigationAction.kt index 12d3b76..eca0c35 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/NavigationAction.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/NavigationAction.kt @@ -2,7 +2,9 @@ package com.developersbreach.kotlindictionarymultiplatform.ui.navigation import androidx.navigation.NavHostController -class NavigationAction(private val navController: NavHostController) { +class NavigationAction( + private val navController: NavHostController, +) { val navigateToDetail: (String) -> Unit = { topicId -> navController.navigate(AppDestinations.Detail(topicId)) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/CodeExampleBox.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/CodeExampleBox.kt index ad15147..1c6643c 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/CodeExampleBox.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/CodeExampleBox.kt @@ -53,14 +53,24 @@ fun CodeExampleBox( Box( modifier = modifier .fillMaxWidth() - .border(1.dp, MaterialTheme.colorScheme.onPrimaryContainer, RoundedCornerShape(8.dp)) - .background(MaterialTheme.colorScheme.primaryContainer, RoundedCornerShape(8.dp)), + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.onPrimaryContainer, + shape = RoundedCornerShape(8.dp), + ) + .background( + color = MaterialTheme.colorScheme.primaryContainer, + shape = RoundedCornerShape(8.dp), + ), ) { Column(modifier = Modifier.padding(0.dp)) { Box( modifier = Modifier .fillMaxWidth() - .background(MaterialTheme.colorScheme.onPrimaryContainer, RoundedCornerShape(8.dp)) + .background( + color = MaterialTheme.colorScheme.onPrimaryContainer, + shape = RoundedCornerShape(8.dp), + ) .padding(6.dp), ) { Row( @@ -108,7 +118,11 @@ fun CodeExampleBox( Text( text = code, - modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp), + modifier = Modifier.padding( + start = 12.dp, + end = 12.dp, + bottom = 12.dp, + ), fontFamily = FontFamily.Monospace, fontSize = 14.sp, lineHeight = 20.sp, diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt index 10acca5..10cd4e3 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt @@ -6,7 +6,9 @@ import androidx.compose.runtime.getValue import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiStateHandler @Composable -fun DetailScreen(viewModel: DetailViewModel) { +fun DetailScreen( + viewModel: DetailViewModel, +) { val topicState by viewModel.state.collectAsState() UiStateHandler(uiState = topicState) { topic -> diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt index 509559e..f9756d2 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt @@ -11,7 +11,9 @@ import androidx.compose.ui.unit.dp import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails @Composable -fun DetailScreenUI(topic: KotlinTopicDetails) { +fun DetailScreenUI( + topic: KotlinTopicDetails, +) { val scrollState = rememberScrollState() Scaffold( diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt index 16736f5..bc9098f 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt @@ -18,7 +18,9 @@ import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterial3Api::class) @Composable -fun DetailTopBar(title: String) { +fun DetailTopBar( + title: String, +) { TopAppBar( title = { Text( @@ -30,7 +32,10 @@ fun DetailTopBar(title: String) { }, navigationIcon = { IconButton(onClick = { /* TODO: Navigate back */ }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(Res.string.back)) + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(Res.string.back), + ) } }, colors = TopAppBarDefaults.topAppBarColors( diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt index 0868acd..7352794 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt @@ -13,8 +13,17 @@ import kotlindictionarymultiplatform.composeapp.generated.resources.introduction import org.jetbrains.compose.resources.stringResource @Composable -fun IntroductionSection(topic: KotlinTopicDetails) { - Text(stringResource(Res.string.introduction), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) +fun IntroductionSection( + topic: KotlinTopicDetails, +) { + Text( + text = stringResource(resource = Res.string.introduction), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(modifier = Modifier.height(4.dp)) - Text(text = topic.intro, style = MaterialTheme.typography.bodyMedium) + Text( + text = topic.intro, + style = MaterialTheme.typography.bodyMedium, + ) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt index df446aa..481cb10 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt @@ -14,12 +14,24 @@ import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls import org.jetbrains.compose.resources.stringResource @Composable -fun PitfallsSection(topic: KotlinTopicDetails) { +fun PitfallsSection( + topic: KotlinTopicDetails, +) { if (topic.pitfalls.isNotEmpty()) { - Text(stringResource(Res.string.pitfalls), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Text( + text = stringResource(resource = Res.string.pitfalls), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) topic.pitfalls.forEach { - Text(stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) + Text( + text = stringResource( + Res.string.bullet_item, + it, + ), + style = MaterialTheme.typography.bodyMedium, + ) } Spacer(Modifier.height(16.dp)) } diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt index 75137db..cbeda30 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt @@ -14,12 +14,24 @@ import kotlindictionarymultiplatform.composeapp.generated.resources.related_topi import org.jetbrains.compose.resources.stringResource @Composable -fun RelatedTopicsSection(topic: KotlinTopicDetails) { +fun RelatedTopicsSection( + topic: KotlinTopicDetails, +) { if (topic.relatedTopics.isNotEmpty()) { - Text(stringResource(Res.string.related_topics), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Text( + text = stringResource(resource = Res.string.related_topics), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) topic.relatedTopics.forEach { - Text(stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) + Text( + text = stringResource( + Res.string.bullet_item, + it, + ), + style = MaterialTheme.typography.bodyMedium, + ) } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt index e9522fd..29d690b 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt @@ -12,19 +12,32 @@ import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Kotl import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.CodeExampleBox @Composable -fun SectionsList(topic: KotlinTopicDetails) { +fun SectionsList( + topic: KotlinTopicDetails, +) { topic.sections.forEach { section -> section.heading?.let { - Text(it, style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Text( + text = it, + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) } section.content?.let { - Text(it, style = MaterialTheme.typography.bodyMedium) + Text( + text = it, + style = MaterialTheme.typography.bodyMedium, + ) Spacer(Modifier.height(8.dp)) } section.codeExamples.forEach { example -> example.description?.let { - Text(it, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium) + Text( + text = it, + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.bodyMedium, + ) } Spacer(Modifier.height(16.dp)) CodeExampleBox(code = example.code) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt index 2ad56a3..e74b255 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt @@ -14,15 +14,27 @@ import kotlindictionarymultiplatform.composeapp.generated.resources.syntax import org.jetbrains.compose.resources.stringResource @Composable -fun SyntaxSection(topic: KotlinTopicDetails) { +fun SyntaxSection( + topic: KotlinTopicDetails, +) { if (topic.syntax.signature.isNotBlank()) { - Text(stringResource(Res.string.syntax), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Text( + text = stringResource(resource = Res.string.syntax), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) - Text(text = topic.syntax.signature, style = MaterialTheme.typography.bodyMedium) + Text( + text = topic.syntax.signature, + style = MaterialTheme.typography.bodyMedium, + ) topic.syntax.notes?.let { Spacer(Modifier.height(4.dp)) Text( - text = stringResource(Res.string.notes_with_value, it), + text = stringResource( + Res.string.notes_with_value, + it, + ), style = MaterialTheme.typography.bodyMedium, ) } diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt index 4413978..29ad76f 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt @@ -20,7 +20,9 @@ import kotlindictionarymultiplatform.composeapp.generated.resources.table_of_con import org.jetbrains.compose.resources.stringResource @Composable -fun TableOfContents(topic: KotlinTopicDetails) { +fun TableOfContents( + topic: KotlinTopicDetails, +) { val items = buildList { add(stringResource(Res.string.introduction_bullet)) if (topic.syntax.signature.isNotBlank()) add(stringResource(Res.string.syntax_bullet)) @@ -29,7 +31,11 @@ fun TableOfContents(topic: KotlinTopicDetails) { if (topic.relatedTopics.isNotEmpty()) add(stringResource(Res.string.related_topics_bullet)) } - Text(text = stringResource(Res.string.table_of_contents), style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onPrimary) + Text( + text = stringResource(Res.string.table_of_contents), + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) items.forEach { Text( diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/SearchField.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/SearchField.kt index c9906f5..c53f9e2 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/SearchField.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/SearchField.kt @@ -46,7 +46,11 @@ fun SearchField( ) }, leadingIcon = { - Icon(Icons.Filled.Search, contentDescription = stringResource(Res.string.search), tint = MaterialTheme.colorScheme.onBackground) + Icon( + imageVector = Icons.Filled.Search, + contentDescription = stringResource(Res.string.search), + tint = MaterialTheme.colorScheme.onBackground, + ) }, colors = TextFieldDefaults.colors( focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, 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 d49d6fa..b24ff5e 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 @@ -46,7 +46,11 @@ fun TopicCard( modifier = Modifier .fillMaxWidth() .padding(8.dp) - .shadow(6.dp, RoundedCornerShape(16.dp), clip = true) + .shadow( + elevation = 6.dp, + shape = RoundedCornerShape(16.dp), + clip = true, + ) .clickable { onCardClick() }, shape = RoundedCornerShape(16.dp), color = MaterialTheme.colorScheme.surface, @@ -60,7 +64,10 @@ fun TopicCard( Box( modifier = Modifier .size(36.dp) - .background(MaterialTheme.colorScheme.primary, CircleShape), + .background( + color = MaterialTheme.colorScheme.primary, + shape = CircleShape, + ), contentAlignment = Alignment.Center, ) { Text(text = topicUi.initial) 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 28212b9..bdf5007 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 @@ -29,7 +29,10 @@ fun TopicScreenUI( .padding(horizontal = 16.dp) .padding(top = paddingValues.calculateTopPadding()), ) { - SearchField(searchQuery = searchQuery, onQueryChange = onQueryChange) + SearchField( + searchQuery = searchQuery, + onQueryChange = onQueryChange, + ) Spacer(modifier = Modifier.height(8.dp)) TopicList( topics = topics, diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicTopAppBar.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicTopAppBar.kt index c7c0e6e..b2c044a 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicTopAppBar.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/topic/TopicTopAppBar.kt @@ -32,7 +32,10 @@ fun TopicTopBar() { }, navigationIcon = { IconButton(onClick = { /* Optional Back Logic */ }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(Res.string.back)) + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(Res.string.back), + ) } }, colors = TopAppBarDefaults.topAppBarColors( 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 462d06d..6db2092 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 @@ -65,11 +65,15 @@ class TopicViewModel( ) } - fun updateSearchQuery(newQuery: String) { + fun updateSearchQuery( + newQuery: String, + ) { _searchQuery.value = newQuery } - fun toggleBookmark(index: Int) { + fun toggleBookmark( + index: Int, + ) { _bookmarkedStates.update { current -> if (index in current.indices) { current.toMutableList().apply { this[index] = !this[index] } diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/theme/Font.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/theme/Font.kt index 7364e4e..e7a599d 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/theme/Font.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/theme/Font.kt @@ -15,24 +15,91 @@ import org.jetbrains.compose.resources.Font @Composable fun AppTypography(): Typography { val fontFamily = FontFamily( - Font(Res.font.noto_sans_regular, weight = FontWeight.Normal), - Font(Res.font.noto_sans_medium, weight = FontWeight.Medium), - Font(Res.font.noto_sans_bold, weight = FontWeight.Bold), + Font( + resource = Res.font.noto_sans_regular, + weight = FontWeight.Normal, + ), + Font( + resource = Res.font.noto_sans_medium, + weight = FontWeight.Medium, + ), + Font( + resource = Res.font.noto_sans_bold, + weight = FontWeight.Bold, + ), ) return Typography( - displayLarge = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Bold, fontSize = 30.sp), - displayMedium = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Bold, fontSize = 22.sp), - displaySmall = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Medium, fontSize = 24.sp), - headlineLarge = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Bold, fontSize = 18.sp, lineHeight = (18 * 1.3).sp, letterSpacing = (18 * 0.012).sp), - headlineMedium = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Medium, fontSize = 18.sp, lineHeight = (18 * 1.3).sp, letterSpacing = (18 * 0.012).sp), - bodyLarge = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 16.sp), - bodyMedium = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 14.sp), - titleLarge = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Bold, fontSize = 18.sp), - titleMedium = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Medium, fontSize = 16.sp), - titleSmall = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Medium, fontSize = 14.sp), - labelLarge = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Bold, fontSize = 14.sp), - labelMedium = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = (18 * 1.3).sp, letterSpacing = (18 * 0.012).sp), - labelSmall = TextStyle(fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 10.sp), + displayLarge = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Bold, + fontSize = 30.sp, + ), + displayMedium = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Bold, + fontSize = 22.sp, + ), + displaySmall = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Medium, + fontSize = 24.sp, + ), + headlineLarge = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Bold, + fontSize = 18.sp, + lineHeight = (18 * 1.3).sp, + letterSpacing = (18 * 0.012).sp, + ), + headlineMedium = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Medium, + fontSize = 18.sp, + lineHeight = (18 * 1.3).sp, + letterSpacing = (18 * 0.012).sp, + ), + bodyLarge = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + ), + bodyMedium = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + ), + titleLarge = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Bold, + fontSize = 18.sp, + ), + titleMedium = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Medium, + fontSize = 16.sp, + ), + titleSmall = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + ), + labelLarge = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + ), + labelMedium = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = (18 * 1.3).sp, + letterSpacing = (18 * 0.012).sp, + ), + labelSmall = TextStyle( + fontFamily = fontFamily, + fontWeight = FontWeight.Normal, + fontSize = 10.sp, + ), ) } \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.desktop.kt b/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.desktop.kt index 99f944f..4e835a8 100644 --- a/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.desktop.kt +++ b/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.desktop.kt @@ -1,3 +1,5 @@ package com.developersbreach.kotlindictionarymultiplatform -actual fun getOpenApiKey(): String = "" \ No newline at end of file +actual fun getOpenApiKey(): String { + return "" +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.jvm.kt b/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.jvm.kt index fa86a77..f5de343 100644 --- a/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.jvm.kt +++ b/composeApp/src/desktopMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.jvm.kt @@ -4,4 +4,6 @@ class JVMPlatform : Platform { override val name: String = "Java ${System.getProperty("java.version")}" } -actual fun getPlatform(): Platform = JVMPlatform() \ No newline at end of file +actual fun getPlatform(): Platform { + return JVMPlatform() +} \ No newline at end of file diff --git a/composeApp/src/iosMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.ios.kt b/composeApp/src/iosMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.ios.kt index 3d47b6d..3f11dac 100644 --- a/composeApp/src/iosMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.ios.kt +++ b/composeApp/src/iosMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.ios.kt @@ -6,4 +6,6 @@ class IOSPlatform : Platform { override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } -actual fun getPlatform(): Platform = IOSPlatform() \ No newline at end of file +actual fun getPlatform(): Platform { + return IOSPlatform() +} \ No newline at end of file diff --git a/composeApp/src/nativeMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.native.kt b/composeApp/src/nativeMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.native.kt index 99f944f..4e835a8 100644 --- a/composeApp/src/nativeMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.native.kt +++ b/composeApp/src/nativeMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.native.kt @@ -1,3 +1,5 @@ package com.developersbreach.kotlindictionarymultiplatform -actual fun getOpenApiKey(): String = "" \ No newline at end of file +actual fun getOpenApiKey(): String { + return "" +} \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.wasmJs.kt b/composeApp/src/wasmJsMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.wasmJs.kt index 290ebf6..64b541f 100644 --- a/composeApp/src/wasmJsMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.wasmJs.kt +++ b/composeApp/src/wasmJsMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/Platform.wasmJs.kt @@ -4,6 +4,10 @@ class WasmPlatform : Platform { override val name: String = "Web with Kotlin/Wasm" } -actual fun getPlatform(): Platform = WasmPlatform() +actual fun getPlatform(): Platform { + return WasmPlatform() +} -actual fun getOpenApiKey(): String = "" \ No newline at end of file +actual fun getOpenApiKey(): String { + return "" +} \ No newline at end of file diff --git a/custom-ktlint-rules/.gitignore b/custom-ktlint-rules/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/custom-ktlint-rules/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/custom-ktlint-rules/build.gradle.kts b/custom-ktlint-rules/build.gradle.kts new file mode 100644 index 0000000..3c1a222 --- /dev/null +++ b/custom-ktlint-rules/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("java-library") + alias(libs.plugins.jetbrainsKotlinJvm) +} + +repositories { + mavenCentral() +} + +dependencies { + implementation("com.pinterest.ktlint:ktlint-cli-ruleset-core:1.3.0") + implementation("com.pinterest.ktlint:ktlint-cli:1.3.0") + implementation("com.pinterest.ktlint:ktlint-rule-engine-core:1.3.0") + implementation("com.pinterest.ktlint:ktlint-test:1.3.0") +} \ No newline at end of file diff --git a/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/CustomRuleSetProvider.kt b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/CustomRuleSetProvider.kt new file mode 100644 index 0000000..5f56f17 --- /dev/null +++ b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/CustomRuleSetProvider.kt @@ -0,0 +1,14 @@ +package com.developersbreach.ktlint.rules + +import com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3 +import com.pinterest.ktlint.rule.engine.core.api.RuleProvider +import com.pinterest.ktlint.rule.engine.core.api.RuleSetId + +class CustomRuleSetProvider : RuleSetProviderV3( + RuleSetId("custom-ktlint-rules") +) { + override fun getRuleProviders() = setOf( + RuleProvider { MultiParameterPerLineRule() }, + RuleProvider { FunctionBlockBodyRule() }, + ) +} \ No newline at end of file diff --git a/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/FunctionBlockBodyRule.kt b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/FunctionBlockBodyRule.kt new file mode 100644 index 0000000..cef3640 --- /dev/null +++ b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/FunctionBlockBodyRule.kt @@ -0,0 +1,35 @@ +package com.developersbreach.ktlint.rules + +import com.pinterest.ktlint.rule.engine.core.api.Rule +import com.pinterest.ktlint.rule.engine.core.api.RuleId +import com.pinterest.ktlint.rule.engine.core.api.ElementType +import org.jetbrains.kotlin.com.intellij.lang.ASTNode + +class FunctionBlockBodyRule : Rule( + ruleId = RuleId("custom-ktlint-rules:function-block-body"), + about = About( + maintainer = "Functions must use a block body with explicit return and braces", + ), +) { + @Deprecated("Marked for removal in Ktlint 2.0. Please implement interface RuleAutocorrectApproveHandler.") + override fun beforeVisitChildNodes( + node: ASTNode, + autoCorrect: Boolean, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, + ) { + if (node.elementType == ElementType.FUN) { + val hasEq = node.findChildByType(ElementType.EQ) != null + val hasBlock = node.findChildByType(ElementType.BLOCK) != null + if (hasEq && !hasBlock) { + // report at the '=' sign + node.findChildByType(ElementType.EQ)?.let { eq -> + emit( + eq.startOffset, + "Functions must use a block body with explicit return and braces", + false, + ) + } + } + } + } +} \ No newline at end of file diff --git a/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/MultiParameterPerLineRule.kt b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/MultiParameterPerLineRule.kt new file mode 100644 index 0000000..73b0f48 --- /dev/null +++ b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/MultiParameterPerLineRule.kt @@ -0,0 +1,54 @@ +package com.developersbreach.ktlint.rules + +import com.pinterest.ktlint.rule.engine.core.api.ElementType +import com.pinterest.ktlint.rule.engine.core.api.Rule +import com.pinterest.ktlint.rule.engine.core.api.RuleId +import org.jetbrains.kotlin.com.intellij.lang.ASTNode +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType + +class MultiParameterPerLineRule : Rule( + ruleId = RuleId("custom-ktlint-rules:multi-parameter-per-line"), + about = About( + maintainer = "Each value argument must be on its own line if there is more than one (only in @Composable functions)", + ) +) { + @Deprecated("Marked for removal in Ktlint 2.0. Please implement interface RuleAutocorrectApproveHandler.") + override fun beforeVisitChildNodes( + node: ASTNode, + autoCorrect: Boolean, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, + ) { + if (node.elementType != ElementType.VALUE_ARGUMENT_LIST) return + + // limit to @Composable + val containingFun = node.psi.getParentOfType(true) ?: return + if (containingFun.annotationEntries.none { it.shortName?.asString() == "Composable" }) return + + val args = node.getChildren(null) + .filter { it.elementType == ElementType.VALUE_ARGUMENT } + if (args.size <= 1) return + + val lines = args.map { it.lineNumber() }.toSet() + if (lines.size == 1) { + emit(node.startOffset, "Each parameter should be on its own line", true) + + if (autoCorrect) { + val psiFactory = KtPsiFactory(node.psi.project) + args.forEachIndexed { index, argNode -> + if (index > 0) { + // before each argument except the first, insert a newline + indentation + val whiteSpace = psiFactory.createWhiteSpace("\n ") + node.addChild(whiteSpace.node, argNode) + } + } + } + } + } + + private fun ASTNode.lineNumber(): Int { + val doc = psi.containingFile.viewProvider.document + return doc?.getLineNumber(startOffset) ?: -1 + } +} \ No newline at end of file diff --git a/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/NamedArgumentsRule.kt b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/NamedArgumentsRule.kt new file mode 100644 index 0000000..1d1ece5 --- /dev/null +++ b/custom-ktlint-rules/src/main/kotlin/com/developersbreach/ktlint/rules/NamedArgumentsRule.kt @@ -0,0 +1,48 @@ +package com.developersbreach.ktlint.rules + +import com.pinterest.ktlint.rule.engine.core.api.Rule +import com.pinterest.ktlint.rule.engine.core.api.RuleId +import com.pinterest.ktlint.rule.engine.core.api.ElementType +import org.jetbrains.kotlin.com.intellij.lang.ASTNode +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType + +class NamedArgumentsRule : Rule( + ruleId = RuleId("custom-ktlint-rules:named-arguments"), + about = About( + maintainer = "All call-site arguments must use explicit names", + ) +) { + @Deprecated("Marked for removal in Ktlint 2.0. Please implement interface RuleAutocorrectApproveHandler.") + override fun beforeVisitChildNodes( + node: ASTNode, + autoCorrect: Boolean, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, + ) { + // only look at call-site argument lists + if (node.elementType != ElementType.VALUE_ARGUMENT_LIST || + node.treeParent?.elementType != ElementType.CALL_EXPRESSION + ) { + return + } + + // walk up to see if we're inside a @Composable function + val containingFun = node.psi.getParentOfType(true) ?: return + val isComposable = containingFun.annotationEntries + .any { it.shortName?.asString() == "Composable" } + if (!isComposable) return + + // enforce named args + node.getChildren(null) + .filter { it.elementType == ElementType.VALUE_ARGUMENT } + .forEach { arg -> + if (arg.findChildByType(ElementType.EQ) == null) { + emit( + arg.startOffset, + "Call arguments in @Composable functions must be named", + false, + ) + } + } + } +} diff --git a/custom-ktlint-rules/src/main/resources/META-INF/services/com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3 b/custom-ktlint-rules/src/main/resources/META-INF/services/com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3 new file mode 100644 index 0000000..619903f --- /dev/null +++ b/custom-ktlint-rules/src/main/resources/META-INF/services/com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3 @@ -0,0 +1 @@ +com.developersbreach.ktlint.rules.CustomRuleSetProvider \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 04bfecb..6ba4bc9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,6 +22,7 @@ ktor-bom = "3.0.1" koin = "4.0.4" navigation-compose = "2.9.0" ktlint = "12.2.0" +jetbrainsKotlinJvm = "2.1.10" [libraries] androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" } @@ -64,4 +65,5 @@ composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-mu composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } \ No newline at end of file +ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } +jetbrainsKotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "jetbrainsKotlinJvm" } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 2e42f7e..622b012 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -28,4 +28,5 @@ dependencyResolutionManagement { } } -include(":composeApp") \ No newline at end of file +include(":composeApp") +include(":custom-ktlint-rules") \ No newline at end of file