Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use molecule #665

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,50 @@
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.http.URLProtocol.Companion.HTTPS
import io.ktor.serialization.kotlinx.json.*

fun IosContainer(
storage: CookiesStorage
) = IosContainer(
HTTPS,
"api.todo.softwork.app",
storage
)

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