Skip to content

Commit

Permalink
Merge pull request #119 from choffmann/implement-category-viewmodel
Browse files Browse the repository at this point in the history
Implement Category ViewModel and refactoring
  • Loading branch information
PasclDev authored Jun 22, 2022
2 parents 8dbf77d + 67b7512 commit dbce187
Show file tree
Hide file tree
Showing 57 changed files with 1,029 additions and 634 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,8 @@ actual fun AccountIcon() {
actual fun DeleteForeverIcon() {
Icon(imageVector = Icons.Default.DeleteForever, contentDescription = null)
}

@Composable
actual fun SaveIcon() {
Icon(imageVector = Icons.Default.Save, contentDescription = null)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,52 @@
package de.hsfl.budgetBinder.common

import de.hsfl.budgetBinder.domain.usecase.NavigateToScreenUseCase
import de.hsfl.budgetBinder.presentation.Screen
import de.hsfl.budgetBinder.presentation.event.UiEvent
import de.hsfl.budgetBinder.presentation.flow.RouterFlow
import de.hsfl.budgetBinder.presentation.flow.UiEventSharedFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch

sealed class DataResponse<T>(val data: T? = null, val error: ErrorModel? = null) {
class Success<T>(data: T) : DataResponse<T>(data)
class Error<T>(error: ErrorModel?, data: T? = null) : DataResponse<T>(data, error)
class Loading<T>(data: T? = null) : DataResponse<T>(data)
class Unauthorized<T>(error: ErrorModel? = null, data: T? = null) : DataResponse<T>(data, error)
}

fun <T> DataResponse<T>.handleDataResponse(
scope: CoroutineScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()),
routerFlow: RouterFlow = RouterFlow(NavigateToScreenUseCase(), scope),
onSuccess: (T) -> Unit,
onError: ((ErrorModel) -> Unit)? = null,
onLoading: (() -> Unit)? = null,
onUnauthorized: (() -> Unit)? = null
) = scope.launch {
when (this@handleDataResponse) {
is DataResponse.Error -> {
onError?.let {
onError(this@handleDataResponse.error!!)
} ?: UiEventSharedFlow.mutableEventFlow.emit(UiEvent.ShowError(this@handleDataResponse.error!!.message))
}
is DataResponse.Loading -> {
onLoading?.let {
onLoading()
} ?: UiEventSharedFlow.mutableEventFlow.emit(UiEvent.ShowLoading)
}
is DataResponse.Success -> {
UiEventSharedFlow.mutableEventFlow.emit(UiEvent.HideSuccess)
onSuccess(this@handleDataResponse.data!!)
}
is DataResponse.Unauthorized -> {
onUnauthorized?.let {
onUnauthorized()
} ?: run {
routerFlow.navigateTo(Screen.Login)
UiEventSharedFlow.mutableEventFlow.emit(UiEvent.ShowError(this@handleDataResponse.error!!.message))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ class Client(engine: HttpClientEngine) : ApiClient {
refreshPath = "/refresh_token"
}

install(Logging) {
/*install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.HEADERS
}
}*/

defaultRequest {
url(BASE_URL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ import de.hsfl.budgetBinder.domain.usecase.storage.StoreUserStateUseCase
import de.hsfl.budgetBinder.presentation.flow.DataFlow
import de.hsfl.budgetBinder.presentation.flow.RouterFlow
import de.hsfl.budgetBinder.presentation.flow.UiEventSharedFlow
import de.hsfl.budgetBinder.presentation.viewmodel.login.LoginViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.register.RegisterViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.auth.login.LoginViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.auth.register.RegisterViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.*
import de.hsfl.budgetBinder.presentation.viewmodel.category.summary.CategorySummaryViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.category._CategoryViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.category.create.CategoryCreateViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.category.detail.CategoryDetailViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.category.edit.CategoryEditViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.dashboard.DashboardViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.navdrawer.NavDrawerViewModel
import de.hsfl.budgetBinder.presentation.viewmodel.settings.SettingsEditServerUrlViewModel
Expand Down Expand Up @@ -77,14 +82,13 @@ fun kodein(ktorEngine: HttpClientEngine) = DI {
bindSingleton { EntriesUseCases(instance(), instance(), instance(), instance(), instance()) }
bindSingleton { CategoriesUseCases(instance(), instance(), instance(), instance(), instance(), instance()) }
bindSingleton { SettingsUseCases(instance(), instance(), instance()) }
bindSingleton { LoginUseCases(instance(), instance()) }
bindSingleton { AuthUseCases(instance(), instance(), instance()) }
bindSingleton { DashboardUseCases(instance(), instance(), instance(), instance()) }
bindSingleton { RegisterUseCases(instance(), instance(), instance()) }
bindSingleton { DataFlowUseCases(instance(), instance(), instance()) }

// Flows
bindSingleton { RouterFlow(instance(), instance()) }
bindSingleton { DataFlow(instance(), instance()) }
bindSingleton { RouterFlow(instance(), instance()) }
bindSingleton { UiEventSharedFlow }

// ViewModels
Expand All @@ -93,8 +97,12 @@ fun kodein(ktorEngine: HttpClientEngine) = DI {
bindSingleton { SettingsViewModel(instance(), instance(), instance(), instance()) }
bindSingleton { SettingsEditUserViewModel(instance(), instance(), instance(), instance()) }
bindSingleton { SettingsEditServerUrlViewModel(instance(), instance(), instance()) }
bindSingleton { CategoryViewModel(instance(), instance()) }
bindSingleton { _CategoryViewModel(instance(), instance()) }
bindSingleton { CategorySummaryViewModel(instance(), instance(), instance()) }
bindSingleton { CategoryDetailViewModel(instance(), instance(), instance()) }
bindSingleton { CategoryEditViewModel(instance(), instance(), instance()) }
bindSingleton { CategoryCreateViewModel(instance(), instance(), instance()) }
bindSingleton { EntryViewModel(instance(), instance()) }
bindSingleton { DashboardViewModel(instance(), instance(), instance(), instance()) }
bindSingleton { NavDrawerViewModel(instance(), instance()) }
bindSingleton { NavDrawerViewModel(instance(), instance(), instance()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,24 @@ package de.hsfl.budgetBinder.domain.usecase

import de.hsfl.budgetBinder.common.AuthToken
import de.hsfl.budgetBinder.common.DataResponse
import de.hsfl.budgetBinder.common.ErrorModel
import de.hsfl.budgetBinder.common.User
import de.hsfl.budgetBinder.domain.repository.AuthRepository
import io.ktor.http.*
import io.ktor.utils.io.errors.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*

class RegisterUseCase(private val repository: AuthRepository) {
operator fun invoke(user: User.In): Flow<DataResponse<User>> = flow {
try {
emit(DataResponse.Loading())
repository.register(user).let { response ->
response.data?.let {
emit(DataResponse.Success(it))
} ?: response.error!!.let { error ->
when (error.code) {
HttpStatusCode.Unauthorized.value -> emit(DataResponse.Unauthorized(error))
else -> emit(DataResponse.Error(error))
}
}
}
} catch (e: IOException) {
e.printStackTrace()
emit(DataResponse.Error(ErrorModel("Couldn't reach the server")))
} catch (e: Throwable) {
e.printStackTrace()
emit(DataResponse.Error(ErrorModel("Something went wrong")))
}
useCaseHelper { repository.register(user) }
}
}

class LoginUseCase(private val repository: AuthRepository) {
operator fun invoke(email: String, password: String): Flow<DataResponse<AuthToken>> = flow {
try {
emit(DataResponse.Loading())
repository.authorize(email, password).let { response ->
response.data?.let {
emit(DataResponse.Success(it))
} ?: response.error!!.let { error ->
when (error.code) {
HttpStatusCode.Unauthorized.value -> emit(DataResponse.Unauthorized(error))
else -> emit(DataResponse.Error(error))
}
}
}
} catch (e: IOException) {
e.printStackTrace()
emit(DataResponse.Error(ErrorModel("Couldn't reach the server")))
} catch (e: Throwable) {
e.printStackTrace()
emit(DataResponse.Error(ErrorModel("Something went wrong")))
}
useCaseHelper { repository.authorize(email, password) }
}
}

class LogoutUseCase(private val repository: AuthRepository) {
operator fun invoke(onAllDevices: Boolean): Flow<DataResponse<AuthToken>> = flow {
try {
emit(DataResponse.Loading())
repository.logout(onAllDevices).let { response ->
response.data?.let {
emit(DataResponse.Success(it))
} ?: response.error!!.let { error ->
when (error.code) {
HttpStatusCode.Unauthorized.value -> emit(DataResponse.Unauthorized(error))
else -> emit(DataResponse.Error(error))
}
}
}
} catch (e: IOException) {
e.printStackTrace()
emit(DataResponse.Error(ErrorModel("Couldn't reach the server")))
} catch (e: Throwable) {
e.printStackTrace()
emit(DataResponse.Error(ErrorModel("Something went wrong")))
}
useCaseHelper { repository.logout(onAllDevices) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.hsfl.budgetBinder.domain.usecase

data class AuthUseCases(
val loginUseCase: LoginUseCase,
val getMyUserUseCase: GetMyUserUseCase,
val registerUseCase: RegisterUseCase
)
Loading

0 comments on commit dbce187

Please sign in to comment.