Skip to content

Commit 2cfd5f7

Browse files
authored
Merge pull request #95 from Kotlin-Android-Open-Source/fix/UI_xml_format
fix(ui): wrong color in dark mode and format .xml files
2 parents 2814d42 + c7ccdf0 commit 2cfd5f7

File tree

39 files changed

+461
-442
lines changed

39 files changed

+461
-442
lines changed

.github/workflows/qodana.yml

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
name: Qodana
2-
3-
on:
4-
push:
5-
branches: [ master ]
6-
paths-ignore: [ '**.md', '**.MD' ]
7-
pull_request:
8-
branches: [ master ]
9-
paths-ignore: [ '**.md', '**.MD' ]
10-
workflow_dispatch:
11-
12-
jobs:
13-
build:
14-
runs-on: ubuntu-latest
15-
steps:
16-
- uses: actions/checkout@v2
17-
18-
- uses: JetBrains/qodana-action@v4.2.3
19-
with:
20-
linter: jetbrains/qodana-jvm-android:latest
21-
fail-threshold: 10
1+
name: Qodana
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
paths-ignore: [ '**.md', '**.MD' ]
7+
pull_request:
8+
branches: [ master ]
9+
paths-ignore: [ '**.md', '**.MD' ]
10+
workflow_dispatch:
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v2
17+
18+
- uses: JetBrains/qodana-action@v4.2.3
19+
with:
20+
linter: jetbrains/qodana-jvm-android:latest
21+
fail-threshold: 10

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
/.idea/assetWizardSettings.xml
1010
.DS_Store
1111
/build
12-
buildSrc/build
1312
/captures
1413
.externalNativeBuild
1514
.cxx
15+
local.properties
16+
**/build/

.idea/misc.xml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/release/app-release.apk

-2.5 MB
Binary file not shown.

app/src/main/java/com/hoc/flowmvi/core/CoreModule.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
44
import com.hoc.flowmvi.core_ui.navigator.Navigator
55
import org.koin.dsl.module
66

7+
@JvmField
78
val coreModule = module {
89
single<CoroutineDispatchers> { DefaultCoroutineDispatchers() }
910

buildSrc/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/build
2+
.gradle

core-ui/src/main/AndroidManifest.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
package="com.hoc.flowmvi.core_ui">
3+
package="com.hoc.flowmvi.core_ui">
44

5-
<application>
5+
<application>
66

7-
<meta-data
8-
android:name="preloaded_fonts"
9-
android:resource="@array/preloaded_fonts" />
7+
<meta-data
8+
android:name="preloaded_fonts"
9+
android:resource="@array/preloaded_fonts" />
1010

11-
</application>
11+
</application>
1212

1313
</manifest>

core-ui/src/main/java/com/hoc/flowmvi/core_ui/FlowBinding.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import androidx.appcompat.widget.SearchView
88
import androidx.core.widget.doOnTextChanged
99
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
1010
import kotlinx.coroutines.Dispatchers
11-
import kotlinx.coroutines.ExperimentalCoroutinesApi
1211
import kotlinx.coroutines.channels.awaitClose
1312
import kotlinx.coroutines.flow.Flow
1413
import kotlinx.coroutines.flow.callbackFlow
@@ -23,7 +22,6 @@ internal fun checkMainThread() {
2322
}
2423
}
2524

