Skip to content

Commit

Permalink
Migrated client functionalities to use the OMH Task abstraction. (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anwera64 committed Jun 21, 2023
1 parent fec0598 commit 9e89281
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package com.omh.android.storage.api

import com.omh.android.auth.api.OmhAuthClient
import com.omh.android.auth.api.async.OmhTask
import com.omh.android.storage.api.async.OmhStorageTaskImpl
import com.omh.android.storage.api.domain.repository.OmhFileRepository
import com.omh.android.storage.api.domain.usecase.CreateFileUseCase
import com.omh.android.storage.api.domain.usecase.CreateFileUseCaseParams
import com.omh.android.storage.api.domain.usecase.CreateFileUseCaseResult
import com.omh.android.storage.api.domain.usecase.DeleteFileUseCase
import com.omh.android.storage.api.domain.usecase.DeleteFileUseCaseParams
import com.omh.android.storage.api.domain.usecase.DeleteFileUseCaseResult
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCase
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCaseParams
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCaseResult
import com.omh.android.storage.api.domain.usecase.OmhResult

abstract class OmhStorageClient protected constructor(
protected val authClient: OmhAuthClient
Expand All @@ -17,15 +26,34 @@ abstract class OmhStorageClient protected constructor(

protected abstract fun getRepository(): OmhFileRepository

/*
* TODO: This must return an asynchronous task that can be executed with any library
* capable to manage this. In the future, this task must be implemented from auth
* and will not return an use case
*/
@SuppressWarnings("ForbiddenComment")
fun listFiles() = GetFilesListUseCase(getRepository())
fun listFiles(parentId: String): OmhTask<GetFilesListUseCaseResult> {
val getFilesListUseCase = GetFilesListUseCase(getRepository())
return OmhStorageTaskImpl {
val parameters = GetFilesListUseCaseParams(parentId)
val result: OmhResult<GetFilesListUseCaseResult> = getFilesListUseCase(parameters)
result
}
}

fun createFile() = CreateFileUseCase(getRepository())
fun createFile(
name: String,
mimeType: String,
parentId: String
): OmhTask<CreateFileUseCaseResult> {
val createFileUseCase = CreateFileUseCase(getRepository())
return OmhStorageTaskImpl {
val parameters = CreateFileUseCaseParams(name, mimeType, parentId)
val result: OmhResult<CreateFileUseCaseResult> = createFileUseCase(parameters)
result
}
}

fun deleteFile() = DeleteFileUseCase(getRepository())
fun deleteFile(id: String): OmhTask<DeleteFileUseCaseResult> {
val deleteFileUseCase = DeleteFileUseCase(getRepository())
return OmhStorageTaskImpl {
val parameters = DeleteFileUseCaseParams(id)
val result = deleteFileUseCase(parameters)
result
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.omh.android.storage.api.async

import com.omh.android.auth.api.async.OmhCancellable
import com.omh.android.auth.api.async.OmhTask
import com.omh.android.storage.api.domain.usecase.OmhResult
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

internal class OmhStorageTaskImpl<T>(private val task: suspend () -> OmhResult<T>) : OmhTask<T>() {

private val coroutineContext = Dispatchers.Main + SupervisorJob()
private val customScope: CoroutineScope = CoroutineScope(context = coroutineContext)

override fun execute(): OmhCancellable {
customScope.launch {
executeScopedTask()
}
return OmhCancellable { coroutineContext.cancelChildren() }
}

@SuppressWarnings("TooGenericExceptionCaught")
private suspend fun executeScopedTask() {
when (val result: OmhResult<T> = task()) {
is OmhResult.OmhSuccess -> executeSuccess(result.data)
is OmhResult.OmhError -> executeFailure(result.exception)
}
}

private suspend fun executeFailure(e: Exception) = withContext(Dispatchers.Main) {
onFailure?.invoke(e)
}

private suspend fun executeSuccess(data: T) {
withContext(Dispatchers.Main) {
onSuccess?.invoke(data)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.omh.android.auth.api.async.CancellableCollector
import com.omh.android.storage.sample.util.LOG_MESSAGE_EVENT
import com.omh.android.storage.sample.util.TAG_VIEW_UPDATE
import com.omh.android.storage.sample.util.launchSafe
Expand All @@ -12,6 +13,7 @@ abstract class BaseViewModel<State : ViewState, Event : ViewEvent> : ViewModel()

val state: MutableLiveData<State> = MutableLiveData()
val toastMessage: MutableLiveData<String> = MutableLiveData()
protected val cancellableCollector = CancellableCollector()

init {
setInitialState()
Expand All @@ -37,4 +39,9 @@ abstract class BaseViewModel<State : ViewState, Event : ViewEvent> : ViewModel()
protected fun setState(state: State) {
this.state.postValue(state)
}

override fun onCleared() {
super.onCleared()
cancellableCollector.clear()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@ package com.omh.android.storage.sample.presentation.file_viewer
import com.omh.android.storage.api.OmhStorageClient
import com.omh.android.storage.api.domain.model.OmhFile
import com.omh.android.storage.api.domain.model.OmhFileType
import com.omh.android.storage.api.domain.usecase.CreateFileUseCase
import com.omh.android.storage.api.domain.usecase.CreateFileUseCaseParams
import com.omh.android.storage.api.domain.usecase.DeleteFileUseCase
import com.omh.android.storage.api.domain.usecase.DeleteFileUseCaseParams
import com.omh.android.storage.api.domain.usecase.DeleteFileUseCaseResult
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCase
import com.omh.android.storage.api.domain.usecase.GetFilesListUseCaseParams
import com.omh.android.storage.api.domain.usecase.OmhResult
import com.omh.android.storage.sample.domain.model.FileType
import com.omh.android.storage.sample.presentation.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down Expand Up @@ -51,36 +43,33 @@ class FileViewerViewModel @Inject constructor(
}
}

private suspend fun initializeEvent() {
private fun initializeEvent() {
refreshFileListEvent()
}

private suspend fun refreshFileListEvent() {
private fun refreshFileListEvent() {
setState(FileViewerViewState.Loading)
val parentId = parentIdStack.peek()

val listFilesUseCase: GetFilesListUseCase = omhStorageClient.listFiles()

when (
val result = listFilesUseCase(GetFilesListUseCaseParams(parentId))
) {
is OmhResult.OmhSuccess -> {
setState(FileViewerViewState.Content(result.data.files))
val cancellable = omhStorageClient.listFiles(parentId)
.addOnSuccess { data ->
val files: List<OmhFile> = data.files
setState(FileViewerViewState.Content(files))
}

is OmhResult.OmhError -> {
toastMessage.postValue(result.toString())
.addOnFailure { e ->
toastMessage.postValue(e.message)
setState(FileViewerViewState.Content(emptyList()))
}
}
.execute()
cancellableCollector.addCancellable(cancellable)
}

private fun swapLayoutManagerEvent() {
isGridLayoutManager = !isGridLayoutManager
setState(FileViewerViewState.SwapLayoutManager)
}

private suspend fun fileClickedEvent(event: FileViewerViewEvent.FileClicked) {
private fun fileClickedEvent(event: FileViewerViewEvent.FileClicked) {
val file = event.file

if (file.isFolder()) {
Expand All @@ -93,7 +82,7 @@ class FileViewerViewModel @Inject constructor(
}
}

private suspend fun backPressedEvent() {
private fun backPressedEvent() {
if (parentIdStack.peek() == ID_ROOT) {
setState(FileViewerViewState.Finish)
} else {
Expand All @@ -102,52 +91,41 @@ class FileViewerViewModel @Inject constructor(
}
}

private suspend fun createFileEvent(event: FileViewerViewEvent.CreateFile) {
private fun createFileEvent(event: FileViewerViewEvent.CreateFile) {
setState(FileViewerViewState.Loading)
val parentId = parentIdStack.peek()

val createFileUseCase: CreateFileUseCase = omhStorageClient.createFile()

when (
val result =
createFileUseCase(CreateFileUseCaseParams(event.name, event.mimeType, parentId))
) {
is OmhResult.OmhSuccess -> {
val cancellable = omhStorageClient.createFile(event.name, event.mimeType, parentId)
.addOnSuccess {
refreshFileListEvent()
}

is OmhResult.OmhError -> {
toastMessage.postValue(result.toString())
.addOnFailure { e ->
toastMessage.postValue(e.message)
refreshFileListEvent()
}
}
.execute()
cancellableCollector.addCancellable(cancellable)
}

private suspend fun deleteFileEvent(event: FileViewerViewEvent.DeleteFile) {
private fun deleteFileEvent(event: FileViewerViewEvent.DeleteFile) {
setState(FileViewerViewState.Loading)

val file = event.file

val deleteFileUseCase: DeleteFileUseCase = omhStorageClient.deleteFile()

when (val result = deleteFileUseCase(DeleteFileUseCaseParams(file.id))) {
is OmhResult.OmhSuccess -> {
handleDeleteSuccess(result, file)
val cancellable = omhStorageClient.deleteFile(file.id)
.addOnSuccess { data ->
handleDeleteSuccess(data.isSuccess, file)
}

is OmhResult.OmhError -> {
.addOnFailure {
toastMessage.postValue("ERROR: ${file.name} was NOT deleted")
}
}

.execute()
cancellableCollector.addCancellable(cancellable)
refreshFileListEvent()
}

private fun handleDeleteSuccess(
result: OmhResult.OmhSuccess<DeleteFileUseCaseResult>,
file: OmhFile
) {
val toastText = if (result.data.isSuccess) {
private fun handleDeleteSuccess(isSuccessful: Boolean, file: OmhFile) {
val toastText = if (isSuccessful) {
"${file.name} was successfully deleted"
} else {
"${file.name} was NOT deleted"
Expand Down

0 comments on commit 9e89281

Please sign in to comment.