Skip to content

Commit

Permalink
For touchlab#305 - Use Compose Multiplatform to show the UI from :sha…
Browse files Browse the repository at this point in the history
…red on Android

Added moko-resources as the community preferred approach to using strings in
similar scenarios.
Added the materialIconsExtended dependency for :shared instead of reusing the
vector images shown previously from :app since those vectors are not in a
format moko-resources supports at this moment (though it support SVGs). While
this is a big package R8 will ensure unused resources are stripped from the
generated builds at compile time.
  • Loading branch information
Mugurell committed Jul 21, 2023
1 parent 87166b0 commit c0f6928
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.isSystemInDarkTheme
import co.touchlab.kampkit.android.ui.MainScreen
import co.touchlab.kampkit.ui.MainScreen
import co.touchlab.kampkit.ui.theme.KaMPKitTheme
import co.touchlab.kampkit.injectLogger
import co.touchlab.kampkit.models.BreedViewModel
Expand Down
9 changes: 0 additions & 9 deletions app/src/main/res/drawable/ic_favorite_24px.xml

This file was deleted.

9 changes: 0 additions & 9 deletions app/src/main/res/drawable/ic_favorite_border_24px.xml

This file was deleted.

3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
plugins {
alias(libs.plugins.gradleVersions)
alias(libs.plugins.ktlint) apply false
alias(libs.plugins.moko.resources) apply false

kotlin("multiplatform") version libs.versions.kotlin.get() apply false
kotlin("plugin.serialization") version libs.versions.kotlin.get() apply false
Expand All @@ -18,13 +19,15 @@ allprojects {
mavenCentral()
maven("https://androidx.dev/storage/compose-compiler/repository/")
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/")
gradlePluginPortal() // for moko
}
}

subprojects {
// TODO libs doesn't resolve if we do this
// apply(plugin = libs.plugins.ktlint.get().pluginId)
apply(plugin = "org.jlleitschuh.gradle.ktlint")
apply(plugin = "dev.icerock.mobile.multiplatform-resources")

configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
enableExperimentalRules.set(true)
Expand Down
8 changes: 8 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ multiplatformSettings = "1.0.0"
turbine = "1.0.0"
sqlDelight = "2.0.0-rc01"

moko-resources = "0.23.0"
moko-graphics = "0.9.0"

[libraries]
android-desugaring = { module = "com.android.tools:desugar_jdk_libs", version.ref = "android-desugaring" }
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
Expand Down Expand Up @@ -87,9 +90,14 @@ touchlab-kermit-simple = { module = "co.touchlab:kermit-simple", version.ref = "
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }

moko-resources = { module = "dev.icerock.moko:resources", version.ref = "moko-resources" }
moko-resources-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "moko-resources" }
moko-graphics = { module = "dev.icerock.moko:graphics", version.ref = "moko-graphics" }

[plugins]
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-gradle" }
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradle-versions" }
moko-resources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko-resources" }

