Skip to content

Commit

Permalink
Merge pull request #38 from felipejoglar/felipejoglar/move-to-coroutines
Browse files Browse the repository at this point in the history
Move to kotlinx coroutines
  • Loading branch information
felipejoglar committed Jan 27, 2024
2 parents 85c12db + 54e4a7c commit 7d29ba0
Show file tree
Hide file tree
Showing 24 changed files with 92 additions and 73 deletions.
1 change: 0 additions & 1 deletion .idea/.name

This file was deleted.

2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
## License

```
Copyright 2022-2023 Felipe Joglar
Copyright 2022-2024 Felipe Joglar
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion apps/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ dependencies {
implementation(libs.precompose.viewmodel)

testImplementation(libs.junit)
testImplementation(libs.coroutines.test)
testImplementation(libs.kotlinx.coroutines.test)

debugImplementation(libs.androidx.compose.ui.tooling)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Felipe Joglar
* Copyright 2024 Felipe Joglar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,8 +27,8 @@ import com.taskodoro.android.app.navigation.graphs.tasks.TASK_GRAPH_ROUTE
import com.taskodoro.android.app.navigation.graphs.tasks.navigateToTaskGraph
import com.taskodoro.android.app.navigation.graphs.tasks.taskGraph
import com.taskodoro.android.app.navigation.transitions.forwardBackwardNavTransition
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import moe.tlaster.precompose.PreComposeApp
import moe.tlaster.precompose.navigation.NavHost
import moe.tlaster.precompose.navigation.NavOptions
Expand All @@ -46,8 +46,7 @@ fun AppNavigation(
val navigator = rememberNavigator()
val scope = rememberCoroutineScope()

val isOnboarded = onboardingStore.isOnboarded().getOrThrow()

val isOnboarded = runBlocking { onboardingStore.isOnboarded().getOrThrow() }
val initialRoute = if (isOnboarded) TASK_GRAPH_ROUTE else ONBOARDING_GRAPH_ROUTE

NavHost(
Expand All @@ -58,7 +57,7 @@ fun AppNavigation(
) {
onboardingGraph(
onContinueClicked = {
flowOf(onboardingStore.setOnboarded()).launchIn(scope)
scope.launch { onboardingStore.setOnboarded() }

val options = NavOptions(popUpTo = PopUpTo.First())
navigator.navigateToTaskGraph(options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class TaskNewViewModelTest {
private class TaskNewUseCaseStub : TaskNewUseCase {
private var result: Result<Unit>? = null

override fun invoke(
override suspend fun invoke(
title: String,
description: String?,
dueDate: Long?,
Expand Down
29 changes: 16 additions & 13 deletions gradle/catalogs/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ detektGradlePlugin = "1.23.1"

desugar = "2.0.4"
activity-compose = "1.8.2"
androidx-activity = "1.8.2"
androidx-splashscreen = "1.0.1"
androidx-lifecycle = "2.6.2"
androidx-activity = "1.8.2"
androidx-splashscreen = "1.0.1"
androidx-lifecycle = "2.6.2"

coil = "2.5.0"

Expand All @@ -35,12 +35,12 @@ compose-compiler = "1.5.7"

precompose = "1.5.10"

coroutines = "1.7.3"

sqlDelight = "2.0.1"
datastore = "1.1.0-alpha07"

datetime = "0.4.1"
coroutines = "1.7.3"

junit = "4.13.2"

Expand Down Expand Up @@ -81,7 +81,10 @@ sqlDelight-jvm-driver = { module = "app.cash.sqldelight:sqlite-driver", version.
datastore = { module = "androidx.datastore:datastore-preferences-core", version.ref = "datastore" }

# kotlinx datetime - https://github.com/Kotlin/kotlinx-datetime
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime"}
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }

# kotlinx coroutines - https://github.com/Kotlin/kotlinx.coroutines
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }

# JUnit - https://junit.org/junit4/
junit = { module = "junit:junit", version.ref = "junit" }
Expand All @@ -90,27 +93,27 @@ junit = { module = "junit:junit", version.ref = "junit" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test" }

# Coroutines - https://github.com/Kotlin/kotlinx.coroutines
coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }

[plugins]
# Android Gradle Plugin - https://developer.android.com/studio/releases/gradle-plugin
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }

# Kotlin Gradle Plugin - https://kotlinlang.org/docs/releases.html
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin"}
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin"}
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin"}
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin"}
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }

# SQLDelight - https://cashapp.github.io/sqldelight/multiplatform_sqlite/
sqlDelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight"}
sqlDelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" }

# Spotless - https://github.com/diffplug/spotless
spotless = { id = "com.diffplug.spotless", version.ref = "spotlessGradlePlugin"}
spotless = { id = "com.diffplug.spotless", version.ref = "spotlessGradlePlugin" }

# Detekt - https://detekt.dev/
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detektGradlePlugin"}
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detektGradlePlugin" }

[bundles]
androidx-compose = [
Expand Down
1 change: 1 addition & 0 deletions infra/preferences/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ kotlin {

commonMain.dependencies {
implementation(libs.datastore)
implementation(libs.kotlinx.coroutines)
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Felipe Joglar
* Copyright 2024 Felipe Joglar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,6 @@
package com.taskodoro.storage.preferences

interface Preferences {
fun getBoolean(key: String): Boolean
fun setBoolean(key: String, value: Boolean)
suspend fun getBoolean(key: String): Boolean
suspend fun setBoolean(key: String, value: Boolean)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Felipe Joglar
* Copyright 2024 Felipe Joglar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,20 +20,26 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import com.taskodoro.storage.preferences.Preferences
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext

internal class DataStorePreferences(
private val dataStore: DataStore<androidx.datastore.preferences.core.Preferences>,
) : Preferences {

override fun getBoolean(key: String): Boolean = runBlocking {
return@runBlocking dataStore.data.first()[booleanPreferencesKey(key)] ?: false
override suspend fun getBoolean(key: String): Boolean {
return withContext(Dispatchers.IO) {
dataStore.data.first()[booleanPreferencesKey(key)] ?: false
}
}

override fun setBoolean(key: String, value: Boolean): Unit = runBlocking {
dataStore.edit { preferences ->
preferences[booleanPreferencesKey(key)] = value
override suspend fun setBoolean(key: String, value: Boolean) {
withContext(Dispatchers.IO) {
dataStore.edit { preferences ->
preferences[booleanPreferencesKey(key)] = value
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Felipe Joglar
* Copyright 2024 Felipe Joglar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -38,11 +38,11 @@ class TestPreferences(
}
}

override fun getBoolean(key: String): Boolean {
override suspend fun getBoolean(key: String): Boolean {
return dataStorePreferences.getBoolean(key)
}

override fun setBoolean(key: String, value: Boolean) {
override suspend fun setBoolean(key: String, value: Boolean) {
dataStorePreferences.setBoolean(key, value)
}

Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencyResolutionManagement {

enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

rootProject.name = "Taskodoro_App"
rootProject.name = "taskodoro-apps"

include(":apps:android:app")
include(":taskodoro")
Expand Down
2 changes: 2 additions & 0 deletions taskodoro/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ kotlin {
implementation(projects.infra.database)
implementation(projects.infra.preferences)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.coroutines)
}

commonTest.dependencies {
implementation(libs.kotlin.test)
implementation(libs.kotlinx.coroutines.test)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ internal class PreferencesOnboardingStore(
private const val IS_ONBOARDED_KEY = "is_onboarded_key"
}

override fun isOnboarded(): Result<Boolean> {
override suspend fun isOnboarded(): Result<Boolean> {
return runCatching {
preferences.getBoolean(IS_ONBOARDED_KEY)
}
}

override fun setOnboarded(): Result<Unit> {
override suspend fun setOnboarded(): Result<Unit> {
return runCatching {
preferences.setBoolean(IS_ONBOARDED_KEY, true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
package com.taskodoro.onboarding.feature

interface OnboardingStore {
fun isOnboarded(): Result<Boolean>
fun setOnboarded(): Result<Unit>
suspend fun isOnboarded(): Result<Boolean>
suspend fun setOnboarded(): Result<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class TaskRepository(

object SaveFailed : Exception()

override fun save(task: Task): Result<Unit> =
override suspend fun save(task: Task): Result<Unit> =
try {
store.save(task)
Result.success(Unit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ package com.taskodoro.tasks.data
import com.taskodoro.tasks.feature.model.Task

interface TaskStore {
fun save(task: Task)
suspend fun save(task: Task)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,28 @@ package com.taskodoro.tasks.data.local
import com.taskodoro.storage.db.TaskodoroDB
import com.taskodoro.tasks.data.TaskStore
import com.taskodoro.tasks.feature.model.Task
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext

internal class SQLDelightTaskStore(
database: TaskodoroDB,
) : TaskStore {

internal val tasksQueries = database.localTaskQueries

override fun save(task: Task) {
tasksQueries.insert(
id = task.id.uuidString,
title = task.title,
description = task.description,
priority = task.priority.ordinal.toLong(),
completed = false,
dueDate = task.dueDate,
createdAt = task.createdAt,
updatedAt = 0,
)
override suspend fun save(task: Task) {
withContext(Dispatchers.IO) {
tasksQueries.insert(
id = task.id.uuidString,
title = task.title,
description = task.description,
priority = task.priority.ordinal.toLong(),
completed = false,
dueDate = task.dueDate,
createdAt = task.createdAt,
updatedAt = 0,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ package com.taskodoro.tasks.feature
import com.taskodoro.tasks.feature.model.Task

interface TaskSaver {
fun save(task: Task): Result<Unit>
suspend fun save(task: Task): Result<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.taskodoro.tasks.validator.TaskValidatorError
import com.taskodoro.tasks.validator.Validator

interface TaskNewUseCase {
operator fun invoke(
suspend operator fun invoke(
title: String,
description: String? = null,
dueDate: Long? = null,
Expand All @@ -35,7 +35,7 @@ class TaskNew(
private val now: () -> Long,
) : TaskNewUseCase {

override operator fun invoke(
override suspend operator fun invoke(
title: String,
description: String?,
dueDate: Long?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.taskodoro.onboarding.data

import com.taskodoro.onboarding.feature.OnboardingStore
import com.taskodoro.storage.preferences.test.TestPreferences
import kotlinx.coroutines.test.runTest
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertFalse
Expand All @@ -26,14 +27,14 @@ import kotlin.test.assertTrue
class OnboardingStoreTest {

@Test
fun isOnboarded_returnsFalseWhenNotPreviouslySet() {
fun isOnboarded_returnsFalseWhenNotPreviouslySet() = runTest {
val sut = makeSut()

assertFalse(sut.isOnboarded().getOrThrow())
}

@Test
fun setOnboarded_setsValueCorrectly() {
fun setOnboarded_setsValueCorrectly() = runTest {
val sut = makeSut()

sut.setOnboarded()
Expand Down
Loading

0 comments on commit 7d29ba0

Please sign in to comment.