Skip to content

Commit f29ae30

Browse files
authored
Merge pull request #158 from ProteGO-Safe/release/4.7.0
Release/4.7.0
2 parents 423d53d + e67f172 commit f29ae30

86 files changed

Lines changed: 1504 additions & 262 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ Dev: ./app/src/dev/google-services.json
7777

7878
## ChangeLog
7979

80+
4.7.0
81+
82+
Possibility to generate Covid Test Subscription when Exposure Notification returns HIGH RISK
83+
84+
Cache UI requests when error should be handled by native
85+
86+
Update UI
87+
8088
4.6.0
8189

8290
List of current color zones for poviats.

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ android {
2727
applicationId "pl.gov.mc.protegosafe"
2828
minSdkVersion 21
2929
targetSdkVersion 29
30-
versionCode 72
31-
versionName "4.6.0"
30+
versionCode 74
31+
versionName "4.7.0"
3232

3333
setProperty("archivesBaseName", "protegosafe-${defaultConfig.versionName}-${defaultConfig.versionCode}")
3434

app/src/main/java/pl/gov/mc/protegosafe/App.kt

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ import org.koin.core.KoinComponent
1818
import org.koin.core.context.startKoin
1919
import org.koin.core.get
2020
import org.koin.core.inject
21-
import org.threeten.bp.LocalDateTime
22-
import org.threeten.bp.OffsetDateTime
2321
import pl.gov.mc.protegosafe.data.BuildConfig
2422
import pl.gov.mc.protegosafe.data.db.realm.RealmDatabaseBuilder
2523
import pl.gov.mc.protegosafe.data.di.dataModule
@@ -29,7 +27,6 @@ import pl.gov.mc.protegosafe.di.deviceModule
2927
import pl.gov.mc.protegosafe.di.useCaseModule
3028
import pl.gov.mc.protegosafe.di.viewModelModule
3129
import pl.gov.mc.protegosafe.domain.repository.CertificatePinningRepository
32-
import pl.gov.mc.protegosafe.domain.repository.DiagnosisKeyRepository
3330
import pl.gov.mc.protegosafe.domain.scheduler.ApplicationTaskScheduler
3431
import pl.gov.mc.protegosafe.domain.usecase.PrepareMigrationIfRequiredUseCase
3532
import timber.log.Timber
@@ -57,7 +54,6 @@ class App : Application(), KoinComponent {
5754
initializeThreeTenABP()
5855
scheduleRemoveOldExposuresTask()
5956
scheduleUpdateDistrictsRestrictionsTask()
60-
setTemporaryExposureKeysDownloadTimestampIfEmpty()
6157
}
6258

6359
private fun prepareMigrationIfRequired() {
@@ -127,16 +123,6 @@ class App : Application(), KoinComponent {
127123
}
128124
}
129125

130-
private fun setTemporaryExposureKeysDownloadTimestampIfEmpty() {
131-
get<DiagnosisKeyRepository>().apply {
132-
if (getLatestProcessedDiagnosisKeyTimestamp() == 0L) {
133-
setLatestProcessedDiagnosisKeyTimestamp(
134-
LocalDateTime.now().toInstant(OffsetDateTime.now().offset).epochSecond
135-
)
136-
}
137-
}
138-
}
139-
140126
private fun initializeFcm() {
141127
FirebaseApp.initializeApp(this)
142128
FirebaseInstanceId.getInstance().instanceId

app/src/main/java/pl/gov/mc/protegosafe/di/AppModule.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import pl.gov.mc.protegosafe.domain.usecase.GetFontScaleUseCase
2424
import pl.gov.mc.protegosafe.domain.usecase.GetLocaleUseCase
2525
import pl.gov.mc.protegosafe.domain.usecase.GetMigrationUrlUseCase
2626
import pl.gov.mc.protegosafe.domain.usecase.GetNotificationDataAndClearUseCase
27-
import pl.gov.mc.protegosafe.domain.usecase.GetSafetyNetAttestationTokenUseCase
2827
import pl.gov.mc.protegosafe.domain.usecase.GetServicesStatusUseCase
28+
import pl.gov.mc.protegosafe.domain.usecase.covidtest.GetTestSubscriptionStatusUseCase
2929
import pl.gov.mc.protegosafe.domain.usecase.GetSystemLanguageUseCase
3030
import pl.gov.mc.protegosafe.domain.usecase.OnGetBridgeDataUseCase
3131
import pl.gov.mc.protegosafe.domain.usecase.OnPushNotificationUseCase
@@ -41,6 +41,9 @@ import pl.gov.mc.protegosafe.domain.usecase.StopExposureNotificationUseCase
4141
import pl.gov.mc.protegosafe.domain.usecase.StorePendingActivityResultUseCase
4242
import pl.gov.mc.protegosafe.domain.usecase.UploadTemporaryExposureKeysUseCase
4343
import pl.gov.mc.protegosafe.domain.usecase.UploadTemporaryExposureKeysWithCachedPayloadUseCase
44+
import pl.gov.mc.protegosafe.domain.usecase.covidtest.GetTestSubscriptionPinUseCase
45+
import pl.gov.mc.protegosafe.domain.usecase.covidtest.UpdateTestSubscriptionStatusUseCase
46+
import pl.gov.mc.protegosafe.domain.usecase.covidtest.UploadTestSubscriptionPinUseCase
4447
import pl.gov.mc.protegosafe.domain.usecase.restrictions.GetDistrictsRestrictionsResultUseCase
4548
import pl.gov.mc.protegosafe.domain.usecase.restrictions.GetSubscribedDistrictsResultUseCase
4649
import pl.gov.mc.protegosafe.domain.usecase.restrictions.HandleDistrictActionUseCase
@@ -72,6 +75,9 @@ val useCaseModule = module {
7275
get(),
7376
get(),
7477
get(),
78+
get(),
79+
get(),
80+
get(),
7581
get()
7682
)
7783
}
@@ -85,7 +91,6 @@ val useCaseModule = module {
8591
factory { ChangeServiceStatusUseCase(get(), get(), get()) }
8692
factory { ClearDataUseCase(get(), get(), get(), get()) }
8793
factory { ProvideDiagnosisKeysUseCase(get(), get(), get()) }
88-
factory { GetSafetyNetAttestationTokenUseCase(get(), get()) }
8994
factory {
9095
UploadTemporaryExposureKeysUseCase(
9196
get(),
@@ -95,6 +100,7 @@ val useCaseModule = module {
95100
get(),
96101
get(),
97102
get(),
103+
get(),
98104
get()
99105
)
100106
}
@@ -105,7 +111,7 @@ val useCaseModule = module {
105111
factory { StorePendingActivityResultUseCase(get(), get()) }
106112
factory { ProcessPendingActivityResultUseCase(get(), get()) }
107113
factory { GetExposureInformationUseCase(get(), get()) }
108-
factory { GetAnalyzeResultUseCase(get(), get(), get(), get()) }
114+
factory { GetAnalyzeResultUseCase(get(), get(), get(), get(), get()) }
109115
factory { CheckDeviceRootedUseCase(get(), get(), get(), get()) }
110116
factory { PrepareMigrationIfRequiredUseCase(get(), get()) }
111117
factory { GetMigrationUrlUseCase(get()) }
@@ -120,11 +126,15 @@ val useCaseModule = module {
120126
factory { HandleDistrictActionUseCase(get(), get(), get()) }
121127
factory { GetSubscribedDistrictsResultUseCase(get(), get(), get()) }
122128
factory { NotifyDistrictsUpdatedUseCase(get(), get(), get()) }
129+
factory { UploadTestSubscriptionPinUseCase(get(), get(), get(), get(), get(), get()) }
130+
factory { GetTestSubscriptionStatusUseCase(get(), get(), get(), get()) }
131+
factory { UpdateTestSubscriptionStatusUseCase(get(), get(), get()) }
132+
factory { GetTestSubscriptionPinUseCase(get(), get(), get()) }
123133
}
124134

125135
val viewModelModule = module {
126136
viewModel { MainViewModel(get(), get(), get()) }
127137
viewModel {
128-
HomeViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get())
138+
HomeViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
129139
}
130140
}

app/src/main/java/pl/gov/mc/protegosafe/ui/home/HomeFragment.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
3131
import pl.gov.mc.protegosafe.BuildConfig
3232
import pl.gov.mc.protegosafe.R
3333
import pl.gov.mc.protegosafe.databinding.FragmentHomeBinding
34+
import pl.gov.mc.protegosafe.domain.exception.CovidTestNotCompatibleDeviceException
3435
import pl.gov.mc.protegosafe.domain.exception.UploadException
3536
import pl.gov.mc.protegosafe.domain.model.ActivityRequest
3637
import pl.gov.mc.protegosafe.domain.model.ActivityResult
@@ -279,12 +280,20 @@ class HomeFragment : BaseFragment() {
279280
}
280281

281282
private fun showError(error: Exception) {
282-
binding.missingConnectionLayout.button_check_internet_connection.setOnClickListener {
283-
binding.webView.visibility = View.VISIBLE
284-
vm.onUploadRetry()
283+
if (error !is CovidTestNotCompatibleDeviceException) {
284+
binding.missingConnectionLayout.button_check_internet_connection.visibility =
285+
View.VISIBLE
286+
binding.missingConnectionLayout.button_check_internet_connection.setOnClickListener {
287+
binding.webView.visibility = View.VISIBLE
288+
vm.onRequestRetry()
289+
}
290+
} else {
291+
binding.missingConnectionLayout.button_check_internet_connection.visibility =
292+
View.INVISIBLE
285293
}
294+
286295
binding.missingConnectionLayout.button_cancel.setOnClickListener {
287-
vm.onUploadCanceled()
296+
vm.onRequestCanceled()
288297
binding.webView.visibility = View.VISIBLE
289298
}
290299
binding.missingConnectionLayout.text_view_connection_error.setText(
@@ -337,6 +346,9 @@ class HomeFragment : BaseFragment() {
337346
is UploadException.DailyLimitExceededError -> {
338347
R.string.upload_temporary_exposure_keys_day_limit_exceed_error
339348
}
349+
is CovidTestNotCompatibleDeviceException -> {
350+
R.string.covid_test_not_compatible_device
351+
}
340352
else -> {
341353
R.string.no_internet_connection_msg
342354
}

app/src/main/java/pl/gov/mc/protegosafe/ui/home/HomeViewModel.kt

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,25 @@ package pl.gov.mc.protegosafe.ui.home
22

33
import androidx.lifecycle.LiveData
44
import androidx.lifecycle.MutableLiveData
5+
import io.reactivex.android.schedulers.AndroidSchedulers
56
import io.reactivex.rxkotlin.addTo
67
import io.reactivex.rxkotlin.subscribeBy
8+
import io.reactivex.schedulers.Schedulers
9+
import pl.gov.mc.protegosafe.domain.exception.CovidTestNotCompatibleDeviceException
710
import pl.gov.mc.protegosafe.domain.exception.NoInternetConnectionException
811
import pl.gov.mc.protegosafe.domain.exception.UploadException
912
import pl.gov.mc.protegosafe.domain.model.ActionRequiredItem
1013
import pl.gov.mc.protegosafe.domain.model.ActivityResult
1114
import pl.gov.mc.protegosafe.domain.model.AppLifecycleState
1215
import pl.gov.mc.protegosafe.domain.model.ExposureNotificationActionNotResolvedException
16+
import pl.gov.mc.protegosafe.domain.model.GetBridgeDataUIRequestItem
1317
import pl.gov.mc.protegosafe.domain.model.IncomingBridgeDataItem
1418
import pl.gov.mc.protegosafe.domain.model.IncomingBridgeDataType
1519
import pl.gov.mc.protegosafe.domain.model.OutgoingBridgeDataResultComposer
1620
import pl.gov.mc.protegosafe.domain.model.OutgoingBridgeDataType
21+
import pl.gov.mc.protegosafe.domain.model.SetBridgeDataUIRequestItem
1722
import pl.gov.mc.protegosafe.domain.model.TemporaryExposureKeysUploadState
23+
import pl.gov.mc.protegosafe.domain.repository.UiRequestCacheRepository
1824
import pl.gov.mc.protegosafe.domain.usecase.ComposeAppLifecycleStateBrideDataUseCase
1925
import pl.gov.mc.protegosafe.domain.usecase.GetServicesStatusUseCase
2026
import pl.gov.mc.protegosafe.domain.usecase.OnGetBridgeDataUseCase
@@ -23,6 +29,7 @@ import pl.gov.mc.protegosafe.domain.usecase.ProcessPendingActivityResultUseCase
2329
import pl.gov.mc.protegosafe.domain.usecase.StartExposureNotificationUseCase
2430
import pl.gov.mc.protegosafe.domain.usecase.StorePendingActivityResultUseCase
2531
import pl.gov.mc.protegosafe.domain.usecase.UploadTemporaryExposureKeysWithCachedPayloadUseCase
32+
import pl.gov.mc.protegosafe.domain.usecase.covidtest.UpdateTestSubscriptionStatusUseCase
2633
import pl.gov.mc.protegosafe.logging.webViewTimber
2734
import pl.gov.mc.protegosafe.ui.common.BaseViewModel
2835
import pl.gov.mc.protegosafe.ui.common.livedata.SingleLiveEvent
@@ -38,7 +45,9 @@ class HomeViewModel(
3845
private val uploadTemporaryExposureKeysWithCachedPayloadUseCase: UploadTemporaryExposureKeysWithCachedPayloadUseCase,
3946
private val storePendingActivityResultUseCase: StorePendingActivityResultUseCase,
4047
private val processPendingActivityResultUseCase: ProcessPendingActivityResultUseCase,
41-
private val outgoingBridgeDataResultComposer: OutgoingBridgeDataResultComposer
48+
private val updateTestSubscriptionStatusUseCase: UpdateTestSubscriptionStatusUseCase,
49+
private val outgoingBridgeDataResultComposer: OutgoingBridgeDataResultComposer,
50+
private val uiRequestCacheRepository: UiRequestCacheRepository
4251
) : BaseViewModel() {
4352

4453
private val _javascriptCode = MutableLiveData<String>()
@@ -96,30 +105,53 @@ class HomeViewModel(
96105
}
97106

98107
fun getBridgeData(dataType: Int, data: String, requestId: String) {
99-
onGetBridgeDataUseCase.execute(OutgoingBridgeDataType.valueOf(dataType), data)
108+
onGetBridgeDataUseCase.execute(
109+
OutgoingBridgeDataType.valueOf(dataType), data, requestId, ::onResultActionRequired
110+
)
100111
.subscribe(
101112
{
102113
webViewTimber().d("getBridgeData: $dataType output: $it")
103114
bridgeDataResponse(it, dataType, requestId)
104115
},
105116
{
117+
handleError(it)
106118
Timber.e(it, "getBridgeData failed")
107119
}
108120
).addTo(disposables)
109121
}
110122

111-
fun onUploadRetry() {
112-
uploadTemporaryExposureKeysWithCachedPayload()
123+
fun onRequestRetry() {
124+
uiRequestCacheRepository.getCachedRequest()?.let { uiRequest ->
125+
when (uiRequest) {
126+
is SetBridgeDataUIRequestItem -> {
127+
retryCachedSetBridgeDataRequest(uiRequest)
128+
}
129+
is GetBridgeDataUIRequestItem -> {
130+
uiRequestCacheRepository.retryCachedRequest(uiRequest, ::getBridgeData)
131+
}
132+
}
133+
}
113134
}
114135

115-
fun onUploadCanceled() {
116-
sendUploadStatus(TemporaryExposureKeysUploadState.CANCELED)
136+
fun onRequestCanceled() {
137+
uiRequestCacheRepository.getCachedRequest()?.let { uiRequest ->
138+
when (uiRequest) {
139+
is SetBridgeDataUIRequestItem -> {
140+
uiRequestCacheRepository.cancelCachedRequest(uiRequest, ::onBridgeData)
141+
}
142+
is GetBridgeDataUIRequestItem -> {
143+
uiRequestCacheRepository.cancelCachedRequest(uiRequest, ::bridgeDataResponse)
144+
}
145+
}
146+
}
117147
}
118148

119-
private fun sendUploadStatus(status: TemporaryExposureKeysUploadState) {
149+
private fun sendAccessDeniedUploadStatus() {
120150
onBridgeData(
121151
OutgoingBridgeDataType.TEMPORARY_EXPOSURE_KEYS_UPLOAD_STATUS.code,
122-
outgoingBridgeDataResultComposer.composeTemporaryExposureKeysUploadResult(status)
152+
outgoingBridgeDataResultComposer.composeTemporaryExposureKeysUploadResult(
153+
TemporaryExposureKeysUploadState.ACCESS_DENIED
154+
)
123155
)
124156
}
125157

@@ -136,6 +168,10 @@ class HomeViewModel(
136168
is UploadException -> {
137169
_showUploadError.postValue(error as Exception)
138170
}
171+
is CovidTestNotCompatibleDeviceException -> {
172+
onRequestCanceled()
173+
_showUploadError.postValue(error as Exception)
174+
}
139175
else -> {
140176
Timber.e(error, "Problem can not be handled")
141177
}
@@ -204,7 +240,7 @@ class HomeViewModel(
204240
onBridgeData(actionRequired.dataType, actionRequired.dataJson)
205241
}
206242
is ActionRequiredItem.TemporaryExposureKeysPermissionDenied -> {
207-
sendUploadStatus(TemporaryExposureKeysUploadState.ACCESS_DENIED)
243+
sendAccessDeniedUploadStatus()
208244
}
209245
is ActionRequiredItem.ExposureNotificationPermissionGranted -> {
210246
onExposureNotificationPermissionGranted()
@@ -218,6 +254,9 @@ class HomeViewModel(
218254
is ActionRequiredItem.CloseApp -> {
219255
_closeApplication.postValue(Unit)
220256
}
257+
is ActionRequiredItem.UpdateTestSubscription -> {
258+
updateTestSubscriptionStatus()
259+
}
221260
}
222261
}
223262

@@ -250,6 +289,40 @@ class HomeViewModel(
250289
).addTo(disposables)
251290
}
252291

292+
private fun updateTestSubscriptionStatus() {
293+
Timber.d("updateTestSubscriptionStatus")
294+
updateTestSubscriptionStatusUseCase.execute()
295+
.subscribe(
296+
{
297+
onBridgeData(OutgoingBridgeDataType.GET_COVID_TEST_SUBSCRIPTION_STATUS.code, it)
298+
},
299+
{
300+
Timber.e(it, "sendServicesStatus failed")
301+
}
302+
).addTo(disposables)
303+
}
304+
305+
private fun retryCachedSetBridgeDataRequest(
306+
setBridgeDataUIRequestItem: SetBridgeDataUIRequestItem
307+
) {
308+
uiRequestCacheRepository.retryCachedRequest(
309+
setBridgeDataUIRequestItem,
310+
::onResultActionRequired
311+
)
312+
.subscribeOn(Schedulers.io())
313+
.observeOn(AndroidSchedulers.mainThread())
314+
.subscribe(
315+
{
316+
Timber.d("Success")
317+
},
318+
{
319+
handleError(it)
320+
Timber.e(it)
321+
}
322+
).addTo(disposables)
323+
// TODO move to usecase
324+
}
325+
253326
private fun bridgeDataResponse(body: String, dataType: Int, requestId: String) {
254327
val codeToExecute = "bridgeDataResponse('$body', $dataType, '$requestId')"
255328
webViewTimber().d("run Javascript: -$codeToExecute-")

0 commit comments

Comments
 (0)