26-
@ExperimentalCoroutinesApi
2725
@CheckResult
2826
fun EditText.firstChange(): Flow<Unit> {
2927
return callbackFlow {
@@ -39,7 +37,6 @@ fun EditText.firstChange(): Flow<Unit> {
3937
}.take(1)
4038
}
4139

42-
@ExperimentalCoroutinesApi
4340
@CheckResult
4441
fun SwipeRefreshLayout.refreshes(): Flow<Unit> {
4542
return callbackFlow {
@@ -50,7 +47,6 @@ fun SwipeRefreshLayout.refreshes(): Flow<Unit> {
5047
}
5148
}
5249

53-
@ExperimentalCoroutinesApi
5450
@CheckResult
5551
fun View.clicks(): Flow<View> {
5652
return callbackFlow {
@@ -67,7 +63,6 @@ data class SearchViewQueryTextEvent(
6763
val isSubmitted: Boolean,
6864
)
6965

70-
@ExperimentalCoroutinesApi
7166
@CheckResult
7267
fun SearchView.queryTextEvents(): Flow<SearchViewQueryTextEvent> {
7368
return callbackFlow {
@@ -109,7 +104,6 @@ fun SearchView.queryTextEvents(): Flow<SearchViewQueryTextEvent> {
109104
}
110105
}
111106

112-
@ExperimentalCoroutinesApi
113107
@CheckResult
114108
fun EditText.textChanges(): Flow<CharSequence?> {
115109
return callbackFlow {
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
3-
app:fontProviderAuthority="com.google.android.gms.fonts"
4-
app:fontProviderPackage="com.google.android.gms"
5-
app:fontProviderQuery="Noto Sans"
6-
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
7-
</font-family>
3+
app:fontProviderAuthority="com.google.android.gms.fonts"
4+
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
5+
app:fontProviderPackage="com.google.android.gms"
6+
app:fontProviderQuery="Noto Sans"></font-family>
Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
11
<resources>
2-
<style name="AppTheme" parent="Theme.Material3.DayNight">
3-
<item name="colorPrimary">@color/md_theme_light_primary</item>
4-
<item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
5-
<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
6-
<item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
7-
<item name="colorSecondary">@color/md_theme_light_secondary</item>
8-
<item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
9-
<item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
10-
<item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
11-
<item name="colorTertiary">@color/md_theme_light_tertiary</item>
12-
<item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
13-
<item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
14-
<item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
15-
<item name="colorError">@color/md_theme_light_error</item>
16-
<item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
17-
<item name="colorOnError">@color/md_theme_light_onError</item>
18-
<item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
19-
<item name="android:colorBackground">@color/md_theme_light_background</item>
20-
<item name="colorOnBackground">@color/md_theme_light_onBackground</item>
21-
<item name="colorSurface">@color/md_theme_light_surface</item>
22-
<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
23-
<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
24-
<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
25-
<item name="colorOutline">@color/md_theme_light_outline</item>
26-
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
27-
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
28-
<item name="colorPrimaryInverse">@color/md_theme_light_primaryInverse</item>
29-
</style>
2+
3+
<style name="AppTheme" parent="Theme.Material3.DayNight">
4+
<item name="colorPrimary">@color/md_theme_light_primary</item>
5+
<item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
6+
<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
7+
<item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
8+
<item name="colorSecondary">@color/md_theme_light_secondary</item>
9+
<item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
10+
<item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
11+
<item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
12+
<item name="colorTertiary">@color/md_theme_light_tertiary</item>
13+
<item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
14+
<item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
15+
<item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
16+
<item name="colorError">@color/md_theme_light_error</item>
17+
<item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
18+
<item name="colorOnError">@color/md_theme_light_onError</item>
19+
<item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
20+
<item name="android:colorBackground">@color/md_theme_light_background</item>
21+
<item name="colorOnBackground">@color/md_theme_light_onBackground</item>
22+
<item name="colorSurface">@color/md_theme_light_surface</item>
23+
<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
24+
<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
25+
<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
26+
<item name="colorOutline">@color/md_theme_light_outline</item>
27+
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
28+
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
29+
<item name="colorPrimaryInverse">@color/md_theme_light_primaryInverse</item>
30+
</style>
3031
</resources>

core/src/main/java/com/hoc/flowmvi/core/SuspendRetry.kt

Lines changed: 0 additions & 31 deletions
This file was deleted.

data/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ dependencies {
4343
implementation(domain)
4444

4545
implementation(deps.coroutines.core)
46+
implementation(deps.flowExt)
4647

4748
implementation(deps.squareup.retrofit)
4849
implementation(deps.squareup.moshiKotlin)

data/src/main/AndroidManifest.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
package="com.hoc.flowmvi.data">
2+
<manifest package="com.hoc.flowmvi.data">
43

54
</manifest>

data/src/main/java/com/hoc/flowmvi/data/DataModule.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.squareup.moshi.Moshi
1010
import com.squareup.moshi.adapter
1111
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
1212
import kotlinx.coroutines.ExperimentalCoroutinesApi
13+
import kotlinx.coroutines.FlowPreview
1314
import okhttp3.OkHttpClient
1415
import okhttp3.logging.HttpLoggingInterceptor
1516
import okhttp3.logging.HttpLoggingInterceptor.Level
@@ -22,6 +23,8 @@ import kotlin.time.ExperimentalTime
2223

2324
val BASE_URL_QUALIFIER = named("BASE_URL")
2425

26+
@JvmField
27+
@FlowPreview
2528
@ExperimentalStdlibApi
2629
@ExperimentalTime
2730
@ExperimentalCoroutinesApi

data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@ import arrow.core.right
88
import arrow.core.valueOr
99
import com.hoc.flowmvi.core.Mapper
1010
import com.hoc.flowmvi.core.dispatchers.CoroutineDispatchers
11-
import com.hoc.flowmvi.core.retrySuspend
1211
import com.hoc.flowmvi.data.remote.UserApiService
1312
import com.hoc.flowmvi.data.remote.UserBody
1413
import com.hoc.flowmvi.data.remote.UserResponse
1514
import com.hoc.flowmvi.domain.model.User
1615
import com.hoc.flowmvi.domain.model.UserError
1716
import com.hoc.flowmvi.domain.model.UserValidationError
1817
import com.hoc.flowmvi.domain.repository.UserRepository
18+
import com.hoc081098.flowext.retryWithExponentialBackoff
1919
import kotlinx.coroutines.ExperimentalCoroutinesApi
20-
import kotlinx.coroutines.delay
20+
import kotlinx.coroutines.FlowPreview
21+
import kotlinx.coroutines.flow.Flow
2122
import kotlinx.coroutines.flow.MutableSharedFlow
23+
import kotlinx.coroutines.flow.asFlow
2224
import kotlinx.coroutines.flow.catch
23-
import kotlinx.coroutines.flow.emitAll
24-
import kotlinx.coroutines.flow.flow
25+
import kotlinx.coroutines.flow.first
26+
import kotlinx.coroutines.flow.flatMapConcat
2527
import kotlinx.coroutines.flow.map
2628
import kotlinx.coroutines.flow.onEach
2729
import kotlinx.coroutines.flow.scan
@@ -32,6 +34,7 @@ import kotlin.time.Duration.Companion.milliseconds
3234
import kotlin.time.ExperimentalTime
3335
import arrow.core.Either.Companion.catch as catchEither
3436

37+
@FlowPreview
3538
@ExperimentalTime
3639
@ExperimentalCoroutinesApi
3740
internal class UserRepositoryImpl(
@@ -65,44 +68,38 @@ internal class UserRepositoryImpl(
6568
@Suppress("NOTHING_TO_INLINE")
6669
private inline fun logError(t: Throwable, message: String) = Timber.tag(TAG).e(t, message)
6770

68-
private suspend fun getUsersFromRemote(): List<User> {
69-
return withContext(dispatchers.io) {
70-
retrySuspend(
71-
times = 3,
72-
initialDelay = 500.milliseconds,
73-
factor = 2.0,
74-
shouldRetry = { it is IOException }
75-
) { times ->
76-
Timber.d("[USER_REPO] Retry times=$times")
77-
userApiService
78-
.getUsers()
79-
.map(responseToDomainThrows)
80-
}
81-
}
82-
}
83-
84-
override fun getUsers() = flow {
85-
val initial = getUsersFromRemote()
86-
87-
changesFlow
88-
.onEach { Timber.d("[USER_REPO] Change=$it") }
89-
.scan(initial) { acc, change ->
90-
when (change) {
91-
is Change.Removed -> acc.filter { it.id != change.removed.id }
92-
is Change.Refreshed -> change.user
93-
is Change.Added -> acc + change.user
71+
private fun getUsersFromRemote(): Flow<List<User>> = suspend {
72+
Timber.d("[USER_REPO] getUsersFromRemote ...")
73+
userApiService
74+
.getUsers()
75+
.map(responseToDomainThrows)
76+
}.asFlow()
77+
.retryWithExponentialBackoff(
78+
maxAttempt = 2,
79+
initialDelay = 500.milliseconds,
80+
factor = 2.0,
81+
) { it is IOException }
82+
83+
override fun getUsers() = getUsersFromRemote()
84+
.flatMapConcat { initial ->
85+
changesFlow
86+
.onEach { Timber.d("[USER_REPO] Change=$it") }
87+
.scan(initial) { acc, change ->
88+
when (change) {
89+
is Change.Removed -> acc.filter { it.id != change.removed.id }
90+
is Change.Refreshed -> change.user
91+
is Change.Added -> acc + change.user
92+
}
9493
}
95-
}
96-
.onEach { Timber.d("[USER_REPO] Emit users.size=${it.size} ") }
97-
.let { emitAll(it) }
98-
}
94+
}
95+
.onEach { Timber.d("[USER_REPO] Emit users.size=${it.size} ") }
9996
.map { it.right().leftWiden<UserError, Nothing, List<User>>() }
10097
.catch {
10198
logError(it, "getUsers")
10299
emit(errorMapper(it).left())
103100
}
104101

105-
override suspend fun refresh() = catchEither { getUsersFromRemote() }
102+
override suspend fun refresh() = catchEither { getUsersFromRemote().first() }
106103
.tap { sendChange(Change.Refreshed(it)) }
107104
.map { }
108105
.tapLeft { logError(it, "refresh") }
@@ -131,8 +128,6 @@ internal class UserRepositoryImpl(
131128
.mapLeft(errorMapper)
132129
.bind()
133130

134-
delay(400) // TODO
135-
136131
val added = responseToDomain(response)
137132
.mapLeft { UserError.ValidationFailed(it.toSet()) }
138133
.tapInvalid { logError(it, "add user=$user") }

0 commit comments

Comments
 (0)