[bundles]
app-ui = [
Expand Down
16 changes: 16 additions & 0 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,18 @@ kotlin {
dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material) // for PullRefreshIndicator
implementation(compose.material3)
implementation(compose.materialIconsExtended)
implementation(libs.koin.core)
implementation(libs.coroutines.core)
implementation(libs.sqlDelight.coroutinesExt)
implementation(libs.bundles.ktor.common)
implementation(libs.multiplatformSettings.common)
implementation(libs.kotlinx.dateTime)
api(libs.touchlab.kermit)
api(libs.moko.resources)
api(libs.moko.resources.compose)
}
}
val commonTest by getting {
Expand All @@ -65,6 +69,8 @@ kotlin {
}
}
val androidMain by getting {
// Below line adds a temporary workaround for https://github.com/icerockdev/moko-resources/issues/531
kotlin.srcDirs("build/generated/moko/androidMain/src")
dependencies {
implementation(libs.compose.activity)
implementation(libs.androidx.lifecycle.viewmodel)
Expand All @@ -78,6 +84,7 @@ kotlin {
}
}
val iosMain by getting {
resources.srcDirs("build/generated/moko/iosMain/src")
dependencies {
implementation(libs.sqlDelight.native)
implementation(libs.ktor.client.ios)
Expand All @@ -86,6 +93,7 @@ kotlin {
}
val iosTest by getting
val iosSimulatorArm64Main by getting {
resources.srcDirs("build/generated/moko/iosSimulatorArm64Main/src")
dependsOn(iosMain)
}
val iosSimulatorArm64Test by getting {
Expand All @@ -105,6 +113,8 @@ kotlin {
isStatic = false // SwiftUI preview requires dynamic framework
linkerOpts("-lsqlite3")
export(libs.touchlab.kermit.simple)
export(libs.moko.resources)
export(libs.moko.graphics)
}
ios.deploymentTarget = "14.0"
podfile = project.file("../ios/Podfile")
Expand All @@ -123,3 +133,9 @@ sqldelight {
packageName.set("co.touchlab.kampkit.db")
}
}

multiplatformResources {
multiplatformResourcesPackage = "co.touchlab.kampkit" // required
// multiplatformResourcesSourceSet = "iosSimulatorArm64Main"
multiplatformResourcesClassName = "MR" // optional, default MR
}
24 changes: 24 additions & 0 deletions shared/src/androidMain/kotlin/co/touchlab/kampkit/utils/Strings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package co.touchlab.kampkit.utils

import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.desc.Resource
import dev.icerock.moko.resources.desc.StringDesc
import dev.icerock.moko.resources.format

actual class Strings(private val context: Context) {
actual fun get(id: StringResource, args: List<Any>): String {
return when (args.isEmpty()) {
true -> StringDesc.Resource(id).toString(context)
false -> id.format(*args.toTypedArray()).toString(context)
}
}
}

/**
* Get a string existing in the shared module.
*/
@Composable
fun getString(id: StringResource, vararg args: Any) = Strings(LocalContext.current).get(id, args.toList())
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.touchlab.kampkit.android.ui
package co.touchlab.kampkit.ui

import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.FastOutSlowInEasing
Expand All @@ -20,33 +20,34 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.touchlab.kampkit.android.R
import co.touchlab.kampkit.MR
import co.touchlab.kampkit.db.Breed
import co.touchlab.kampkit.models.BreedViewModel
import co.touchlab.kampkit.models.BreedViewState
import co.touchlab.kermit.Logger
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.launch

@Composable
fun MainScreen(
viewModel: BreedViewModel,
log: Logger
) {
val dogsState by viewModel.breedState.collectAsStateWithLifecycle()
val dogsState by viewModel.breedState.collectAsState()
val scope = rememberCoroutineScope()

MainScreenContent(
Expand Down Expand Up @@ -106,7 +107,7 @@ fun Empty() {
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(stringResource(R.string.empty_breeds))
Text(text = stringResource(MR.strings.empty_breeds))
}
}

Expand Down Expand Up @@ -166,27 +167,14 @@ fun FavoriteIcon(breed: Breed) {
) { fav ->
if (fav) {
Image(
painter = painterResource(id = R.drawable.ic_favorite_border_24px),
contentDescription = stringResource(R.string.favorite_breed, breed.name)
imageVector = Icons.Default.FavoriteBorder,
contentDescription = stringResource(MR.strings.favorite_breed, breed.name)
)
} else {
Image(
painter = painterResource(id = R.drawable.ic_favorite_24px),
contentDescription = stringResource(R.string.unfavorite_breed, breed.name)
imageVector = Icons.Default.Favorite,
contentDescription = stringResource(MR.strings.unfavorite_breed, breed.name)
)
}
}
}

@Preview
@Composable
fun MainScreenContentPreview_Success() {
MainScreenContent(
dogsState = BreedViewState(
breeds = listOf(
Breed(0, "appenzeller", false),
Breed(1, "australian", true)
)
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package co.touchlab.kampkit.utils

import dev.icerock.moko.resources.StringResource

expect class Strings {
fun get(id: StringResource, args: List<Any>): String
}
7 changes: 7 additions & 0 deletions shared/src/commonMain/resources/MR/base/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="app_name">KaMP Kit</string>
<string name="favorite_breed">Favorite %1$s</string>
<string name="unfavorite_breed">Unfavorite %1$s</string>
<string name="empty_breeds">Sorry, no doggos found</string>
</resources>
13 changes: 13 additions & 0 deletions shared/src/iosMain/kotlin/co/touchlab/kampkit/utils/Strings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package co.touchlab.kampkit.utils

import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.desc.Resource
import dev.icerock.moko.resources.desc.StringDesc
import dev.icerock.moko.resources.format

actual class Strings {
actual fun get(id: StringResource, args: List<Any>) = when (args.isEmpty()) {
true -> StringDesc.Resource(id).localized()
false -> id.format(*args.toTypedArray()).localized()
}
}

0 comments on commit c0f6928

Please sign in to comment.