diff --git a/.gitignore b/.gitignore index 71c276a..ca563fb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ app/.idea/ .cxx local.properties /buildSrc/build/ +.kotlin diff --git a/app/build.gradle.kts b/app/build.gradle.kts deleted file mode 100644 index f5ed860..0000000 --- a/app/build.gradle.kts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2024 Jayesh Seth - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -@Suppress("DSL_SCOPE_VIOLATION") - -plugins { - alias(libs.plugins.madifiers.application) -} - -android { - namespace = libs.versions.namespace.sample.get() - compileSdk = libs.versions.compile.sdk.get().toInt() - - defaultConfig { - applicationId = libs.versions.applicationId.get() - minSdk = libs.versions.min.sdk.get().toInt() - targetSdk = libs.versions.target.sdk.get().toInt() - versionCode = libs.versions.version.code.get().toInt() - versionName = libs.versions.version.name.get() - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary = true - } - } - - buildTypes { - release { - isMinifyEnabled = true - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } -} - -dependencies { - // project modules -/* - implementation(projects.madifiersText.bionicText) - implementation(projects.madifiersText.animateTextUnitAsState) - implementation(projects.madifiersWindow.windowUtils) - implementation(projects.madifiersUtils.buttons) -*/ - implementation(libs.bundles.madifiers) - - implementation(libs.commonmodule) - implementation(libs.androidx.activity.compose) - implementation(libs.androidx.window) - implementation(libs.core.ktx) - implementation(libs.compose.material3) - implementation(libs.compose.material.iconsExtended) - implementation(libs.compose.material3.window) - implementation(libs.compose.ui) - implementation(libs.shimmer) - implementation(libs.color.picker) - implementation(libs.navigation.compose) - implementation(libs.navigation.compose) - implementation(libs.compose.ui.googleFonts) - implementation(libs.compose.ui.graphics) - implementation(libs.compose.ui.tooling.preview) - debugImplementation(libs.compose.ui.manifest) - debugImplementation(libs.compose.ui.tooling) - implementation(libs.lifecycle.compiler) - implementation(libs.lifecycle.runtime) - implementation(libs.lifecycle.viewmodel.compose) - implementation(libs.lifecycle.viewmodel.ktx) - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.test.ext.junit) - androidTestImplementation(libs.espresso.core) - androidTestImplementation(libs.android.test.ext.junit) -} \ No newline at end of file diff --git a/app/src/androidTest/java/pro/jayeshseth/madifiers/ExampleInstrumentedTest.kt b/app/src/androidTest/java/pro/jayeshseth/madifiers/ExampleInstrumentedTest.kt deleted file mode 100644 index b5b5754..0000000 --- a/app/src/androidTest/java/pro/jayeshseth/madifiers/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2024 Jayesh Seth - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package pro.jayeshseth.madifiers - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("in.realogs.madifiers", appContext.packageName) - } -} \ No newline at end of file diff --git a/app/src/test/java/pro/jayeshseth/madifiers/ExampleUnitTest.kt b/app/src/test/java/pro/jayeshseth/madifiers/ExampleUnitTest.kt deleted file mode 100644 index fb90657..0000000 --- a/app/src/test/java/pro/jayeshseth/madifiers/ExampleUnitTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2024 Jayesh Seth - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package pro.jayeshseth.madifiers - -import org.junit.Assert.assertEquals -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 750e788..8f54a28 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { `kotlin-dsl` } @@ -5,33 +7,73 @@ plugins { group = "pro.jayeshseth.madifiers.buildlogic" java { - sourceCompatibility = JavaVersion.VERSION_19 - targetCompatibility = JavaVersion.VERSION_19 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_17 + } } dependencies { compileOnly(libs.android.gradlePlugin) compileOnly(libs.kotlin.gradlePlugin) compileOnly(libs.spotless.gradlePlugin) + compileOnly(libs.ksp.gradlePlugin) + compileOnly(libs.android.tools.common) + compileOnly(libs.compose.gradlePlugin) } gradlePlugin { plugins { + /* Spotless */ register("spotless") { id = "madifiers.spotless" implementationClass = "SpotlessConventionPlugin" } - register("androidLibraryCompose") { - id = "madifiers.library.compose" - implementationClass = "AndroidLibraryComposeConventionPlugin" + + /* Base Internal Plugins */ + register("androidApplication") { + id = "android.application" + implementationClass = "AndroidApplicationConventionPlugin" } + register("androidApplicationCompose") { - id = "madifiers.application.compose" + id = "android.application.compose" implementationClass = "AndroidApplicationComposeConventionPlugin" } - register("madifiersLibrary") { - id = "madifiers.library" - implementationClass = "MadifiersLibraryConventionPlugin" + + register("androidLibraryCompose") { + id = "android.library.compose" + implementationClass = "AndroidLibraryComposeConventionPlugin" + } + + register("kmpLibrary") { + id = "kmp.library" + implementationClass = "KmpLibraryConventionPlugin" + } + + register("cmpLibrary") { + id = "cmp.library" + implementationClass = "CmpLibraryConventionPlugin" + } + + register("cmpApplication") { + id = "cmp.application" + implementationClass = "CmpApplicationConventionPlugin" + } + + /* Shared Module/Library Plugins */ + register("madifiersAndroidLibrary") { + id = "madifiers.android.library" + implementationClass = "MadifiersAndroidLibraryConventionPlugin" + } + + register("madifiersCmpLibrary") { + id = "madifiers.cmp.library" + implementationClass = "MadifiersCmpLibraryConventionPlugin" } } } diff --git a/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt index 9a8e4b0..b44098a 100644 --- a/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt @@ -9,8 +9,7 @@ class AndroidApplicationComposeConventionPlugin: Plugin { override fun apply(target: Project) { with(target) { pluginManager.apply { - apply("com.android.application") - apply("org.jetbrains.kotlin.android") + apply("android.application") apply("madifiers.spotless") apply("org.jetbrains.kotlin.plugin.compose") } diff --git a/build-logic/convention/src/main/java/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidApplicationConventionPlugin.kt new file mode 100644 index 0000000..879e855 --- /dev/null +++ b/build-logic/convention/src/main/java/AndroidApplicationConventionPlugin.kt @@ -0,0 +1,41 @@ +import com.android.build.api.dsl.ApplicationExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import pro.jayeshseth.madifiers.convention.configureKotlinAndroid +import pro.jayeshseth.madifiers.convention.libs + +class AndroidApplicationConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.application") + // required when only want to use android as platform +// apply("org.jetbrains.kotlin.android") + } + + extensions.configure() { + namespace = libs.findVersion("namespace-androidApp").get().toString() + + defaultConfig { + applicationId = libs.findVersion("applicationId").get().toString() + targetSdk = libs.findVersion("target-sdk").get().toString().toInt() + versionCode = libs.findVersion("version-code").get().toString().toInt() + versionName = libs.findVersion("version-name").get().toString() + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + buildTypes { + getByName("release") { + isMinifyEnabled = true + } + } + configureKotlinAndroid(this) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt index e4aa876..8c5e3d0 100644 --- a/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt @@ -1,10 +1,9 @@ -import com.android.build.gradle.LibraryExtension +import com.android.build.api.dsl.LibraryExtension import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.configure import pro.jayeshseth.madifiers.convention.configureAndroidCompose import pro.jayeshseth.madifiers.convention.configureKotlinAndroid -import pro.jayeshseth.madifiers.convention.kotlinOptions class AndroidLibraryComposeConventionPlugin : Plugin { override fun apply(target: Project) { @@ -17,9 +16,9 @@ class AndroidLibraryComposeConventionPlugin : Plugin { configureAndroidCompose(this) configureKotlinAndroid(this) - kotlinOptions { - freeCompilerArgs = freeCompilerArgs - } +// kotlinOptions { +// freeCompilerArgs = freeCompilerArgs +// } } } } diff --git a/build-logic/convention/src/main/java/CmpApplicationConventionPlugin.kt b/build-logic/convention/src/main/java/CmpApplicationConventionPlugin.kt new file mode 100644 index 0000000..82180ce --- /dev/null +++ b/build-logic/convention/src/main/java/CmpApplicationConventionPlugin.kt @@ -0,0 +1,41 @@ +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import pro.jayeshseth.madifiers.convention.applyHierarchyTemplate +import pro.jayeshseth.madifiers.convention.configureAndroidTarget +import pro.jayeshseth.madifiers.convention.configureDesktopTarget +import pro.jayeshseth.madifiers.convention.configureIosTargets +import pro.jayeshseth.madifiers.convention.configureWebTarget +import pro.jayeshseth.madifiers.convention.debugImplementation +import pro.jayeshseth.madifiers.convention.libs + +class CmpApplicationConventionPlugin : Plugin { + + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("android.application.compose") + apply("org.jetbrains.kotlin.multiplatform") + apply("org.jetbrains.compose") + apply("org.jetbrains.kotlin.plugin.compose") + apply("org.jetbrains.kotlin.plugin.serialization") + apply("org.jetbrains.compose.hot-reload") + } + + configureAndroidTarget() + configureIosTargets() + configureDesktopTarget() + configureWebTarget() + + extensions.configure { + applyHierarchyTemplate() + } + + dependencies { + debugImplementation(libs.findLibrary("compose-ui-tooling").get()) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/CmpLibraryConventionPlugin.kt b/build-logic/convention/src/main/java/CmpLibraryConventionPlugin.kt new file mode 100644 index 0000000..d8563af --- /dev/null +++ b/build-logic/convention/src/main/java/CmpLibraryConventionPlugin.kt @@ -0,0 +1,34 @@ +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies +import pro.jayeshseth.madifiers.convention.AndroidMainImplementation +import pro.jayeshseth.madifiers.convention.CommonMainImplementation +import pro.jayeshseth.madifiers.convention.debugImplementation +import pro.jayeshseth.madifiers.convention.libs + +class CmpLibraryConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + pluginManager.apply { + apply("org.jetbrains.compose") + apply("kmp.library") + apply("org.jetbrains.kotlin.plugin.compose") + } + + dependencies { + AndroidMainImplementation(libs.findLibrary("core-ktx").get()) + CommonMainImplementation(libs.findLibrary("jetbrains-compose-ui").get()) + CommonMainImplementation(libs.findLibrary("jetbrains-compose-foundation").get()) + CommonMainImplementation(libs.findLibrary("jetbrains-compose-material3").get()) + CommonMainImplementation( + libs.findLibrary("jetbrains-compose-material-icons-core").get(), + ) + CommonMainImplementation( + libs.findLibrary("jetbrains-compose-material-icons-extended").get(), + ) + + debugImplementation(libs.findLibrary("compose-ui-tooling").get()) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/KmpLibraryConventionPlugin.kt b/build-logic/convention/src/main/java/KmpLibraryConventionPlugin.kt new file mode 100644 index 0000000..150fe9e --- /dev/null +++ b/build-logic/convention/src/main/java/KmpLibraryConventionPlugin.kt @@ -0,0 +1,37 @@ +import com.android.build.api.dsl.LibraryExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import pro.jayeshseth.madifiers.convention.CommonMainImplementation +import pro.jayeshseth.madifiers.convention.configureKotlinAndroid +import pro.jayeshseth.madifiers.convention.configureKotlinMultiplatform +import pro.jayeshseth.madifiers.convention.libs +import pro.jayeshseth.madifiers.convention.pathToResourcePrefix + +class KmpLibraryConventionPlugin : Plugin { + + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.library") + apply("org.jetbrains.kotlin.multiplatform") + } + + configureKotlinMultiplatform() + + extensions.configure { + configureKotlinAndroid(this) + + resourcePrefix = this@with.pathToResourcePrefix() + + // Required to make debug build of app run in iOS simulator + experimentalProperties["android.experimental.kmp.enableAndroidResources"] = "true" + } + + dependencies { + CommonMainImplementation(libs.findLibrary("jetbrains-lifecycle-compose").get()) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/MadifiersLibraryConventionPlugin.kt b/build-logic/convention/src/main/java/MadifiersAndroidLibraryConventionPlugin.kt similarity index 90% rename from build-logic/convention/src/main/java/MadifiersLibraryConventionPlugin.kt rename to build-logic/convention/src/main/java/MadifiersAndroidLibraryConventionPlugin.kt index dff427c..379ac0c 100644 --- a/build-logic/convention/src/main/java/MadifiersLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/java/MadifiersAndroidLibraryConventionPlugin.kt @@ -7,11 +7,11 @@ import pro.jayeshseth.madifiers.convention.configureAndroidCompose import pro.jayeshseth.madifiers.convention.configureKotlinAndroid import pro.jayeshseth.madifiers.convention.libs -class MadifiersLibraryConventionPlugin : Plugin { +class MadifiersAndroidLibraryConventionPlugin : Plugin { override fun apply(target: Project) { with(target) { pluginManager.apply { - apply("madifiers.library.compose") + apply("android.library.compose") apply("madifiers.spotless") apply("org.jetbrains.kotlin.android") apply("com.vanniktech.maven.publish") diff --git a/build-logic/convention/src/main/java/MadifiersCmpLibraryConventionPlugin.kt b/build-logic/convention/src/main/java/MadifiersCmpLibraryConventionPlugin.kt new file mode 100644 index 0000000..41e6784 --- /dev/null +++ b/build-logic/convention/src/main/java/MadifiersCmpLibraryConventionPlugin.kt @@ -0,0 +1,32 @@ +import com.android.build.api.dsl.LibraryExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import pro.jayeshseth.madifiers.convention.configureAndroidCompose +import pro.jayeshseth.madifiers.convention.configureIosTargets +import pro.jayeshseth.madifiers.convention.configureKotlinAndroid +import pro.jayeshseth.madifiers.convention.libs + +class MadifiersCmpLibraryConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + pluginManager.apply { + apply("cmp.library") + apply("madifiers.spotless") + apply("com.vanniktech.maven.publish") + } + + extensions.configure { + configureAndroidCompose(this) + configureKotlinAndroid(this) + } + + dependencies { +// add("implementation", libs.findLibrary("compose-material3").get()) +// add("implementation", libs.findLibrary("compose-ui").get()) +// add("implementation", libs.findLibrary("androidx-activity-compose").get()) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/AndroidCompose.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/AndroidCompose.kt index 3346dd8..8ab32ef 100644 --- a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/AndroidCompose.kt +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/AndroidCompose.kt @@ -2,25 +2,20 @@ package pro.jayeshseth.madifiers.convention import com.android.build.api.dsl.CommonExtension import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies +import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension import java.io.File internal fun Project.configureAndroidCompose( - commonExtension: CommonExtension<*, *, *, *, *> + commonExtension: CommonExtension<*, *, *, *, *, *>, ) { commonExtension.apply { buildFeatures { + buildConfig = true compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.findVersion("compose-compiler").get().toString() - } - - kotlinOptions { - freeCompilerArgs = freeCompilerArgs + buildComposeMetricsParameters() - } - packaging { resources { excludes.add("/META-INF/{AL2.0,LGPL2.1}") @@ -29,9 +24,37 @@ internal fun Project.configureAndroidCompose( dependencies { val bom = libs.findLibrary("compose-bom").get() - add("implementation", platform(bom)) - add("debugImplementation", libs.findLibrary("compose-ui-manifest").get()) - add("androidTestImplementation", platform(bom)) + "implementation"(platform(bom)) + "testImplementation"(platform(bom)) + + "debugImplementation"(libs.findLibrary("compose-ui-tooling").get()) + "debugImplementation"(libs.findLibrary("compose-ui-tooling-preview").get()) + "debugImplementation"(libs.findLibrary("compose-ui-manifest").get()) + } + + // Configure Compose Compiler metrics and reports + extensions.configure { + val enableMetricsProvider = + project.providers.gradleProperty("enableComposeCompilerMetrics") + val enableMetrics = (enableMetricsProvider.orNull == "true") + + val enableReportsProvider = + project.providers.gradleProperty("enableComposeCompilerReports") + val enableReports = (enableReportsProvider.orNull == "true") + + if (enableMetrics) { + metricsDestination.set(project.layout.buildDirectory.dir("compose-metrics")) + } + + if (enableReports) { + reportsDestination.set(project.layout.buildDirectory.dir("compose-reports")) + } + + // Optional: Enable strong skipping mode (recommended) + enableStrongSkippingMode.set(true) + + // Optional: Include source information in generated code + includeSourceInformation.set(true) } } } @@ -44,7 +67,7 @@ private fun Project.buildComposeMetricsParameters(): List { val metricsFolder = File(project.buildDir, "compose-metrics") metricParameters.add("-P") metricParameters.add( - "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + metricsFolder.absolutePath + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + metricsFolder.absolutePath, ) } @@ -54,7 +77,7 @@ private fun Project.buildComposeMetricsParameters(): List { val reportsFolder = File(project.buildDir, "compose-reports") metricParameters.add("-P") metricParameters.add( - "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + reportsFolder.absolutePath + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + reportsFolder.absolutePath, ) } return metricParameters.toList() diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/HierarchyTemplate.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/HierarchyTemplate.kt new file mode 100644 index 0000000..5b3f606 --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/HierarchyTemplate.kt @@ -0,0 +1,64 @@ +@file:OptIn(ExperimentalKotlinGradlePluginApi::class) +package pro.jayeshseth.madifiers.convention + +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinHierarchyTemplate +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree + + +private val hierarchyTemplate = KotlinHierarchyTemplate { + withSourceSetTree( + KotlinSourceSetTree.main, + KotlinSourceSetTree.test, + ) + + common { + withCompilations { true } + + group("mobileAndDesktop") { + withAndroidTarget() + withJvm() + group("ios") { + withIos() + } + } + + group("web") { + withJs() + withWasmJs() + } + + group("mobile") { + withAndroidTarget() + group("ios") { + withIos() + } + } + + group("jvmCommon") { + withAndroidTarget() + withJvm() + } + + group("native") { + withNative() + + group("apple") { + withApple() + + group("ios") { + withIos() + } + + group("macos") { + withMacos() + } + } + } + } +} + +fun KotlinMultiplatformExtension.applyHierarchyTemplate() { + applyHierarchyTemplate(hierarchyTemplate) +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroid.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroid.kt index 1696e69..529acee 100644 --- a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroid.kt +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroid.kt @@ -3,32 +3,44 @@ package pro.jayeshseth.madifiers.convention import com.android.build.api.dsl.CommonExtension import org.gradle.api.JavaVersion import org.gradle.api.Project -import org.gradle.api.plugins.ExtensionAware -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + internal fun Project.configureKotlinAndroid( - commonExtension: CommonExtension<*, *, *, *, *> + commonExtension: CommonExtension<*, *, *, *, *, *>, ) { commonExtension.apply { + compileSdk = libs.findVersion("compile-sdk").get().toString().toInt() + + defaultConfig { + minSdk = libs.findVersion("min-sdk").get().toString().toInt() + } + compileOptions { - sourceCompatibility = JavaVersion.VERSION_19 - targetCompatibility = JavaVersion.VERSION_19 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = "19" - freeCompilerArgs = freeCompilerArgs + listOf( - "-opt-in=kotlin.RequiresOptIn", - "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", - ) + buildFeatures { + buildConfig = true + } + + tasks.withType { + compilerOptions { + jvmTarget.set(JvmTarget.fromTarget(libs.findVersion("jvm-target").get().toString())) + freeCompilerArgs.addAll( + listOf( + "-opt-in=kotlin.RequiresOptIn", + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + ) + ) + } } lint { abortOnError = false } } -} - -fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { - (this as ExtensionAware).extensions.configure("kotlinOptions", block) } \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroidTarget.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroidTarget.kt new file mode 100644 index 0000000..2ab8e2d --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinAndroidTarget.kt @@ -0,0 +1,25 @@ +package pro.jayeshseth.madifiers.convention + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +/** + * Configures the Android target for a Kotlin Multiplatform project. + * + * This extension function sets up the `androidTarget` within the `kotlin` block, + * specifically configuring the JVM target version for the Android compilation. + * It sets the `jvmTarget` to `JVM_17`. + */ +internal fun Project.configureAndroidTarget() { + extensions.configure { + androidTarget { + @OptIn(ExperimentalKotlinGradlePluginApi::class) + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinDesktopTarget.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinDesktopTarget.kt new file mode 100644 index 0000000..4e77a8e --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinDesktopTarget.kt @@ -0,0 +1,27 @@ +package pro.jayeshseth.madifiers.convention + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +/** + * Configures the "desktop" JVM target for a Kotlin Multiplatform project. + * + * This extension function applies the following configuration: + * - Adds a JVM target named "desktop". + * - Sets the a`jvmTarget` for all compilations within the "desktop" target to `JvmTarget.JVM_17`. + */ +internal fun Project.configureDesktopTarget() { + extensions.configure { + jvm("desktop") { + compilations.all { + compileTaskProvider.configure { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } + } + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinIosTarget.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinIosTarget.kt new file mode 100644 index 0000000..22e496e --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinIosTarget.kt @@ -0,0 +1,33 @@ +package pro.jayeshseth.madifiers.convention + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +/** + * Configures the iOS targets for a Kotlin Multiplatform project. + * + * This extension function on [Project] accesses the [KotlinMultiplatformExtension] + * and sets up the following iOS targets: + * - `iosX64()` for x86_64 simulators. + * - `iosArm64()` for ARM64-based iOS devices. + * - `iosSimulatorArm64()` for ARM64-based simulators (Apple Silicon Macs). + * + * For each of these targets, it configures the output framework with a + * base name of "ComposeApp" and sets it to be a static framework (`isStatic = true`). + * This is a common setup for integrating a KMP shared module into an Xcode project. + */ +internal fun Project.configureIosTargets() { + extensions.configure { + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "ComposeApp" + isStatic = true + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinMultiplatform.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinMultiplatform.kt new file mode 100644 index 0000000..5fcf52e --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinMultiplatform.kt @@ -0,0 +1,47 @@ +package pro.jayeshseth.madifiers.convention + +import com.android.build.api.dsl.LibraryExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +/** + * Configures a Gradle [Project] for Kotlin Multiplatform development. + * + * This function applies common configurations for a multiplatform library module, including: + * - Setting the Android library namespace based on the project's path. + * - Configuring targets for Android, Desktop (JVM), and Web (JS). + * - Configuring iOS targets (X64, Arm64, SimulatorArm64) and setting the framework base name. + * - Applying the Kotlin source set hierarchy template. + * - Adding common compiler options, such as enabling expect/actual classes and opting into + * experimental APIs like `kotlin.RequiresOptIn` and `kotlin.time.ExperimentalTime`. + */ +internal fun Project.configureKotlinMultiplatform() { + extensions.configure { + namespace = this@configureKotlinMultiplatform.pathToPackageName() + } + + configureAndroidTarget() + configureDesktopTarget() + configureWebTarget() + + extensions.configure { + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = this@configureKotlinMultiplatform.pathToFrameworkName() + } + } + + applyHierarchyTemplate() + + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn") + freeCompilerArgs.add("-opt-in=kotlin.time.ExperimentalTime") + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinWebTarget.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinWebTarget.kt new file mode 100644 index 0000000..683b80f --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/KotlinWebTarget.kt @@ -0,0 +1,39 @@ +package pro.jayeshseth.madifiers.convention + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension + +/** + * Configures the Kotlin/JS and Kotlin/Wasm targets for a web browser environment. + * + * This extension function applies the necessary configuration to a Gradle `Project` + * to set up both JavaScript (JS) and WebAssembly (Wasm) targets for a Compose Multiplatform project. + * + * For both `js` and `wasmJs` targets, it: + * - Enables the browser toolchain. + * - Sets up the webpack configuration to produce a unified output file named "composeApp.js". + * - Declares an executable binary, making the targets runnable. + */ +@OptIn(ExperimentalWasmDsl::class) +internal fun Project.configureWebTarget() { + extensions.configure { + js { + browser { + commonWebpackConfig { + outputFileName = "composeApp.js" + } + } + binaries.executable() + } + wasmJs { + browser { + commonWebpackConfig { + outputFileName = "composeApp.js" + } + } + binaries.executable() + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/PathUtil.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/PathUtil.kt new file mode 100644 index 0000000..e035bbf --- /dev/null +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/PathUtil.kt @@ -0,0 +1,69 @@ +package pro.jayeshseth.madifiers.convention + +import org.gradle.api.Project +import java.util.Locale + +/** + * Converts a Gradle project's path into a valid Android package name. + * + * This function takes the project's path (e.g., `:feature:home`) and transforms it + * into a package name by replacing colons with dots and converting it to lowercase. + * It then prepends a base package name (`pro.jayeshseth`) to form the full package name. + * + * For example, a project with the path `:madifiers-window:windowUtils` will be converted to + * `pro.jayeshseth.madifiers.window.windowUtils`. + * + * @return The generated package name as a [String]. + */ +fun Project.pathToPackageName(): String { + val relativePackageName = path + .replace(':', '.') + .replace('-','.') + .lowercase() + + println("pathToPackageName: pro.jayeshseth$relativePackageName") + return "pro.jayeshseth$relativePackageName" +} + +/** + * Converts a Gradle project path into a resource prefix. + * + * This is used to create unique resource prefixes for each module, preventing resource name collisions. + * The transformation involves: + * 1. Replacing colons (`:`) with underscores (`_`). + * 2. Converting the entire string to lowercase. + * 3. Removing the initial underscore (which comes from the root project's leading colon). + * 4. Appending a final underscore to signify it's a prefix. + * + * For example, a project path `:feature:home` would be transformed into `feature_home_`. + * + * @return A string suitable for use as a resource file prefix. + */ +fun Project.pathToResourcePrefix(): String { + return path + .replace(':', '_') + .lowercase() + .drop(1) + "_" +} + +/** + * Converts a Gradle project path into a CamelCase framework name. + * + * This is used for naming iOS frameworks in a Kotlin Multiplatform project. + * It takes the project path, splits it by common delimiters (`:`, `-`, `_`, ` `), + * capitalizes the first letter of each part, and then joins them together + * without any separators. + * + * For example, a project path like `:feature:my-awesome-feature` would be + * converted to `FeatureMyAwesomeFeature`. + * + * @return The CamelCase representation of the project path. + */ +fun Project.pathToFrameworkName(): String { + val parts = this.path.split(":", "-", "_", " ") + return parts.joinToString("") { part -> + part.replaceFirstChar { + it.titlecase(Locale.ROOT) + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/ProjectExtension.kt b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/ProjectExtension.kt index fd51c77..a843ace 100644 --- a/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/ProjectExtension.kt +++ b/build-logic/convention/src/main/java/pro/jayeshseth/madifiers/convention/ProjectExtension.kt @@ -7,3 +7,8 @@ import org.gradle.kotlin.dsl.getByType val Project.libs get(): VersionCatalog = extensions.getByType().named("libs") + + +internal const val AndroidMainImplementation = "androidMainImplementation" +internal const val CommonMainImplementation = "commonMainImplementation" +internal const val debugImplementation = "debugImplementation" \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index a11f5b6..f13b908 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,8 +4,15 @@ plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidLibrary) apply false alias(libs.plugins.kotlinAndroid) apply false - alias(libs.plugins.compose.compiler) apply false + alias(libs.plugins.composeCompiler) apply false alias(libs.plugins.spotless) alias(libs.plugins.vanniktech.maven.publish) alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.composeHotReload) apply false + alias(libs.plugins.kotlin.serialization) apply false + alias(libs.plugins.composeMultiplatform) apply false + alias(libs.plugins.kotlinMultiplatform) apply false + alias(libs.plugins.android.kotlin.multiplatform.library) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.kotlinAtomicfu) apply false } \ No newline at end of file diff --git a/app/.gitignore b/composeApp/.gitignore similarity index 100% rename from app/.gitignore rename to composeApp/.gitignore diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts new file mode 100644 index 0000000..729566f --- /dev/null +++ b/composeApp/build.gradle.kts @@ -0,0 +1,122 @@ +/* + * Copyright 2024 Jayesh Seth + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Suppress("DSL_SCOPE_VIOLATION") + +plugins { + alias(libs.plugins.madifiers.cmp.application) +} + +kotlin { + sourceSets { + androidMain { + dependencies { + + // project modules + /* + implementation(projects.madifiersText.bionicText) + implementation(projects.madifiersText.animateTextUnitAsState) + implementation(projects.madifiersWindow.windowUtils) + implementation(projects.madifiersUtils.buttons) + */ + implementation(libs.madifiers.bionicText) + implementation(libs.madifiers.animatedTextUnit) + implementation(libs.madifiers.madButtons) +// implementation(libs.madifiers.windowUtils) +// implementation(libs.bundles.madifiers) + + implementation(libs.commonmodule) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.window) + implementation(libs.core.ktx) + implementation(libs.compose.material3) + implementation(libs.compose.material.iconsExtended) + implementation(libs.compose.material3.window) + implementation(libs.compose.ui) + implementation(libs.shimmer) + implementation(libs.color.picker) + implementation(libs.navigation.compose) + implementation(libs.navigation.compose) + implementation(libs.compose.ui.googleFonts) + implementation(libs.compose.ui.graphics) + implementation(libs.compose.ui.tooling.preview) +// debugImplementation(libs.compose.ui.manifest) +// debugImplementation(libs.compose.ui.tooling) + implementation(libs.lifecycle.compiler) + implementation(libs.lifecycle.runtime) + implementation(libs.lifecycle.viewmodel.compose) + implementation(libs.lifecycle.viewmodel.ktx) +// testImplementation(libs.junit) +// androidTestImplementation(libs.androidx.test.ext.junit) +// androidTestImplementation(libs.espresso.core) +// androidTestImplementation(libs.android.test.ext.junit) + } + } + commonMain { + dependencies { + implementation(projects.madifiersWindow.windowUtils) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + implementation(compose.components.resources) + implementation(compose.components.uiToolingPreview) + } + } + } +} + +//dependencies { +// +// // project modules +// /* +// implementation(projects.madifiersText.bionicText) +// implementation(projects.madifiersText.animateTextUnitAsState) +// implementation(projects.madifiersWindow.windowUtils) +// implementation(projects.madifiersUtils.buttons) +// */ +// implementation(libs.madifiers.bionicText) +// implementation(libs.madifiers.animatedTextUnit) +// implementation(libs.madifiers.madButtons) +// implementation(projects.madifiersWindow.windowUtils) +//// implementation(libs.madifiers.windowUtils) +//// implementation(libs.bundles.madifiers) +// +// implementation(libs.commonmodule) +// implementation(libs.androidx.activity.compose) +// implementation(libs.androidx.window) +// implementation(libs.core.ktx) +// implementation(libs.compose.material3) +// implementation(libs.compose.material.iconsExtended) +// implementation(libs.compose.material3.window) +// implementation(libs.compose.ui) +// implementation(libs.shimmer) +// implementation(libs.color.picker) +// implementation(libs.navigation.compose) +// implementation(libs.navigation.compose) +// implementation(libs.compose.ui.googleFonts) +// implementation(libs.compose.ui.graphics) +// implementation(libs.compose.ui.tooling.preview) +// debugImplementation(libs.compose.ui.manifest) +// debugImplementation(libs.compose.ui.tooling) +// implementation(libs.lifecycle.compiler) +// implementation(libs.lifecycle.runtime) +// implementation(libs.lifecycle.viewmodel.compose) +// implementation(libs.lifecycle.viewmodel.ktx) +// testImplementation(libs.junit) +// androidTestImplementation(libs.androidx.test.ext.junit) +// androidTestImplementation(libs.espresso.core) +// androidTestImplementation(libs.android.test.ext.junit) +//} \ No newline at end of file diff --git a/app/proguard-rules.pro b/composeApp/proguard-rules.pro similarity index 100% rename from app/proguard-rules.pro rename to composeApp/proguard-rules.pro diff --git a/app/src/main/AndroidManifest.xml b/composeApp/src/androidMain/AndroidManifest.xml similarity index 100% rename from app/src/main/AndroidManifest.xml rename to composeApp/src/androidMain/AndroidManifest.xml diff --git a/app/src/main/ic_launcher-playstore.png b/composeApp/src/androidMain/ic_launcher-playstore.png similarity index 100% rename from app/src/main/ic_launcher-playstore.png rename to composeApp/src/androidMain/ic_launcher-playstore.png diff --git a/app/src/main/java/pro/jayeshseth/madifiers/MainActivity.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/MainActivity.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/MainActivity.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/MainActivity.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/Navigation.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/Navigation.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/Navigation.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/Navigation.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/composables/SliderTemplate.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/composables/SliderTemplate.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/composables/SliderTemplate.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/composables/SliderTemplate.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/screens/AnimateTextUnit.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/AnimateTextUnit.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/screens/AnimateTextUnit.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/AnimateTextUnit.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/screens/BionicText.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/BionicText.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/screens/BionicText.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/BionicText.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/screens/Buttons.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/Buttons.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/screens/Buttons.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/Buttons.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/screens/GlowButtonScreen.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/GlowButtonScreen.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/screens/GlowButtonScreen.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/GlowButtonScreen.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/screens/HomeScreen.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/HomeScreen.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/screens/HomeScreen.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/HomeScreen.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/screens/WindowInfo.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/WindowInfo.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/screens/WindowInfo.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/screens/WindowInfo.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/theme/Color.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/theme/Color.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/theme/Color.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/theme/Color.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/theme/Theme.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/theme/Theme.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/theme/Theme.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/theme/Theme.kt diff --git a/app/src/main/java/pro/jayeshseth/madifiers/ui/theme/Type.kt b/composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/theme/Type.kt similarity index 100% rename from app/src/main/java/pro/jayeshseth/madifiers/ui/theme/Type.kt rename to composeApp/src/androidMain/kotlin/pro/jayeshseth/madifiers/ui/theme/Type.kt diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/composeApp/src/androidMain/res/drawable/ic_launcher_background.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_background.xml rename to composeApp/src/androidMain/res/drawable/ic_launcher_background.xml diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/composeApp/src/androidMain/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_foreground.xml rename to composeApp/src/androidMain/res/drawable/ic_launcher_foreground.xml diff --git a/app/src/main/res/drawable/madifiers.xml b/composeApp/src/androidMain/res/drawable/madifiers.xml similarity index 100% rename from app/src/main/res/drawable/madifiers.xml rename to composeApp/src/androidMain/res/drawable/madifiers.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher.webp rename to composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_round.webp rename to composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher.webp rename to composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_round.webp rename to composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp rename to composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp rename to composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename to composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/values/colors.xml b/composeApp/src/androidMain/res/values/colors.xml similarity index 100% rename from app/src/main/res/values/colors.xml rename to composeApp/src/androidMain/res/values/colors.xml diff --git a/app/src/main/res/values/ic_launcher_background.xml b/composeApp/src/androidMain/res/values/ic_launcher_background.xml similarity index 100% rename from app/src/main/res/values/ic_launcher_background.xml rename to composeApp/src/androidMain/res/values/ic_launcher_background.xml diff --git a/app/src/main/res/values/strings.xml b/composeApp/src/androidMain/res/values/strings.xml similarity index 100% rename from app/src/main/res/values/strings.xml rename to composeApp/src/androidMain/res/values/strings.xml diff --git a/app/src/main/res/values/themes.xml b/composeApp/src/androidMain/res/values/themes.xml similarity index 100% rename from app/src/main/res/values/themes.xml rename to composeApp/src/androidMain/res/values/themes.xml diff --git a/app/src/main/res/xml/backup_rules.xml b/composeApp/src/androidMain/res/xml/backup_rules.xml similarity index 100% rename from app/src/main/res/xml/backup_rules.xml rename to composeApp/src/androidMain/res/xml/backup_rules.xml diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/composeApp/src/androidMain/res/xml/data_extraction_rules.xml similarity index 100% rename from app/src/main/res/xml/data_extraction_rules.xml rename to composeApp/src/androidMain/res/xml/data_extraction_rules.xml diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 043a9ab..1e9c6e9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,13 @@ [versions] -activity-compose = "1.9.2" -androidGradlePlugin = "8.2.2" +activity-compose = "1.12.2" +androidGradlePlugin = "8.13.2" androidx-test-ext-junit = "1.2.1" androidx-window = "1.3.0" applicationId = "pro.jayeshseth.madifiers" coil = "2.5.0" commonmodule = "0.0.8" -compile-sdk = "34" -compose-bom = "2024.09.01" +compile-sdk = "36" +compose-bom = "2026.01.00" compose-compiler = "1.5.7" core-ktx = "1.13.1" core-splashscreen = "1.0.1" @@ -20,8 +20,10 @@ gson = "2.10.1" hilt = "2.51.1" hilt-ext = "1.1.0" junit = "4.13.2" -kotlin = "2.0.0" +kotlin = "2.3.0" +androidTools = "31.12.0" kotlin-bom = "1.9.20" +kotlinxSerializationCore = "1.9.0" kotlinxSerializationJson = "1.6.2" ksp = "2.0.0-1.0.21" lifecycle = "2.8.5" @@ -31,7 +33,7 @@ min-sdk = "24" namespace-animateTextUnitAsState = "pro.jayeshseth.animatetextunitasstate" namespace-bionicText = "pro.jayeshseth.bionictext" namespace-buttons = "pro.jayeshseth.buttons" -namespace-sample = "pro.jayeshseth.madifiers" +namespace-androidApp = "pro.jayeshseth.madifiers" namespace-textExtensions = "pro.jayeshseth.textextensions" namespace-windowUtils = "pro.jayeshseth.windowutils" navigation = "2.8.0" @@ -54,6 +56,16 @@ bionicText = "1.0.0" animatedTextUnit = "1.0.0" madButtons = "0.0.1" windowUtils = "1.0.0" +jvm-target = "17" +compose-hot-reload = "1.0.0" +compose-jetbrains-m3 = "1.9.0" +compose-multiplatform = "1.10.0" +material-icons = "1.7.3" +compose-lifecycle = "2.9.1" +jetbrains-savedstate = "1.3.1" +jetbrains-core-bundle = "1.0.1" +adaptive = "1.2.0-alpha04" +kotlin-atomic = "0.30.0-beta" [libraries] # [AndroidX Deps] @@ -125,11 +137,29 @@ google-gson = { group = "com.google.code.gson", name = "gson", version.ref = "gs kotlin-bom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlin-bom" } kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinxSerializationCore" } + +# Jetbrains Compose +jetbrains-compose-backhandler = { module = "org.jetbrains.compose.ui:ui-backhandler", version.ref = "compose-multiplatform" } +jetbrains-compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose-multiplatform" } +jetbrains-compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "compose-jetbrains-m3" } +jetbrains-compose-material-icons-core = { module = "org.jetbrains.compose.material:material-icons-core", version.ref = "material-icons" } +jetbrains-compose-material-icons-extended = { module = "org.jetbrains.compose.material:material-icons-extended", version.ref = "material-icons" } +jetbrains-compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "compose-multiplatform" } +jetbrains-compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "compose-multiplatform" } +jetbrains-bundle = { module = "org.jetbrains.androidx.core:core-bundle", version.ref = "jetbrains-core-bundle" } +jetbrains-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", version.ref = "compose-lifecycle" } +jetbrains-lifecycle-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "compose-lifecycle" } +jetbrains-lifecycle-viewmodel-savedstate = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", version.ref = "compose-lifecycle" } +jetbrains-savedstate = { module = "org.jetbrains.androidx.savedstate:savedstate", version.ref = "jetbrains-savedstate" } # Dependencies of the included build-logic android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } spotless-gradlePlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version.ref = "spotless" } +android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" } +ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } +compose-gradlePlugin = { group = "org.jetbrains.kotlin", name = "compose-compiler-gradle-plugin", version.ref = "kotlin" } # [Test Dependencies] # Android Tests @@ -147,6 +177,10 @@ appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "a material = { group = "com.google.android.material", name = "material", version.ref = "com-google-android-material-material" } [plugins] +composeHotReload = { id = "org.jetbrains.compose.hot-reload", version.ref = "compose-hot-reload" } +composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" } +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } androidApplication = { id = "com.android.application", version.ref = "androidGradlePlugin" } androidLibrary = { id = "com.android.library", version.ref = "androidGradlePlugin" } android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } @@ -158,11 +192,15 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } nexus-plugin = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPlugin" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } vanniktech-maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktechMavenPublish" } -compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" } +kotlinAtomicfu = { id = "org.jetbrains.kotlinx.atomicfu", version.ref = "kotlin-atomic" } # Plugins defined by this project -madifiers-library = { id = "madifiers.library", version = "unspecified" } -madifiers-application = { id = "madifiers.application.compose", version = "unspecified" } +madifiers-application = { id = "android.application.compose", version = "unspecified" } +madifiers-android-library = { id = "madifiers.android.library", version = "unspecified" } +madifiers-cmp-application = { id = "cmp.application", version = "unspecified" } +madifiers-cmp-library = { id = "madifiers.cmp.library", version = "unspecified" } +madifiers-kmp-library = { id = "madifiers.kmp.library", version = "unspecified" } madifiers-spotless = { id = "madifiers.spotless", version = "unspecified" } [bundles] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 25cd569..6042b01 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Jul 20 21:50:53 IST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/madifiers-text/animateTextUnitAsState/build.gradle.kts b/madifiers-text/animateTextUnitAsState/build.gradle.kts index d1af34e..b80ef15 100644 --- a/madifiers-text/animateTextUnitAsState/build.gradle.kts +++ b/madifiers-text/animateTextUnitAsState/build.gradle.kts @@ -18,7 +18,7 @@ import pro.jayeshseth.madifiers.Versions @Suppress("DSL_SCOPE_VIOLATION") plugins { - alias(libs.plugins.madifiers.library) + alias(libs.plugins.madifiers.android.library) } mavenPublishing { @@ -26,7 +26,7 @@ mavenPublishing { coordinates( groupId = Versions.artifactGroup, artifactId = artifactId, - version = Versions.animateTextUnitAsState + version = Versions.animateTextUnitAsState, ) pom { diff --git a/madifiers-text/bionicText/build.gradle.kts b/madifiers-text/bionicText/build.gradle.kts index 1ba25ea..6715ef6 100644 --- a/madifiers-text/bionicText/build.gradle.kts +++ b/madifiers-text/bionicText/build.gradle.kts @@ -18,7 +18,7 @@ import pro.jayeshseth.madifiers.Versions @Suppress("DSL_SCOPE_VIOLATION") plugins { - alias(libs.plugins.madifiers.library) + alias(libs.plugins.madifiers.android.library) } mavenPublishing { diff --git a/madifiers-utils/buttons/build.gradle.kts b/madifiers-utils/buttons/build.gradle.kts index 65f3477..9a8de6d 100644 --- a/madifiers-utils/buttons/build.gradle.kts +++ b/madifiers-utils/buttons/build.gradle.kts @@ -16,7 +16,7 @@ import pro.jayeshseth.madifiers.Versions * limitations under the License. */ plugins { - alias(libs.plugins.madifiers.library) + alias(libs.plugins.madifiers.android.library) } mavenPublishing { diff --git a/madifiers-window/windowUtils/build.gradle.kts b/madifiers-window/windowUtils/build.gradle.kts index de3500c..1c8f15b 100644 --- a/madifiers-window/windowUtils/build.gradle.kts +++ b/madifiers-window/windowUtils/build.gradle.kts @@ -18,7 +18,7 @@ import pro.jayeshseth.madifiers.Versions @Suppress("DSL_SCOPE_VIOLATION") plugins { - alias(libs.plugins.madifiers.library) + alias(libs.plugins.madifiers.cmp.library) } mavenPublishing { @@ -33,20 +33,3 @@ mavenPublishing { name.set(artifactId) } } - -android { - namespace = libs.versions.namespace.windowUtils.get() - compileSdk = libs.versions.compile.sdk.get().toInt() - - defaultConfig { - minSdk = libs.versions.min.sdk.get().toInt() - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } -} - -dependencies { - implementation(libs.compose.foundation) -} - diff --git a/madifiers-window/windowUtils/src/main/AndroidManifest.xml b/madifiers-window/windowUtils/src/androidMain/AndroidManifest.xml similarity index 100% rename from madifiers-window/windowUtils/src/main/AndroidManifest.xml rename to madifiers-window/windowUtils/src/androidMain/AndroidManifest.xml diff --git a/madifiers-window/windowUtils/src/androidMain/kotlin/pro/jayeshseth/windowUtils/WindowInfo.android.kt b/madifiers-window/windowUtils/src/androidMain/kotlin/pro/jayeshseth/windowUtils/WindowInfo.android.kt new file mode 100644 index 0000000..8fc9456 --- /dev/null +++ b/madifiers-window/windowUtils/src/androidMain/kotlin/pro/jayeshseth/windowUtils/WindowInfo.android.kt @@ -0,0 +1,29 @@ +package pro.jayeshseth.windowUtils + +import android.content.res.Configuration +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.safeGestures +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp + +/** + * [isInLandscapeMode] checks if device is in landscape orientation + */ +@Composable +fun isInLandscapeMode(): Boolean { + val configuration = LocalConfiguration.current + return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE +} + +/** + * [isGestureNavigation] checks if device is using gesture navigation bar + */ +@Composable +fun isGestureNavigation(): Boolean { + val safeGesture = + WindowInsets.safeGestures.asPaddingValues().calculateLeftPadding(LayoutDirection.Ltr) + return safeGesture != 0.dp +} \ No newline at end of file diff --git a/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/DeviceConfiguration.kt b/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/DeviceConfiguration.kt new file mode 100644 index 0000000..ea2f640 --- /dev/null +++ b/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/DeviceConfiguration.kt @@ -0,0 +1,149 @@ +package pro.jayeshseth.windowUtils + +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalWindowInfo +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import pro.jayeshseth.windowUtils.DeviceConfiguration.DESKTOP +import pro.jayeshseth.windowUtils.DeviceConfiguration.MOBILE_LANDSCAPE +import pro.jayeshseth.windowUtils.DeviceConfiguration.MOBILE_PORTRAIT +import pro.jayeshseth.windowUtils.DeviceConfiguration.TABLET_LANDSCAPE +import pro.jayeshseth.windowUtils.DeviceConfiguration.TABLET_PORTRAIT + +/** + * A Composable function that determines and returns the current [DeviceConfiguration] + * based on the window size. + * + * This function uses [currentWindowAdaptiveInfo] to get the [WindowSizeClass] and then + * maps it to a specific [DeviceConfiguration] enum (e.g., MOBILE_PORTRAIT, TABLET_LANDSCAPE). + * It's useful for creating adaptive UIs that respond to changes in screen size and orientation. + * + * @return The current [DeviceConfiguration] for the window. + * @see DeviceConfiguration + */ +@Composable +fun currentDeviceConfiguration(): DeviceConfiguration { + val windowInfo = LocalWindowInfo.current + val density = LocalDensity.current + + val sizePx = windowInfo.containerSize + + val widthDp = with(density) { sizePx.width.toDp() } + val heightDp = with(density) { sizePx.height.toDp() } + + return DeviceConfiguration.fromWindowInfo(widthDp, heightDp) +} + +/** + * Represents different device configurations based on screen size and orientation. + * + * This enum class categorizes the device's display into common form factors like mobile, tablet, + * and desktop, considering both portrait and landscape orientations. + * + * @property MOBILE_PORTRAIT A typical phone in portrait orientation. + * @property MOBILE_LANDSCAPE A typical phone in landscape orientation. + * @property TABLET_PORTRAIT A tablet in portrait orientation. + * @property TABLET_LANDSCAPE A tablet in landscape orientation. + * @property DESKTOP A large screen, typical of a desktop or a large tablet in landscape. + * @property isMobile Returns true for [MOBILE_PORTRAIT] or [MOBILE_LANDSCAPE]. + * @property isWideScreen Returns true for [TABLET_LANDSCAPE] or [DESKTOP]. + */ +enum class DeviceConfiguration { + MOBILE_PORTRAIT, + MOBILE_LANDSCAPE, + TABLET_PORTRAIT, + TABLET_LANDSCAPE, + DESKTOP; + + val isMobile: Boolean + get() = this in listOf(MOBILE_PORTRAIT, MOBILE_LANDSCAPE) + + val isWideScreen: Boolean + get() = this in listOf(TABLET_LANDSCAPE, DESKTOP) + + companion object { + + /** + * Represents the physical configuration of the device screen based on available width and height. + * This classification logic prioritizes width for layout structure but uses height to distinguish + * landscape phones and desktop environments. + * + * ### Breakpoint Logic & Mapping + * + * | Configuration | Width Condition | Height Condition | Typical Device | + * | :----------------- | :-------------- | :-------------- | :-------------------------- | + * | **MOBILE_PORTRAIT** | `< 600.dp` | *Any* | Standard Phone (Portrait) | + * | **MOBILE_LANDSCAPE** | `≥ 600.dp` | `< 480.dp` | Phone (Landscape) | + * | **TABLET_PORTRAIT** | `600..839.dp` | `≥ 480.dp` | Tablet (Portrait), Foldable | + * | **TABLET_LANDSCAPE** | `≥ 840.dp` | `480..899.dp` | Tablet (Land), Small Laptop | + * | **DESKTOP** | `≥ 1200.dp` | `≥ 1200.dp` | Large Monitor, Desktop | + */ + fun fromWindowInfo(widthDp: Dp, heightDp: Dp): DeviceConfiguration { + return when { + widthDp < COMPACT_WIDTH && + heightDp >= COMPACT_HEIGHT -> MOBILE_PORTRAIT + + widthDp >= COMPACT_WIDTH && + heightDp < COMPACT_HEIGHT -> MOBILE_LANDSCAPE + + widthDp < EXPANDED_WIDTH && + heightDp < EXPANDED_HEIGHT -> TABLET_PORTRAIT + + widthDp in COMPACT_WIDTH..EXPANDED_WIDTH && + heightDp >= EXPANDED_HEIGHT -> TABLET_PORTRAIT + + widthDp in EXPANDED_WIDTH..EXTRA_EXPANDED_WIDTH && + heightDp in COMPACT_HEIGHT..EXPANDED_HEIGHT -> TABLET_LANDSCAPE + + widthDp >= EXTRA_EXPANDED_WIDTH && + heightDp >= EXTRA_EXPANDED_HEIGHT -> DESKTOP + + else -> DESKTOP + } + } + } +} + + +/** + * A Standard Width for mobile devices in portrait orientation. + * + * @see Source + */ +private val COMPACT_WIDTH = 600.dp + +/** + * A Standard Expanded Width for inner display of foldables. + * + * @see Source + */ +private val EXPANDED_WIDTH = 840.dp + +/** + * Width of very large displays usually tablets or large monitors. + * + * @see Source + */ +private val EXTRA_EXPANDED_WIDTH = 1600.dp + +/** + * A Standard height for mobile devices in landscape orientation. + * + * @see Source + */ +private val COMPACT_HEIGHT = 480.dp + +/** + * A Standard Expanded Height of large displays in portrait orientation. + * + * @see Source + */ +private val EXPANDED_HEIGHT = 900.dp + +/** + * Height of a very large display usually tablets or large monitors. + * + * @see Source + */ +private val EXTRA_EXPANDED_HEIGHT = 1200.dp \ No newline at end of file diff --git a/madifiers-window/windowUtils/src/main/java/pro/jayeshseth/windowUtils/Dimensions.kt b/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/Dimensions.kt similarity index 81% rename from madifiers-window/windowUtils/src/main/java/pro/jayeshseth/windowUtils/Dimensions.kt rename to madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/Dimensions.kt index c297776..4599e22 100644 --- a/madifiers-window/windowUtils/src/main/java/pro/jayeshseth/windowUtils/Dimensions.kt +++ b/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/Dimensions.kt @@ -15,12 +15,14 @@ */ package pro.jayeshseth.windowUtils +import androidx.compose.runtime.Stable import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +@Stable data class Dimensions( - val heightInDp: Dp = 0.dp, - val widthInDp: Dp = 0.dp, - val heightInPx: Int = 0, - val widthInPx: Int = 0, + val heightInDp: Dp = 0.dp, + val widthInDp: Dp = 0.dp, + val heightInPx: Int = 0, + val widthInPx: Int = 0, ) \ No newline at end of file diff --git a/madifiers-window/windowUtils/src/main/java/pro/jayeshseth/windowUtils/WindowInfo.kt b/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/WindowInfo.kt similarity index 67% rename from madifiers-window/windowUtils/src/main/java/pro/jayeshseth/windowUtils/WindowInfo.kt rename to madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/WindowInfo.kt index c3bfaef..36f4c82 100644 --- a/madifiers-window/windowUtils/src/main/java/pro/jayeshseth/windowUtils/WindowInfo.kt +++ b/madifiers-window/windowUtils/src/commonMain/kotlin/pro/jayeshseth/windowUtils/WindowInfo.kt @@ -13,35 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:SuppressLint("ComposableNaming") - package pro.jayeshseth.windowUtils -import android.annotation.SuppressLint -import android.content.res.Configuration import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.foundation.layout.safeGestures import androidx.compose.foundation.layout.systemBars import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.LayoutDirection -import androidx.compose.ui.unit.dp /** * [ScreenDimensions] returns the screen height and width in [Dp] and Px */ -@SuppressLint("ComposableNaming") @Composable fun ScreenDimensions(): Dimensions { - val configuration = LocalConfiguration.current + val windowInfo = LocalWindowInfo.current val density = LocalDensity.current + val sizePx = windowInfo.containerSize + // Values in Dp - val heightInDp = configuration.screenHeightDp.dp - val widthInDp = configuration.screenWidthDp.dp + val heightInDp = with(density) { sizePx.height.toDp() } + val widthInDp = with(density) { sizePx.width.toDp() } // Values in Px val heightInPx = with(density) { heightInDp.roundToPx() } @@ -72,23 +66,4 @@ fun NavigationBar(): Dimensions { val sizeInPx = with(density) { navigationBarSize.roundToPx() } return Dimensions(heightInDp = navigationBarSize, heightInPx = sizeInPx) -} - -/** - * [isGestureNavigation] checks if device is using gesture navigation bar - */ -@Composable -fun isGestureNavigation(): Boolean { - val safeGesture = - WindowInsets.safeGestures.asPaddingValues().calculateLeftPadding(LayoutDirection.Ltr) - return safeGesture != 0.dp -} - -/** - * [isInLandscapeMode] checks if device is in landscape orientation - */ -@Composable -fun isInLandscapeMode(): Boolean { - val configuration = LocalConfiguration.current - return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index de17a6e..a27707a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,7 +22,7 @@ dependencyResolutionManagement { } rootProject.name = "Madifiers" -include(":app") +include(":composeApp") // add your modules here include(":madifiers-text:animateTextUnitAsState") include(":madifiers-text:bionicText")