ConfirmInfectionPatientPortalViewModel.kt 7.35 KB
Newer Older
1
2
3
4
5
6
package org.dpppt.android.app.infection.patientportal

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.disposables.Disposable
import mobi.lab.mvvm.Event
7
import org.dpppt.android.app.common.util.asLiveData
8
import org.dpppt.android.app.common.util.backgroundToMain
9
import org.dpppt.android.app.common.util.exhaustive
10
import org.dpppt.android.app.domain.entity.DomainException
11
import org.dpppt.android.app.domain.entity.enums.PatientPortalResult
12
import org.dpppt.android.app.domain.usecase.infection.patientportal.CleanupPatientPortalWebViewSessionUseCase
13
import org.dpppt.android.app.domain.usecase.infection.patientportal.HandlePatientPortalCallbackUseCase
14
import org.dpppt.android.app.domain.usecase.infection.patientportal.PreparePatientPortalUrlNavigationUseCase
15
import org.dpppt.android.app.domain.usecase.infection.request.DeleteConfirmInfectionRequestUseCase
16
17
import org.dpppt.android.app.util.dispose
import timber.log.Timber
18
import java.lang.IllegalArgumentException
19
20
21
import javax.inject.Inject

class ConfirmInfectionPatientPortalViewModel @Inject constructor(
22
23
    private val preparePatientPortalUrlNavigationUseCase: PreparePatientPortalUrlNavigationUseCase,
    private val cleanupPatientPortalWebViewSessionUseCase: CleanupPatientPortalWebViewSessionUseCase,
24
25
    private val handleCallbackUseCase: HandlePatientPortalCallbackUseCase,
    private val deleteInfectionRequestUseCase: DeleteConfirmInfectionRequestUseCase
26
27
28
) : ViewModel() {

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

    private val _showProgress = MutableLiveData(true)
32
    val showProgress = _showProgress.asLiveData()
33
    private var portalResult: PatientPortalResult = PatientPortalResult.InProgress
34
    private var isViewStopped: Boolean = false
35
36
37
38
39

    private var disposable: Disposable? = null

    init {
        _showProgress.value = true
40
        initializePortalResult()
41
        preparePatientPortalUrlNavigation()
42
43
    }

44
45
46
    fun onViewStarted() {
        Timber.d("onViewStarted")
        isViewStopped = false
47
        checkPatientPortalResult(portalResult)
48
49
50
51
52
53
54
    }

    fun onViewStopped() {
        Timber.d("onViewStopped")
        isViewStopped = true
    }

55
56
57
    override fun onCleared() {
        super.onCleared()
        dispose(disposable)
58
        disposePortalResult()
59
        Timber.d("onCleared")
60
61
    }

62
63
64
65
    fun onPageLoaded() {
        _showProgress.value = false
    }

66
    fun shouldOverrideUrl(uri: String): Boolean {
67
68
69
        rememberPortalResult(handleCallbackUseCase.execute(uri))
        return when (portalResult) {
            is PatientPortalResult.InProgress -> {
70
71
72
                // Not our end condition
                false
            }
73
            is PatientPortalResult.Ok, is PatientPortalResult.Cancel, is PatientPortalResult.Error -> {
74
                // Successful end
75
                cleanupAndContinueWithTheResult(portalResult)
76
77
                true
            }
78
79
80
81
            is PatientPortalResult.DebugJustDone -> {
                // Not supported here
                throw IllegalArgumentException("The PatientPortalResult.DebugJustDone is not supported for this screen!")
            }
82
        }.exhaustive
83
84
85
86
87
88
89
90
91
92
93
94
95
    }

    private fun checkPatientPortalResult(result: PatientPortalResult?) {
        if (result == null) {
            Timber.d("checkPatientPortalResult - No result yet")
            return
        } else if (result == PatientPortalResult.InProgress) {
            Timber.d("checkPatientPortalResult - Still in progress: $result")
            return
        }
        Timber.d("checkPatientPortalResult - We have a result: $result")
        // We have a result
        cleanupAndContinueWithTheResult(result)
96
97
    }

98
99
100
101
    fun onPageLoadError(error: DomainException) {
        _action.value = Event(Action.ShowError(error))
    }

102
103
104
105
    fun onUpClicked() {
        restartToHome()
    }

106
    fun onBackClicked() {
107
        cleanupAndAbort(listener = { _action.value = Event(Action.NavigateBack) })
108
109
    }

110
    private fun restartToHome() {
111
        cleanupAndAbort(listener = { _action.value = Event(Action.NavigateToRestartHome) })
112
113
    }

114
115
116
117
    private fun clearFormData() {
        _action.value = Event(Action.ClearFormData)
    }

118
119
    private fun preparePatientPortalUrlNavigation() {
        Timber.d("preparePatientPortalUrlNavigation")
120
        dispose(disposable)
121
        disposable = preparePatientPortalUrlNavigationUseCase
Harri Kirik's avatar
Harri Kirik committed
122
123
            .execute()
            .backgroundToMain()
124
125
            .subscribe(
                { url ->
126
                    Timber.d("preparePatientPortalUrlNavigation - start URL: $url")
127
128
129
130
131
132
133
                    _action.value = Event(Action.LoadUrl(url))
                },
                { error ->
                    Timber.w(error, "preparePatientPortalUrlNavigation")
                    _action.value = Event(Action.ShowError(DomainException.from(error)))
                }
            )
Harri Kirik's avatar
Harri Kirik committed
134
135
    }

136
    private fun cleanupAndContinueWithTheResult(resp: PatientPortalResult) {
137
138
139
140
141
        if (isViewStopped) {
            Timber.w("cleanupAndContinueWithTheResult - view is currently stopped, we can't continue with the result $resp.")
            return
        }
        Timber.d("cleanupAndContinueWithTheResult - handling the result: $resp")
142
        clearFormData()
143
        disposePortalResult()
144
145
146
147
        dispose(disposable)
        disposable = cleanupPatientPortalWebViewSessionUseCase
            .execute()
            .backgroundToMain()
148
149
150
151
152
153
154
155
156
157
            .subscribe(
                {
                    Timber.d("cleanupAndContinueWithTheResult - Navigate to ConfirmInfectionResult")
                    _action.value = Event(Action.NavigateToConfirmInfectionResult(resp))
                },
                { error ->
                    Timber.w(error, "cleanupAndContinueWithTheResult - Navigation to ConfirmInfectionResult failed")
                    _action.value = Event(Action.ShowError(DomainException.from(error)))
                }
            )
158
159
160
161
    }

    private fun cleanupAndAbort(listener: () -> Unit) {
        Timber.d("cleanupAndAbort")
162
        clearFormData()
163
164
        // Delete the request
        deleteInfectionRequestUseCase.execute()
165
        disposePortalResult()
166
167
168
169
170
        // Also delete cookies
        dispose(disposable)
        disposable = cleanupPatientPortalWebViewSessionUseCase
            .execute()
            .backgroundToMain()
171
172
173
174
175
176
177
178
179
180
            .subscribe(
                {
                    // Call the listener
                    listener.invoke()
                },
                { error ->
                    Timber.w(error, "cleanupAndAbort")
                    _action.value = Event(Action.ShowError(DomainException.from(error)))
                }
            )
181
182
    }

183
    private fun initializePortalResult() {
184
        portalResult = PatientPortalResult.InProgress
185
186
187
    }

    private fun rememberPortalResult(value: PatientPortalResult) {
188
        portalResult = value
189
190
191
    }

    private fun disposePortalResult() {
192
193
        // For a reset we just initialize it again to the first state
        initializePortalResult()
194
195
    }

196
197
    sealed class Action {
        data class LoadUrl(val url: String) : Action()
198
        data class ShowError(val error: DomainException) : Action()
199
        object ClearFormData : Action()
200
201
202
        object NavigateBack : Action()
        object NavigateToRestartHome : Action()
        data class NavigateToConfirmInfectionResult(val callbackResult: PatientPortalResult) : Action()
203
204
    }
}