ConfirmInfectionResultViewModel.kt 4.67 KB
Newer Older
1
2
3
4
package org.dpppt.android.app.infection.result

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
5
import com.google.android.gms.common.api.ApiException
6
7
import io.reactivex.rxjava3.disposables.Disposable
import mobi.lab.mvvm.Event
8
import org.dpppt.android.app.common.util.asLiveData
9
10
import org.dpppt.android.app.common.util.backgroundToMain
import org.dpppt.android.app.common.util.exhaustive
11
import org.dpppt.android.app.domain.entity.DomainException
12
import org.dpppt.android.app.domain.entity.enums.PatientPortalResult
13
import org.dpppt.android.app.domain.usecase.dp3t.GaenSendIAmInfectedUseCase
14
import org.dpppt.android.app.domain.usecase.infection.request.DeleteConfirmInfectionRequestUseCase
15
import org.dpppt.android.app.domain.usecase.infection.request.GetActiveConfirmInfectionRequestUseCase
16
import org.dpppt.android.app.util.dispose
17
import org.dpppt.android.sdk.internal.backend.StatusCodeException
18
import timber.log.Timber
19
import java.util.concurrent.CancellationException
20
21
import javax.inject.Inject

22
class ConfirmInfectionResultViewModel @Inject constructor(
23
    private val deleteInfectionRequestUseCase: DeleteConfirmInfectionRequestUseCase,
24
    private val getActiveRequestUseCase: GetActiveConfirmInfectionRequestUseCase,
25
    private val gaenSendIAmInfectedUseCase: GaenSendIAmInfectedUseCase
26
) : ViewModel() {
27
28

    private val _action = MutableLiveData<Event<Action>>()
29
    val action = _action.asLiveData()
30

31
    private val _state: MutableLiveData<UiState> = MutableLiveData(UiState.Loading)
32
    val state = _state.asLiveData()
33
34
35
36
37
38
39
40

    private var disposable: Disposable? = null

    override fun onCleared() {
        super.onCleared()
        dispose(disposable)
    }

41
42
    fun start(result: PatientPortalResult) {
        when (result) {
43
            PatientPortalResult.Ok -> showPreShareInfo()
44
45
            PatientPortalResult.Cancel -> restartToHome()
            is PatientPortalResult.Error -> showError(result.exception)
46
47
48
            PatientPortalResult.InProgress -> {
                // No-op, will not happen here
            }
49
            is PatientPortalResult.DebugJustDone -> onSendInfectedStatusSuccess()
50
51
52
        }.exhaustive
    }

53
54
55
56
    private fun showPreShareInfo() {
        _state.value = UiState.PreShareInfo
    }

57
58
59
60
    fun onErrorDismissed() {
        restartToHome()
    }

61
    private fun onSendInfectedStatusSuccess() {
Harri Kirik's avatar
Harri Kirik committed
62
        Timber.d("onSendInfectedStatusSuccess")
63
        _state.value = UiState.Done
64
        deleteInfectionRequestUseCase.execute()
65
66
    }

67
    private fun onSendInfectedStatusError(error: Throwable) {
Harri Kirik's avatar
Harri Kirik committed
68
        Timber.e(error, "onSendInfectedStatusError")
69
        if (error is CancellationException) {
Harri Kirik's avatar
Harri Kirik committed
70
            // Show the share denied error dialog
71
            showShareDeniedError()
72
73
74
75
76
77
            return
        }
        val allowRetry = when (error) {
            is StatusCodeException -> false
            is ApiException -> true
            else -> true
78
        }
79
        _action.value = Event(Action.ShowInfectedStatusError(error, allowRetry))
80
81
    }

82
83
84
85
86
    private fun showShareDeniedError() {
        Timber.d("showShareDeniedError")
        _action.value = Event(Action.ShowShareDeniedError)
    }

87
    fun onContinueFromSuccessClicked() {
88
89
90
        restartToHome()
    }

91
92
93
94
95
    fun onBackClicked() {
        Timber.d("onBackClicked")
        restartToHome()
    }

96
97
98
99
    fun onContinueFromPreShareInfoClicked() {
        startInfectionConfirmation()
    }

100
101
102
103
    fun onErrorRetryClicked() {
        startInfectionConfirmation()
    }

104
    private fun restartToHome() {
105
        Timber.d("restartToHome")
106
        deleteInfectionRequestUseCase.execute()
107
        _action.value = Event(Action.NavigateToHomeRestart)
108
109
110
    }

    private fun showError(error: DomainException) {
111
        _action.value = Event(Action.ShowPatientPortalResultError(error))
112
113
    }

114
    fun startInfectionConfirmation() {
115
116
117
118
119
        val request = getActiveRequestUseCase.execute()
        if (request == null) {
            showError(DomainException.ConfirmInfectionRequestNotFound())
            return
        }
120
        Timber.d("startInfectionConfirmation")
121

Kelian Kaio's avatar
Kelian Kaio committed
122
123
124
125
        dispose(disposable)
        disposable = gaenSendIAmInfectedUseCase.execute(request)
            .backgroundToMain()
            .subscribe(::onSendInfectedStatusSuccess, ::onSendInfectedStatusError)
126
127
128
129
130
    }

    sealed class UiState {
        object Loading : UiState()
        object Done : UiState()
131
        object PreShareInfo : UiState()
132
133
    }

134
    sealed class Action {
135
136
        data class ShowPatientPortalResultError(val error: DomainException) : Action()
        data class ShowInfectedStatusError(val error: Throwable, val allowRetry: Boolean) : Action()
137
        object ShowShareDeniedError : Action()
138
        object NavigateToHomeRestart : Action()
139
    }
140
}