Skip to content

Commit

Permalink
Use molecule
Browse files Browse the repository at this point in the history
  • Loading branch information
hfhbd committed Nov 13, 2022
1 parent 696642b commit d6dee77
Show file tree
Hide file tree
Showing 32 changed files with 423 additions and 319 deletions.
45 changes: 0 additions & 45 deletions androidApp/src/main/kotlin/app/softwork/composetodo/Container.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,43 @@ package app.softwork.composetodo
import android.os.*
import androidx.activity.*
import androidx.activity.compose.*
import app.cash.sqldelight.driver.android.*
import app.softwork.composetodo.repository.*
import io.ktor.client.*
import io.ktor.client.engine.android.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.resources.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*

class MainActivity : ComponentActivity() {

private val client = HttpClient(Android) {
defaultRequest {
url {
protocol = URLProtocol.HTTPS
host = "api.todo.softwork.app"
}
}
install(Resources)
install(ContentNegotiation) {
json()
}
}

private val db = TodoRepository.createDatabase(
AndroidSqliteDriver(
ComposeTodoDB.Schema,
applicationContext,
"composetodo.db"
)
)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val appContainer = Container(applicationContext)

val appContainer = AppContainer(client, db)

setContent {
MainView(appContainer)
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugins {
id("io.gitlab.arturbosch.detekt") version "1.21.0"
}

// https://issuetracker.google.com/issues/240445963
buildscript {
dependencies {
classpath("org.apache.commons:commons-compress:1.22")
Expand Down
37 changes: 34 additions & 3 deletions clients/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ kotlin {
config()
}

watchosArm64 {
config()
}
watchosSimulatorArm64 {
config()
}

js(IR) {
browser()
}
Expand All @@ -51,7 +58,7 @@ kotlin {
dependencies {
api(projects.shared)
implementation("app.cash.sqldelight:coroutines-extensions:$sqlDelight")

api("app.cash.molecule:molecule-runtime:0.6.0")
api("io.ktor:ktor-client-logging:$ktor")
}
}
Expand All @@ -70,21 +77,45 @@ kotlin {
}
}

val iosArm64Main by getting {
val darwinMain by creating {
dependsOn(commonMain.get())
dependencies {
implementation("io.ktor:ktor-client-darwin:$ktor")
implementation("app.cash.sqldelight:native-driver:$sqlDelight")
}
}
val darwinTest by creating {
dependsOn(commonTest.get())
}

val iosArm64Main by getting {
dependsOn(darwinMain)
}
val iosSimulatorArm64Main by getting {
dependsOn(iosArm64Main)
}

val iosArm64Test by getting
val iosArm64Test by getting {
dependsOn(darwinTest)
}

val iosSimulatorArm64Test by getting {
dependsOn(iosArm64Test)
}

val watchosArm64Main by getting {
dependsOn(darwinMain)
}
val watchosArm64Test by getting {
dependsOn(darwinTest)
}
val watchosSimulatorArm64Main by getting {
dependsOn(darwinMain)
}
val watchosSimulatorArm64Test by getting {
dependsOn(darwinTest)
}

val jsMain by getting {
dependencies {
api("app.cash.sqldelight:sqljs-driver:$sqlDelight")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,49 @@
package app.softwork.composetodo

import app.softwork.composetodo.repository.*
import app.softwork.composetodo.viewmodels.*
import io.ktor.client.*
import io.ktor.utils.io.errors.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

interface AppContainer {
fun todoViewModel(api: API.LoggedIn): TodoViewModel
fun loginViewModel(api: API.LoggedOut): LoginViewModel
fun registerViewModel(api: API.LoggedOut): RegisterViewModel
class AppContainer(
val client: HttpClient,
val db: ComposeTodoDB
) : ViewModel() {

val client: HttpClient
fun todoViewModel(): TodoViewModel {
val api = api.value as API.LoggedIn
return TodoViewModel(TodoRepository(api, db.todoQueries))
}
fun loginViewModel(): LoginViewModel {
val api = api.value as API.LoggedOut
return LoginViewModel(api) {
this.api.value = it
}
}
fun registerViewModel(): RegisterViewModel {
val api = api.value as API.LoggedOut
return RegisterViewModel(api) {
this.api.value = it
}
}

suspend fun logout() {
when (val login = api.value) {
is API.LoggedIn -> {
try {
login.logout()
} catch (_: IOException) {
fun logout() {
lifecycleScope.launch {
when (val login = api.value) {
is API.LoggedIn -> {
try {
login.logout()
} catch (_: IOException) {
}
api.value = API.LoggedOut(client)
}
api.value = API.LoggedOut(client)

is API.LoggedOut -> {}
}
is API.LoggedOut -> {}
}
}

val api: MutableStateFlow<API>
val api: MutableStateFlow<API> = MutableStateFlow(API.LoggedOut(client))
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package app.softwork.composetodo.viewmodels

import androidx.compose.runtime.*
import app.cash.molecule.*
import app.softwork.composetodo.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
Expand All @@ -8,27 +10,54 @@ class LoginViewModel(
private val api: API.LoggedOut,
private val onLogin: (API.LoggedIn) -> Unit
) : ViewModel() {
val userName = MutableStateFlow("")
val password = MutableStateFlow("")
data class LoginState(
val username: String,
val password: String,
val enableLogin: Boolean,
val error: Failure?
)

val error = MutableStateFlow<Failure?>(null)
private var username by mutableStateOf("")
fun updateUsername(new: String) {
username = new
}

private var password by mutableStateOf("")
fun updatePassword(new: String) {
password = new
}

private var error by mutableStateOf<Failure?>(null)
fun dismissError() {
error = null
}

fun state(
coroutineScope: CoroutineScope,
clock: RecompositionClock = RecompositionClock.ContextClock
): StateFlow<LoginState> = coroutineScope.launchMolecule(clock) {
val isError = username.isNotEmpty() && password.isNotEmpty()

val enableLogin = userName.combine(password) { userName, password ->
userName.isNotEmpty() && password.isNotEmpty()
LoginState(
username = username,
password = password,
enableLogin = isError,
error = error
)
}

fun login() {
error.value = null
error = null
lifecycleScope.launch {
api.networkCall(
action = {
login(username = userName.value, password = password.value)
login(username = username, password = password)
}, onSuccess = {
error.value = null
error = null
onLogin(it)
}
) {
error.value = it
error = it
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package app.softwork.composetodo

import app.cash.sqldelight.driver.native.*
import app.softwork.composetodo.repository.*
import io.ktor.client.*
import io.ktor.client.engine.darwin.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.cookies.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.plugins.resources.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*

fun IosContainer(
protocol: URLProtocol,
host: String,
storage: CookiesStorage
): AppContainer {
val client = HttpClient(Darwin) {
install(HttpCookies) {
this.storage = storage
}
install(DefaultRequest) {
url {
this.protocol = protocol
this.host = host
}
}
install(Logging) {
level = LogLevel.ALL
}
install(Resources)
install(ContentNegotiation) {
json()
}
}
val db = TodoRepository.createDatabase(NativeSqliteDriver(ComposeTodoDB.Schema, "composetodo.db"))

return AppContainer(client, db)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package app.softwork.composetodo.viewmodels
import kotlinx.coroutines.*

actual abstract class ViewModel actual constructor() {
val lifecycleScope = MainScope()
val lifecycleScope = CoroutineScope(Dispatchers.Default)
}

actual val ViewModel.lifecycleScope: CoroutineScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package app.softwork.composetodo.viewmodels
import kotlinx.coroutines.*

actual abstract class ViewModel actual constructor() {
val lifecycleScope: CoroutineScope = MainScope()
val lifecycleScope = CoroutineScope(Dispatchers.Default)
}

actual val ViewModel.lifecycleScope: CoroutineScope
Expand Down
Loading

0 comments on commit d6dee77

Please sign in to comment.