Skip to content

Commit 4cac950

Browse files
authored
Merge pull request #168 from ProteGO-Safe/release/4.10.0
Release/4.10.0
2 parents 215a27b + 6080553 commit 4cac950

File tree

65 files changed

+810
-805
lines changed

Some content is hidden

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

65 files changed

+810
-805
lines changed

README.md

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

7878
## ChangeLog
7979

80+
**4.10.0**
81+
82+
- Added new file storage method
83+
- Split current JSON data to multiple smaller data files to prevent over downloading unwanted data
84+
- Enhanced view of the app home screen, which now includes more detailed statistics on vaccination and infections
85+
- New screen with detailed statistics and graphs on vaccination (number of people vaccinated, doses, adverse reactions) and infections (number of people infected, recovered, deaths, causes of death and tests)
86+
- Added information on vaccination and registration rules with redirection to registration, vaccination request and helpline
87+
- Fixed bug that occurred on Xiaomi phones with dark mode enabled
88+
- Bump EN version to 1.8.3
89+
8090
**4.9.1**
8191

8292
- Added information on vaccination statistics in Poland

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ android {
2828
applicationId "pl.gov.mc.protegosafe"
2929
minSdkVersion 21
3030
targetSdkVersion 29
31-
versionCode 85
32-
versionName "4.9.1"
31+
versionCode 87
32+
versionName "4.10.0"
3333

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

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import pl.gov.mc.protegosafe.data.db.WorkersIntervalDataStore
1313
import pl.gov.mc.protegosafe.data.db.realm.RealmDatabaseBuilder
1414
import pl.gov.mc.protegosafe.data.extension.toCompletable
1515
import pl.gov.mc.protegosafe.domain.repository.AppRepository
16+
import pl.gov.mc.protegosafe.domain.repository.FileRepository
1617
import timber.log.Timber
1718
import java.util.Locale
1819

@@ -22,6 +23,7 @@ class AppRepositoryImpl(
2223
private val realmDatabaseBuilder: RealmDatabaseBuilder,
2324
private val covidStatsDataStore: CovidStatsDataStore,
2425
private val workersIntervalDataStore: WorkersIntervalDataStore,
26+
private val fileRepository: FileRepository,
2527
private val context: Context
2628
) : AppRepository {
2729
override fun getVersionName(): Single<String> {
@@ -54,9 +56,8 @@ class AppRepositoryImpl(
5456

5557
override fun clearAppData(): Completable {
5658
return clearDatabase()
57-
.andThen(
58-
clearSharedPreferences()
59-
)
59+
.andThen(clearSharedPreferences())
60+
.andThen(fileRepository.clearAllInternalFiles())
6061
}
6162

6263
private fun clearDatabase(): Completable {

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

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,60 +10,65 @@ import pl.gov.mc.protegosafe.AppRepositoryImpl
1010
import pl.gov.mc.protegosafe.domain.Notifier
1111
import pl.gov.mc.protegosafe.domain.executor.PostExecutionThread
1212
import pl.gov.mc.protegosafe.domain.repository.AppRepository
13+
import pl.gov.mc.protegosafe.domain.repository.FileRepository
1314
import pl.gov.mc.protegosafe.domain.usecase.AppReviewUseCase
1415
import pl.gov.mc.protegosafe.domain.usecase.CancelExposureRiskUseCase
1516
import pl.gov.mc.protegosafe.domain.usecase.ChangeServiceStatusUseCase
16-
import pl.gov.mc.protegosafe.domain.usecase.PrepareMigrationIfRequiredUseCase
1717
import pl.gov.mc.protegosafe.domain.usecase.CheckDeviceRootedUseCase
1818
import pl.gov.mc.protegosafe.domain.usecase.ClearDataUseCase
1919
import pl.gov.mc.protegosafe.domain.usecase.CloseAppUseCase
2020
import pl.gov.mc.protegosafe.domain.usecase.ComposeAppLifecycleStateBrideDataUseCase
2121
import pl.gov.mc.protegosafe.domain.usecase.DeleteActivitiesUseCase
2222
import pl.gov.mc.protegosafe.domain.usecase.GetActivitiesResultUseCase
23-
import pl.gov.mc.protegosafe.domain.usecase.SaveKeysCountToAnalyzeUseCase
2423
import pl.gov.mc.protegosafe.domain.usecase.GetAnalyzeResultUseCase
2524
import pl.gov.mc.protegosafe.domain.usecase.GetAppVersionNameUseCase
2625
import pl.gov.mc.protegosafe.domain.usecase.GetCovidStatsNotificationStatusResultUseCase
27-
import pl.gov.mc.protegosafe.domain.usecase.GetCovidStatsResultAndUpdateUseCase
2826
import pl.gov.mc.protegosafe.domain.usecase.GetENStatsResultUseCase
29-
import pl.gov.mc.protegosafe.domain.usecase.restrictions.UpdateDistrictsRestrictionsUseCase
3027
import pl.gov.mc.protegosafe.domain.usecase.GetExposureInformationUseCase
3128
import pl.gov.mc.protegosafe.domain.usecase.GetFontScaleUseCase
3229
import pl.gov.mc.protegosafe.domain.usecase.GetLocaleUseCase
3330
import pl.gov.mc.protegosafe.domain.usecase.GetMigrationUrlUseCase
3431
import pl.gov.mc.protegosafe.domain.usecase.GetRouteDataAndClearUseCase
3532
import pl.gov.mc.protegosafe.domain.usecase.GetServicesStatusUseCase
36-
import pl.gov.mc.protegosafe.domain.usecase.covidtest.GetTestSubscriptionStatusUseCase
3733
import pl.gov.mc.protegosafe.domain.usecase.GetSystemLanguageUseCase
3834
import pl.gov.mc.protegosafe.domain.usecase.HandleNewUriUseCase
3935
import pl.gov.mc.protegosafe.domain.usecase.OnGetBridgeDataUseCase
40-
import pl.gov.mc.protegosafe.domain.usecase.ShowPushNotificationUseCase
4136
import pl.gov.mc.protegosafe.domain.usecase.OnSetBridgeDataUseCase
37+
import pl.gov.mc.protegosafe.domain.usecase.PrepareMigrationIfRequiredUseCase
4238
import pl.gov.mc.protegosafe.domain.usecase.ProcessPendingActivityResultUseCase
4339
import pl.gov.mc.protegosafe.domain.usecase.ProvideDiagnosisKeysUseCase
4440
import pl.gov.mc.protegosafe.domain.usecase.RescheduleProvideDiagnosisKeysTaskUseCase
4541
import pl.gov.mc.protegosafe.domain.usecase.SaveExposureCheckActivityUseCase
4642
import pl.gov.mc.protegosafe.domain.usecase.SaveExposureUseCase
47-
import pl.gov.mc.protegosafe.domain.usecase.SaveRouteUseCase
43+
import pl.gov.mc.protegosafe.domain.usecase.SaveKeysCountToAnalyzeUseCase
4844
import pl.gov.mc.protegosafe.domain.usecase.SaveRiskCheckActivityUseCase
45+
import pl.gov.mc.protegosafe.domain.usecase.SaveRouteUseCase
4946
import pl.gov.mc.protegosafe.domain.usecase.SaveTriageCompletedUseCase
5047
import pl.gov.mc.protegosafe.domain.usecase.SetAppLanguageUseCase
48+
import pl.gov.mc.protegosafe.domain.usecase.ShowPushNotificationUseCase
5149
import pl.gov.mc.protegosafe.domain.usecase.StartExposureNotificationUseCase
5250
import pl.gov.mc.protegosafe.domain.usecase.StopExposureNotificationUseCase
5351
import pl.gov.mc.protegosafe.domain.usecase.StorePendingActivityResultUseCase
5452
import pl.gov.mc.protegosafe.domain.usecase.SubscribeCovidStatusTopicUseCase
55-
import pl.gov.mc.protegosafe.domain.usecase.UpdateCovidStatsAndGetResultUseCase
5653
import pl.gov.mc.protegosafe.domain.usecase.UpdateCovidStatsNotificationsStatusUseCase
57-
import pl.gov.mc.protegosafe.domain.usecase.UpdateCovidStatsUseCase
5854
import pl.gov.mc.protegosafe.domain.usecase.UploadTemporaryExposureKeysUseCase
5955
import pl.gov.mc.protegosafe.domain.usecase.UploadTemporaryExposureKeysWithCachedPayloadUseCase
6056
import pl.gov.mc.protegosafe.domain.usecase.covidtest.GetTestSubscriptionPinUseCase
57+
import pl.gov.mc.protegosafe.domain.usecase.covidtest.GetTestSubscriptionStatusUseCase
6158
import pl.gov.mc.protegosafe.domain.usecase.covidtest.UpdateTestSubscriptionStatusUseCase
6259
import pl.gov.mc.protegosafe.domain.usecase.covidtest.UploadTestSubscriptionPinUseCase
63-
import pl.gov.mc.protegosafe.domain.usecase.restrictions.GetDistrictsRestrictionsResultUseCase
60+
import pl.gov.mc.protegosafe.domain.usecase.info.UpdateDashboardIfRequiredAndGetResultUseCase
61+
import pl.gov.mc.protegosafe.domain.usecase.info.UpdateDashboardUseCase
62+
import pl.gov.mc.protegosafe.domain.usecase.info.UpdateDetailsIfRequiredAndGetResultUseCase
63+
import pl.gov.mc.protegosafe.domain.usecase.info.UpdateTimestampsIfRequiredAndGetUseCase
6464
import pl.gov.mc.protegosafe.domain.usecase.restrictions.GetSubscribedDistrictsResultUseCase
65+
import pl.gov.mc.protegosafe.domain.usecase.restrictions.GetVoivodeshipsResultOrFetchIfRequiredUseCase
66+
import pl.gov.mc.protegosafe.domain.usecase.restrictions.GetVoivodeshipsResultUseCase
6567
import pl.gov.mc.protegosafe.domain.usecase.restrictions.HandleDistrictActionUseCase
6668
import pl.gov.mc.protegosafe.domain.usecase.restrictions.NotifyDistrictsUpdatedUseCase
69+
import pl.gov.mc.protegosafe.domain.usecase.restrictions.UpdateVoivodeshipsAndSyncDistrictsUseCase
70+
import pl.gov.mc.protegosafe.domain.usecase.restrictions.UpdateVoivodeshipsIfRequiredUseCase
71+
import pl.gov.mc.protegosafe.repository.FileRepositoryImpl
6772
import pl.gov.mc.protegosafe.ui.MainViewModel
6873
import pl.gov.mc.protegosafe.ui.common.NotifierImpl
6974
import pl.gov.mc.protegosafe.ui.home.HomeViewModel
@@ -75,7 +80,8 @@ val appModule = module {
7580
factory<PostExecutionThread> { pl.gov.mc.protegosafe.executor.PostExecutionThread() }
7681
factory { Realm.getDefaultInstance() }
7782
single<AppUpdateManager> { AppUpdateManagerFactory.create(androidContext()) }
78-
single<AppRepository> { AppRepositoryImpl(get(), get(), get(), get(), get(), androidContext()) }
83+
single<AppRepository> { AppRepositoryImpl(get(), get(), get(), get(), get(), get(), androidContext()) }
84+
factory<FileRepository> { FileRepositoryImpl(androidContext()) }
7985
}
8086

8187
val useCaseModule = module {
@@ -99,6 +105,8 @@ val useCaseModule = module {
99105
get(),
100106
get(),
101107
get(),
108+
get(),
109+
get(),
102110
get()
103111
)
104112
}
@@ -154,8 +162,6 @@ val useCaseModule = module {
154162
factory { GetLocaleUseCase(get()) }
155163
factory { GetFontScaleUseCase(get(), get(), get()) }
156164
factory { CloseAppUseCase(get(), get()) }
157-
factory { UpdateDistrictsRestrictionsUseCase(get(), get(), get()) }
158-
factory { GetDistrictsRestrictionsResultUseCase(get(), get(), get()) }
159165
factory { HandleDistrictActionUseCase(get(), get(), get()) }
160166
factory { GetSubscribedDistrictsResultUseCase(get(), get(), get()) }
161167
factory { NotifyDistrictsUpdatedUseCase(get(), get(), get(), get()) }
@@ -171,14 +177,19 @@ val useCaseModule = module {
171177
factory { GetActivitiesResultUseCase(get(), get(), get()) }
172178
factory { DeleteActivitiesUseCase(get(), get(), get()) }
173179
factory { HandleNewUriUseCase(get(), get()) }
174-
factory { UpdateCovidStatsUseCase(get(), get()) }
175-
factory { GetCovidStatsResultAndUpdateUseCase(get(), get(), get()) }
176-
factory { UpdateCovidStatsAndGetResultUseCase(get(), get(), get(), get()) }
177180
factory { GetCovidStatsNotificationStatusResultUseCase(get(), get(), get()) }
178181
factory { UpdateCovidStatsNotificationsStatusUseCase(get(), get(), get(), get()) }
179182
factory { SubscribeCovidStatusTopicUseCase(get(), get()) }
180183
factory { GetENStatsResultUseCase(get(), get(), get()) }
181184
factory { RescheduleProvideDiagnosisKeysTaskUseCase(get(), get()) }
185+
factory { UpdateTimestampsIfRequiredAndGetUseCase(get(), get()) }
186+
factory { UpdateDashboardUseCase(get(), get()) }
187+
factory { UpdateDashboardIfRequiredAndGetResultUseCase(get(), get(), get(), get()) }
188+
factory { UpdateDetailsIfRequiredAndGetResultUseCase(get(), get(), get()) }
189+
factory { GetVoivodeshipsResultUseCase(get(), get(), get()) }
190+
factory { GetVoivodeshipsResultOrFetchIfRequiredUseCase(get(), get(), get(), get()) }
191+
factory { UpdateVoivodeshipsAndSyncDistrictsUseCase(get(), get(), get()) }
192+
factory { UpdateVoivodeshipsIfRequiredUseCase(get(), get(), get(), get()) }
182193
}
183194

184195
val viewModelModule = module {
@@ -196,7 +207,6 @@ val viewModelModule = module {
196207
get(),
197208
get(),
198209
get(),
199-
get(),
200210
get()
201211
)
202212
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package pl.gov.mc.protegosafe.repository
2+
3+
import android.content.Context
4+
import io.reactivex.Completable
5+
import io.reactivex.Single
6+
import pl.gov.mc.protegosafe.domain.repository.FileRepository
7+
import java.io.File
8+
9+
class FileRepositoryImpl(private val context: Context) : FileRepository {
10+
11+
/**
12+
* Writes text to file in internal storage
13+
*
14+
* @param fileName File name
15+
* @param text Text to write
16+
*/
17+
override fun writeInternalFile(fileName: String, text: String): Completable {
18+
return Completable.fromAction {
19+
val file = File(context.filesDir.path + "/$fileName")
20+
if (file.exists().not()) {
21+
file.createNewFile()
22+
}
23+
file.writeText(text)
24+
}
25+
}
26+
27+
/**
28+
* Reads text from file in internal storage
29+
*
30+
* @param fileName File name
31+
* @return File content
32+
*/
33+
override fun readInternalFile(fileName: String): Single<String> {
34+
return Single.fromCallable {
35+
val file = File(context.filesDir.path + "/$fileName")
36+
file.readText()
37+
}
38+
}
39+
40+
/**
41+
* Reads text from file in internal storage or returns empty string on error (eg. missing file)
42+
*
43+
* @param fileName File name
44+
* @return File content or empty string
45+
*/
46+
override fun readInternalFileOrEmpty(fileName: String): Single<String> {
47+
return readInternalFile(fileName).onErrorReturn { "" }
48+
}
49+
50+
/**
51+
* Removes all internal files recursively
52+
*/
53+
override fun clearAllInternalFiles(): Completable {
54+
return Completable.fromAction {
55+
context.filesDir.listFiles()?.forEach { file ->
56+
file.deleteRecursively()
57+
}
58+
}
59+
}
60+
}

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import android.view.ViewGroup
1515
import android.webkit.ConsoleMessage
1616
import android.webkit.SslErrorHandler
1717
import android.webkit.WebChromeClient
18+
import android.webkit.WebSettings
1819
import android.webkit.WebView
1920
import android.webkit.WebViewClient
2021
import android.widget.Toast
@@ -127,12 +128,10 @@ class HomeFragment : BaseFragment() {
127128
).addTo(disposables)
128129
}
129130

130-
@SuppressLint("SetJavaScriptEnabled")
131131
private fun startPwaMigration(url: String) {
132132
binding.migrationLayout.isVisible = true
133133
binding.webView.apply {
134-
settings.javaScriptEnabled = true
135-
settings.domStorageEnabled = true
134+
applySettings()
136135
webViewClient = object : WebViewClient() {
137136
override fun onPageFinished(view: WebView?, url: String?) {
138137
binding.webView.evaluateJavascript(DUMP_UI_COMMAND) { dump ->
@@ -145,11 +144,9 @@ class HomeFragment : BaseFragment() {
145144
}
146145
}
147146

148-
@SuppressLint("SetJavaScriptEnabled")
149147
private fun setUpWebView() {
150148
binding.webView.apply {
151-
settings.javaScriptEnabled = true
152-
settings.domStorageEnabled = true
149+
applySettings()
153150
webViewClient = ProteGoWebViewClient()
154151
addJavascriptInterface(
155152
NativeBridgeInterface(
@@ -183,6 +180,17 @@ class HomeFragment : BaseFragment() {
183180
vm.javascriptCode.observe(viewLifecycleOwner, ::runJavascript)
184181
}
185182

183+
@SuppressLint("SetJavaScriptEnabled")
184+
private fun WebView.applySettings() {
185+
settings.apply {
186+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
187+
forceDark = WebSettings.FORCE_DARK_OFF
188+
}
189+
javaScriptEnabled = true
190+
domStorageEnabled = true
191+
}
192+
}
193+
186194
private inner class ProteGoWebViewClient : WebViewClient() {
187195
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
188196
return if (url.startsWith("tel:") ||

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import pl.gov.mc.protegosafe.domain.usecase.OnSetBridgeDataUseCase
3030
import pl.gov.mc.protegosafe.domain.usecase.ProcessPendingActivityResultUseCase
3131
import pl.gov.mc.protegosafe.domain.usecase.StartExposureNotificationUseCase
3232
import pl.gov.mc.protegosafe.domain.usecase.StorePendingActivityResultUseCase
33-
import pl.gov.mc.protegosafe.domain.usecase.UpdateCovidStatsAndGetResultUseCase
3433
import pl.gov.mc.protegosafe.domain.usecase.UploadTemporaryExposureKeysWithCachedPayloadUseCase
3534
import pl.gov.mc.protegosafe.domain.usecase.covidtest.UpdateTestSubscriptionStatusUseCase
3635
import pl.gov.mc.protegosafe.logging.WebViewTimber
@@ -51,7 +50,6 @@ class HomeViewModel(
5150
private val updateTestSubscriptionStatusUseCase: UpdateTestSubscriptionStatusUseCase,
5251
private val outgoingBridgeDataResultComposer: OutgoingBridgeDataResultComposer,
5352
private val getRouteAndClearUseCase: GetRouteDataAndClearUseCase,
54-
private val updateCovidStatsAndGetResultUseCase: UpdateCovidStatsAndGetResultUseCase,
5553
private val uiRequestCacheRepository: UiRequestCacheRepository
5654
) : BaseViewModel() {
5755

@@ -275,9 +273,6 @@ class HomeViewModel(
275273
is ActionRequiredItem.AppReview -> {
276274
_requestAppReview.postValue(Unit)
277275
}
278-
is ActionRequiredItem.UpdateCovidStats -> {
279-
updateCovidStats()
280-
}
281276
}
282277
}
283278

@@ -345,19 +340,6 @@ class HomeViewModel(
345340
).addTo(disposables)
346341
}
347342

348-
private fun updateCovidStats() {
349-
Timber.d("updateCovidStats")
350-
updateCovidStatsAndGetResultUseCase.execute()
351-
.subscribe(
352-
{
353-
onBridgeData(OutgoingBridgeDataType.GET_COVID_STATS.code, it)
354-
},
355-
{
356-
Timber.d("updateCovidStats failed")
357-
}
358-
).addTo(disposables)
359-
}
360-
361343
private fun retryCachedSetBridgeDataRequest(
362344
setBridgeDataUIRequestItem: SetBridgeDataUIRequestItem
363345
) {

app/src/main/java/pl/gov/mc/protegosafe/worker/HandleFcmNotificationWorker.kt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import pl.gov.mc.protegosafe.domain.model.FcmNotificationMapper
1111
import pl.gov.mc.protegosafe.domain.model.PushNotificationItem
1212
import pl.gov.mc.protegosafe.domain.repository.ActivitiesRepository
1313
import pl.gov.mc.protegosafe.domain.usecase.ShowPushNotificationUseCase
14-
import pl.gov.mc.protegosafe.domain.usecase.UpdateCovidStatsUseCase
14+
import pl.gov.mc.protegosafe.domain.usecase.info.UpdateDashboardUseCase
1515

1616
class HandleFcmNotificationWorker(
1717
appContext: Context,
@@ -21,7 +21,7 @@ class HandleFcmNotificationWorker(
2121
private val showPushNotificationUseCase: ShowPushNotificationUseCase by inject()
2222
private val fcmNotificationMapper: FcmNotificationMapper by inject()
2323
private val activitiesRepository: ActivitiesRepository by inject()
24-
private val updateCovidStatsUseCase: UpdateCovidStatsUseCase by inject()
24+
private val updateDashboardUseCase: UpdateDashboardUseCase by inject()
2525

2626
private val notificationData by lazy {
2727
mutableMapOf<String, String>().apply {
@@ -42,7 +42,7 @@ class HandleFcmNotificationWorker(
4242
}
4343
}.andThen(
4444
Completable.defer {
45-
updateCovidStatsIfAvailable(notificationData)
45+
updateDashboardIfAvailable(notificationData)
4646
}
4747
)
4848
.toSingleDefault(Result.success())
@@ -67,10 +67,9 @@ class HandleFcmNotificationWorker(
6767
}
6868
}
6969

70-
private fun updateCovidStatsIfAvailable(notificationData: Map<String, String>): Completable {
71-
return fcmNotificationMapper.getCovidStatsItem(notificationData)
72-
.flatMapCompletable {
73-
updateCovidStatsUseCase.execute(it)
74-
}
70+
private fun updateDashboardIfAvailable(notificationData: Map<String, String>): Completable {
71+
return fcmNotificationMapper
72+
.getDashboard(notificationData)
73+
.flatMapCompletable(updateDashboardUseCase::execute)
7574
}
7675
}

0 commit comments

Comments
 (0)