Skip to content

Commit 92711d5

Browse files
authored
Kotlin 1.8.10 and friends (#49)
* Kotlin 1.8.10 and friends * 1.9 * fix deprecated * spotless * update * update * @immutable * ưip * update * fix tests * refactor ios
1 parent b88612a commit 92711d5

File tree

33 files changed

+219
-168
lines changed

33 files changed

+219
-168
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Github Repos Search - Kotlin Multiplatform Mobile using Jetpack Compose, SwiftUI
77
[![iOS Build CI](https://github.com/hoc081098/GithubSearchKMM/actions/workflows/ios-build.yml/badge.svg)](https://github.com/hoc081098/GithubSearchKMM/actions/workflows/ios-build.yml)
88
[![Validate Gradle Wrapper](https://github.com/hoc081098/GithubSearchKMM/actions/workflows/gradle-wrapper-validation.yml/badge.svg)](https://github.com/hoc081098/GithubSearchKMM/actions/workflows/gradle-wrapper-validation.yml)
99
[![API](https://img.shields.io/badge/API-23%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=23)
10-
[![Kotlin](https://img.shields.io/badge/kotlin-1.7.20-blue.svg?logo=kotlin)](http://kotlinlang.org)
10+
[![Kotlin](https://img.shields.io/badge/kotlin-1.8.10-blue.svg?logo=kotlin)](http://kotlinlang.org)
1111
[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fhoc081098%2FGithubSearchKMM&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com)
1212
[![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](https://opensource.org/licenses/MIT)
1313
[![codecov](https://codecov.io/gh/hoc081098/GithubSearchKMM/branch/master/graph/badge.svg?token=qzSAFkj09P)](https://codecov.io/gh/hoc081098/GithubSearchKMM)

androidApp/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ android {
7070
}
7171
}
7272
}
73+
74+
packagingOptions {
75+
resources {
76+
// TODO: Remove workaround for https://github.com/Kotlin/kotlinx.coroutines/issues/3668
77+
excludes += "META-INF/versions/9/previous-compilation-data.bin"
78+
}
79+
}
7380
}
7481

7582
dependencies {
@@ -97,6 +104,7 @@ dependencies {
97104
kapt(deps.dagger.hiltAndroidCompiler)
98105

99106
// Compose
107+
implementation(platform(deps.compose.bom))
100108
implementation(deps.compose.foundation)
101109
implementation(deps.compose.foundationLayout)
102110
implementation(deps.compose.materialIconsExtended)

androidApp/src/main/java/com/hoc081098/github_search_kmm/android/rememberFlowWithLifecycle.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package com.hoc081098.github_search_kmm.android
22

33
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.LaunchedEffect
5+
import androidx.compose.runtime.Stable
6+
import androidx.compose.runtime.getValue
47
import androidx.compose.runtime.remember
8+
import androidx.compose.runtime.rememberUpdatedState
59
import androidx.compose.ui.platform.LocalLifecycleOwner
610
import androidx.lifecycle.Lifecycle
711
import androidx.lifecycle.flowWithLifecycle
12+
import androidx.lifecycle.repeatOnLifecycle
13+
import kotlinx.coroutines.Dispatchers
814
import kotlinx.coroutines.flow.Flow
15+
import kotlinx.coroutines.withContext
916

1017
@Composable
1118
fun <T> rememberFlowWithLifecycle(
@@ -18,3 +25,27 @@ fun <T> rememberFlowWithLifecycle(
1825
minActiveState = minActiveState
1926
)
2027
}
28+
29+
@Suppress("ComposableNaming")
30+
@Composable
31+
fun <T> Flow<T>.collectInLaunchedEffectWithLifecycle(
32+
vararg keys: Any?,
33+
lifecycle: Lifecycle = LocalLifecycleOwner.current.lifecycle,
34+
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
35+
collector: suspend (T) -> Unit
36+
) {
37+
val flow = this
38+
val currentCollector by rememberUpdatedState(collector)
39+
40+
LaunchedEffect(flow, lifecycle, minActiveState, *keys) {
41+
withContext(Dispatchers.Main.immediate) {
42+
lifecycle.repeatOnLifecycle(minActiveState) {
43+
flow.collect { currentCollector(it) }
44+
}
45+
}
46+
}
47+
}
48+
49+
@Stable
50+
@JvmInline
51+
value class StableWrapper<T>(val value: T)

androidApp/src/main/java/com/hoc081098/github_search_kmm/android/ui/GithubRepoItemRow.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import androidx.compose.material.icons.Icons
1515
import androidx.compose.material.icons.filled.Star
1616
import androidx.compose.material3.Card
1717
import androidx.compose.material3.CardDefaults
18-
import androidx.compose.material3.ExperimentalMaterial3Api
1918
import androidx.compose.material3.Icon
2019
import androidx.compose.material3.MaterialTheme
2120
import androidx.compose.material3.Text
@@ -32,16 +31,16 @@ import androidx.compose.ui.unit.dp
3231
import coil.compose.AsyncImage
3332
import coil.request.ImageRequest
3433
import com.hoc081098.github_search_kmm.android.R
34+
import com.hoc081098.github_search_kmm.android.StableWrapper
3535
import com.hoc081098.github_search_kmm.android.core_ui.fromArgbColor
3636
import com.hoc081098.github_search_kmm.domain.model.RepoItem
3737
import java.text.DecimalFormat
3838

39-
@OptIn(ExperimentalMaterial3Api::class)
4039
@Composable
4140
fun GithubRepoItemRow(
42-
modifier: Modifier = Modifier,
4341
item: RepoItem,
44-
decimalFormat: DecimalFormat,
42+
decimalFormat: StableWrapper<DecimalFormat>,
43+
modifier: Modifier = Modifier,
4544
) {
4645
Card(
4746
modifier = modifier,
@@ -127,7 +126,7 @@ fun GithubRepoItemRow(
127126
)
128127

129128
Text(
130-
text = decimalFormat.format(item.starCount),
129+
text = decimalFormat.value.format(item.starCount),
131130
style = MaterialTheme.typography.bodyMedium
132131
)
133132
}

androidApp/src/main/java/com/hoc081098/github_search_kmm/android/ui/GithubRepoItemsList.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import androidx.compose.ui.Modifier
1717
import androidx.compose.ui.unit.dp
1818
import com.hoc081098.flowext.ThrottleConfiguration
1919
import com.hoc081098.flowext.throttleTime
20+
import com.hoc081098.github_search_kmm.android.StableWrapper
2021
import com.hoc081098.github_search_kmm.android.core_ui.LoadingIndicator
2122
import com.hoc081098.github_search_kmm.android.core_ui.RetryButton
2223
import com.hoc081098.github_search_kmm.android.getReadableMessage
@@ -66,7 +67,7 @@ internal fun GithubRepoItemsList(
6667
}
6768
}
6869

69-
val decimalFormat = remember { DecimalFormat("#,###") }
70+
val decimalFormat = remember { StableWrapper(DecimalFormat("#,###")) }
7071

7172
LazyColumn(
7273
modifier = Modifier

androidApp/src/main/java/com/hoc081098/github_search_kmm/android/ui/GithubRepoItemsSearchScreen.kt

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.BoxWithConstraints
55
import androidx.compose.foundation.layout.Column
66
import androidx.compose.foundation.layout.ExperimentalLayoutApi
7-
import androidx.compose.foundation.layout.consumedWindowInsets
7+
import androidx.compose.foundation.layout.consumeWindowInsets
88
import androidx.compose.foundation.layout.fillMaxSize
99
import androidx.compose.foundation.layout.fillMaxWidth
1010
import androidx.compose.foundation.layout.padding
@@ -18,25 +18,24 @@ import androidx.compose.material3.SnackbarHost
1818
import androidx.compose.material3.SnackbarHostState
1919
import androidx.compose.material3.Text
2020
import androidx.compose.runtime.Composable
21-
import androidx.compose.runtime.LaunchedEffect
2221
import androidx.compose.runtime.getValue
2322
import androidx.compose.runtime.remember
23+
import androidx.compose.runtime.rememberCoroutineScope
2424
import androidx.compose.ui.Alignment
2525
import androidx.compose.ui.Modifier
2626
import androidx.compose.ui.platform.LocalContext
2727
import androidx.compose.ui.res.stringResource
2828
import androidx.compose.ui.tooling.preview.Preview
2929
import androidx.compose.ui.unit.dp
3030
import androidx.hilt.navigation.compose.hiltViewModel
31-
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
3231
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3332
import com.hoc081098.github_search_kmm.android.R
33+
import com.hoc081098.github_search_kmm.android.collectInLaunchedEffectWithLifecycle
3434
import com.hoc081098.github_search_kmm.android.core_ui.AppBackground
3535
import com.hoc081098.github_search_kmm.android.core_ui.AppTheme
3636
import com.hoc081098.github_search_kmm.android.core_ui.LoadingIndicator
3737
import com.hoc081098.github_search_kmm.android.core_ui.RetryButton
3838
import com.hoc081098.github_search_kmm.android.getReadableMessage
39-
import com.hoc081098.github_search_kmm.android.rememberFlowWithLifecycle
4039
import com.hoc081098.github_search_kmm.domain.model.Owner
4140
import com.hoc081098.github_search_kmm.domain.model.RepoItem
4241
import com.hoc081098.github_search_kmm.presentation.DaggerGithubSearchViewModel
@@ -51,34 +50,31 @@ import kotlinx.datetime.Clock
5150
@OptIn(
5251
ExperimentalMaterial3Api::class,
5352
ExperimentalLayoutApi::class,
54-
ExperimentalLifecycleComposeApi::class
5553
)
5654
@Composable
5755
fun GithubRepoItemsSearchScreen(
5856
vm: DaggerGithubSearchViewModel = hiltViewModel()
5957
) {
60-
val eventFlow = rememberFlowWithLifecycle(flow = vm.eventFlow)
6158
val snackbarHostState = remember { SnackbarHostState() }
6259
val context = LocalContext.current
60+
val scope = rememberCoroutineScope()
6361

64-
LaunchedEffect(eventFlow, snackbarHostState) {
65-
eventFlow.collect { event ->
66-
when (event) {
67-
is GithubSearchSingleEvent.SearchFailure -> {
68-
launch {
69-
snackbarHostState.showSnackbar(
70-
event
71-
.appError
72-
.getReadableMessage(context)
73-
)
74-
}
62+
vm.eventFlow.collectInLaunchedEffectWithLifecycle { event ->
63+
when (event) {
64+
is GithubSearchSingleEvent.SearchFailure -> {
65+
scope.launch {
66+
snackbarHostState.showSnackbar(
67+
event
68+
.appError
69+
.getReadableMessage(context)
70+
)
7571
}
76-
GithubSearchSingleEvent.ReachedMaxItems -> {
77-
launch {
78-
snackbarHostState.showSnackbar(
79-
context.getString(R.string.loaded_all_items)
80-
)
81-
}
72+
}
73+
GithubSearchSingleEvent.ReachedMaxItems -> {
74+
scope.launch {
75+
snackbarHostState.showSnackbar(
76+
context.getString(R.string.loaded_all_items)
77+
)
8278
}
8379
}
8480
}
@@ -107,7 +103,7 @@ fun GithubRepoItemsSearchScreen(
107103
BoxWithConstraints(
108104
modifier = Modifier
109105
.padding(innerPadding)
110-
.consumedWindowInsets(innerPadding)
106+
.consumeWindowInsets(innerPadding)
111107
) {
112108
Column(
113109
horizontalAlignment = Alignment.CenterHorizontally,
@@ -190,9 +186,6 @@ internal fun GithubRepoItemsSearchContent(
190186
}
191187

192188
@Preview(name = "phone", device = "spec:shape=Normal,width=360,height=640,unit=dp,dpi=480")
193-
// @Preview(name = "landscape", device = "spec:shape=Normal,width=640,height=360,unit=dp,dpi=480")
194-
// @Preview(name = "foldable", device = "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480")
195-
// @Preview(name = "tablet", device = "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=480")
196189
@Composable
197190
fun SearchScreenContentPreview() {
198191
AppTheme {

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ buildscript {
2828
}
2929

3030
plugins {
31-
id("com.google.devtools.ksp") version "1.7.20-1.0.8" apply false
32-
id("com.codingfeline.buildkonfig") version "0.13.3" apply false
31+
googleKsp version versions.googleKsp apply false
32+
buildKonfig version versions.buildKonfig apply false
3333
}
3434

3535
allprojects {
34 Bytes
Binary file not shown.
34 Bytes
Binary file not shown.

buildSrc/src/main/kotlin/deps.kt

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import org.gradle.plugin.use.PluginDependencySpec
1010
object versions {
1111
const val spotless = "6.7.2"
1212
const val ktlint = "0.45.2"
13-
const val kotlin = "1.7.20"
13+
const val kotlin = "1.8.10"
1414
const val agp = "7.3.0"
1515
const val gradleVersions = "0.42.0"
16-
const val mokoKSwift = "0.6.0"
16+
const val mokoKSwift = "0.6.1"
17+
const val googleKsp = "1.8.10-1.0.9"
18+
const val buildKonfig = "0.13.3"
1719
}
1820

1921
object appConfig {
@@ -34,15 +36,15 @@ object appConfig {
3436

3537
object deps {
3638
object androidx {
37-
const val appCompat = "androidx.appcompat:appcompat:1.5.1"
39+
const val appCompat = "androidx.appcompat:appcompat:1.6.1"
3840
const val coreKtx = "androidx.core:core-ktx:1.9.0"
39-
const val material = "com.google.android.material:material:1.6.1"
40-
const val activityCompose = "androidx.activity:activity-compose:1.6.0"
41+
const val material = "com.google.android.material:material:1.8.0"
42+
const val activityCompose = "androidx.activity:activity-compose:1.7.0"
4143
const val hiltNavigationCompose = "androidx.hilt:hilt-navigation-compose:1.0.0"
4244
}
4345

4446
object lifecycle {
45-
private const val version = "2.6.0-alpha02"
47+
private const val version = "2.6.1"
4648

4749
const val viewModelKtx = "androidx.lifecycle:lifecycle-viewmodel-ktx:$version" // viewModelScope
4850
const val runtimeKtx = "androidx.lifecycle:lifecycle-runtime-ktx:$version" // lifecycleScope
@@ -59,7 +61,7 @@ object deps {
5961
}
6062

6163
object coroutines {
62-
private const val version = "1.6.4"
64+
private const val version = "1.7.0-Beta"
6365

6466
const val core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version"
6567
const val android = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version"
@@ -73,7 +75,7 @@ object deps {
7375
}
7476

7577
object ktor {
76-
private const val version = "2.1.2"
78+
private const val version = "2.2.4"
7779
const val core = "io.ktor:ktor-client-core:$version"
7880
const val clientJson = "io.ktor:ktor-client-json:$version"
7981
const val logging = "io.ktor:ktor-client-logging:$version"
@@ -86,49 +88,54 @@ object deps {
8688
}
8789

8890
object compose {
89-
const val androidxComposeCompilerVersion = "1.3.2"
90-
private const val version = "1.3.0-beta03"
91-
private const val androidxComposeMaterial3Version = "1.0.0-beta03"
91+
const val androidxComposeCompilerVersion = "1.4.4"
92+
const val bom = "androidx.compose:compose-bom:2023.04.00"
9293

93-
const val foundation = "androidx.compose.foundation:foundation:$version"
94-
const val foundationLayout = "androidx.compose.foundation:foundation-layout:$version"
94+
const val foundation = "androidx.compose.foundation:foundation"
95+
const val foundationLayout = "androidx.compose.foundation:foundation-layout"
9596

96-
const val materialIconsExtended = "androidx.compose.material:material-icons-extended:$version"
97-
const val material3 = "androidx.compose.material3:material3:$androidxComposeMaterial3Version"
98-
const val material3WindowSizeClass = "androidx.compose.material3:material3-window-size-class:$androidxComposeMaterial3Version"
97+
const val materialIconsExtended = "androidx.compose.material:material-icons-extended"
98+
const val material3 = "androidx.compose.material3:material3"
99+
const val material3WindowSizeClass = "androidx.compose.material3:material3-window-size-class"
99100

100-
const val runtime = "androidx.compose.runtime:runtime:$version"
101+
const val runtime = "androidx.compose.runtime:runtime"
101102

102-
const val uiTooling = "androidx.compose.ui:ui-tooling:$version"
103-
const val uiToolingPreview = "androidx.compose.ui:ui-tooling-preview:$version"
104-
const val uiUtil = "androidx.compose.ui:ui-util:$version"
103+
const val uiTooling = "androidx.compose.ui:ui-tooling"
104+
const val uiToolingPreview = "androidx.compose.ui:ui-tooling-preview"
105+
const val uiUtil = "androidx.compose.ui:ui-util"
105106
}
106107

107108
object koin {
108-
private const val version = "3.2.2"
109+
private const val version = "3.4.0"
109110

110111
const val core = "io.insert-koin:koin-core:$version"
111112
const val testJunit4 = "io.insert-koin:koin-test-junit4:$version"
112113
const val test = "io.insert-koin:koin-test:$version"
113114
}
114115

115116
object dagger {
116-
const val version = "2.44"
117+
const val version = "2.45"
117118
const val hiltAndroid = "com.google.dagger:hilt-android:$version"
118119
const val hiltAndroidCompiler = "com.google.dagger:hilt-android-compiler:$version"
119120
}
120121

122+
object kmpViewModel {
123+
private const val version = "0.4.0"
124+
const val core = "io.github.hoc081098:kmp-viewmodel:$version"
125+
const val savedState = "io.github.hoc081098:kmp-viewmodel-savedstate:$version"
126+
}
127+
121128
const val mokoKSwiftRuntime = "dev.icerock.moko:kswift-runtime:${versions.mokoKSwift}"
122129
const val dateTime = "org.jetbrains.kotlinx:kotlinx-datetime:0.4.0"
123130

124-
const val coilCompose = "io.coil-kt:coil-compose:2.2.2"
125-
const val flowExt = "io.github.hoc081098:FlowExt:0.4.0"
131+
const val coilCompose = "io.coil-kt:coil-compose:2.3.0"
132+
const val flowExt = "io.github.hoc081098:FlowExt:0.6.0"
126133

127134
const val atomicfu = "org.jetbrains.kotlinx:atomicfu:0.18.3"
128135
const val immutableCollections = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5"
129136

130137
object arrow {
131-
private const val version = "1.1.3"
138+
private const val version = "1.2.0-RC"
132139
const val core = "io.arrow-kt:arrow-core:$version"
133140
const val fx = "io.arrow-kt:arrow-fx-coroutines:$version"
134141
}
@@ -148,9 +155,9 @@ object deps {
148155
}
149156
}
150157

151-
const val mockative = "io.mockative:mockative:1.2.3"
152-
const val mockativeProcessor = "io.mockative:mockative-processor:1.2.3"
153-
const val turbine = "app.cash.turbine:turbine:0.12.0"
158+
const val mockative = "io.mockative:mockative:1.4.0"
159+
const val mockativeProcessor = "io.mockative:mockative-processor:1.4.0"
160+
const val turbine = "app.cash.turbine:turbine:0.12.3"
154161
}
155162
}
156163

@@ -168,6 +175,8 @@ inline val PDsS.kotlinMultiplatform: PDS get() = kotlin("multiplatform")
168175
inline val PDsS.kotlinNativeCocoapods: PDS get() = kotlin("native.cocoapods")
169176
inline val PDsS.daggerHiltAndroid: PDS get() = id("dagger.hilt.android.plugin")
170177
inline val PDsS.mokoKSwift: PDS get() = id("dev.icerock.moko.kswift")
178+
inline val PDsS.googleKsp: PDS get() = id("com.google.devtools.ksp")
179+
inline val PDsS.buildKonfig: PDS get() = id("com.codingfeline.buildkonfig")
171180

172181
inline val DependencyHandler.shared get() = project(":shared")
173182
inline val DependencyHandler.flowRedux get() = project(":flowredux")

0 commit comments

Comments
 (0)