Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

Commit

Permalink
feat: add customer support info (#243)
Browse files Browse the repository at this point in the history
* feat: add last check date in support screen

* fix: add missing divider

* fix: last check date format

* feat: plug real last check date

* fix: avoid force unwrapping

* refactor: expose last check date as state flow

Co-authored-by: Stefano Rodriguez <[email protected]>
Co-authored-by: Marco Uberti <[email protected]>
  • Loading branch information
3 people authored Jul 6, 2020
1 parent b321ba8 commit 00716c5
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class ExposureManager(

val exposureStatus = exposureStatusRepository.exposureStatus

val lastSuccessfulCheckDate = exposureReportingRepository.lastSuccessfulCheckDate

suspend fun updateAndGetServiceIsActive(): Boolean {
exposureNotificationManager.update()
return exposureNotificationManager.areExposureNotificationsEnabled.value ?: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import it.ministerodellasalute.immuni.extensions.storage.KVStorage
import it.ministerodellasalute.immuni.extensions.utils.DateUtils.MILLIS_IN_A_DAY
import it.ministerodellasalute.immuni.logic.exposure.models.ExposureSummary
import java.util.Date
import kotlinx.coroutines.flow.StateFlow

class ExposureReportingRepository(
private val storage: KVStorage
Expand All @@ -31,6 +32,7 @@ class ExposureReportingRepository(
companion object {
private val summariesKey = KVStorage.Key<ExposureSummaryList>("summaries")
private val lastProcessedChunkKey = KVStorage.Key<Int>("LastProcessedChunk")
private val lastSuccessfulCheckDateKey = KVStorage.Key<Date>("LastSuccessfulCheckDate")
}

fun getSummaries(): List<ExposureSummary> {
Expand Down Expand Up @@ -74,4 +76,11 @@ class ExposureReportingRepository(
storage[lastProcessedChunkKey] = value
}
}

val lastSuccessfulCheckDate: StateFlow<Date?>
get() = storage.stateFlow(lastSuccessfulCheckDateKey)

fun setLastSuccessfulCheckDate(value: Date) {
storage[lastSuccessfulCheckDateKey] = value
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright (C) 2020 Presidenza del Consiglio dei Ministri.
* Please refer to the AUTHORS file for more information.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package it.ministerodellasalute.immuni.ui.support

import android.annotation.SuppressLint
Expand Down Expand Up @@ -65,7 +80,8 @@ class SupportDialogFragment : PopupDialogFragment() {
"${getString(R.string.support_info_item_bluetoothEnabled)}: ${viewModel.isBluetoothEnabled.value}",
"${getString(R.string.support_info_item_appVersion)}: ${viewModel.appVersion.value}",
"Google Play Services: ${viewModel.googlePlayVersion.value}",
"${getString(R.string.support_info_item_connectionType)}: ${viewModel.connectionType.value}"
"${getString(R.string.support_info_item_connectionType)}: ${viewModel.connectionType.value}",
"${getString(R.string.support_info_item_lastencheck)}: ${viewModel.lastCheckDate.value}"
).joinToString(separator = "; ", postfix = ".")

startSendingEmail(it, subject = "", message = message)
Expand Down Expand Up @@ -103,6 +119,9 @@ class SupportDialogFragment : PopupDialogFragment() {
viewModel.connectionType.observe(viewLifecycleOwner) {
connectionType.text = it
}
viewModel.lastCheckDate.observe(viewLifecycleOwner) {
lastCheckDate.text = it
}

openFaq.setSafeOnClickListener {
dismiss()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
/*
* Copyright (C) 2020 Presidenza del Consiglio dei Ministri.
* Please refer to the AUTHORS file for more information.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package it.ministerodellasalute.immuni.ui.support

import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.os.Build
import android.text.format.DateFormat
import androidx.core.content.pm.PackageInfoCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.liveData
import com.google.android.gms.common.GoogleApiAvailability
import it.ministerodellasalute.immuni.BuildConfig
import it.ministerodellasalute.immuni.R
import it.ministerodellasalute.immuni.logic.exposure.ExposureManager
import it.ministerodellasalute.immuni.logic.settings.ConfigurationSettingsManager
import java.util.*
import kotlinx.coroutines.flow.map

class SupportViewModel(
val context: Context,
Expand Down Expand Up @@ -44,19 +63,23 @@ class SupportViewModel(

val isExposureNotificationEnabled = liveData {
val enabled = exposureManager.isBroadcastingActive.value
emit(when (enabled) {
true -> context.getString(R.string.support_info_active_plural)
else -> context.getString(R.string.support_info_not_active_plural)
})
emit(
when (enabled) {
true -> context.getString(R.string.support_info_active_plural)
else -> context.getString(R.string.support_info_not_active_plural)
}
)
}

val isBluetoothEnabled = liveData {
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
val enabled = bluetoothAdapter?.isEnabled ?: false
emit(when (enabled) {
true -> context.getString(R.string.support_info_active)
false -> context.getString(R.string.support_info_not_active)
})
emit(
when (enabled) {
true -> context.getString(R.string.support_info_active)
false -> context.getString(R.string.support_info_not_active)
}
)
}

val appVersion = liveData {
Expand Down Expand Up @@ -93,4 +116,15 @@ class SupportViewModel(
)
}
}

val lastCheckDate = exposureManager.lastSuccessfulCheckDate.map { date ->
val lastCheckDateStr = if (date != null) {
val dateStr = DateFormat.getLongDateFormat(context).format(date)
val timeStr = DateFormat.getTimeFormat(context).format(date)
context.getString(R.string.support_info_item_lastencheck_date, dateStr, timeStr)
} else {
context.getString(R.string.support_info_item_lastencheck_none)
}
lastCheckDateStr
}.asLiveData()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package it.ministerodellasalute.immuni.workers
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import it.ministerodellasalute.immuni.BuildConfig
import it.ministerodellasalute.immuni.R
import it.ministerodellasalute.immuni.api.immuniApiCall
import it.ministerodellasalute.immuni.api.services.ExposureReportingService
Expand Down Expand Up @@ -102,13 +103,14 @@ class RequestDiagnosisKeysWorker(
mkdir()
}

val serverDate = settingsResult.serverDate
val indexResponse = immuniApiCall { api.index() }

if (indexResponse !is NetworkResource.Success) {
val error = indexResponse.error
// 404 means that the list is empty, so the work is successful
if (error is NetworkError.HttpError && error.httpCode == 404) {
return@withTimeout success()
return@withTimeout success(serverDate)
}

return@withTimeout Result.retry()
Expand All @@ -132,7 +134,7 @@ class RequestDiagnosisKeysWorker(
try {
chunkResponse.data?.byteStream()?.saveToFile(filePath)
?: return@withTimeout Result.retry()
val token = "${UUID.randomUUID()}_${settingsResult.serverDate.time}"
val token = "${UUID.randomUUID()}_${serverDate.time}"
exposureManager.provideDiagnosisKeys(
keyFiles = listOf(File(filePath)),
token = token
Expand All @@ -142,7 +144,7 @@ class RequestDiagnosisKeysWorker(
return@withTimeout Result.retry()
}
}
return@withTimeout success()
return@withTimeout success(serverDate)
}
} catch (e: Exception) {
return Result.retry()
Expand All @@ -151,7 +153,11 @@ class RequestDiagnosisKeysWorker(
}
}

private fun success(): Result {
private fun success(serverDate: Date): Result {
exposureReportingRepository.setLastSuccessfulCheckDate(when (BuildConfig.DEBUG) {
true -> Date()
false -> serverDate
})
workerManager.scheduleNextDiagnosisKeysRequest()
return Result.success()
}
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/res/layout/support_dialog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,20 @@
tools:text="WI-FI" />
</LinearLayout>

<include layout="@layout/support_information_content_divider" />

<LinearLayout style="@style/SupportInformationRow">

<TextView
style="@style/SupportInformationKey"
android:text="@string/support_info_item_lastencheck" />

<TextView
android:id="@+id/lastCheckDate"
style="@style/SupportInformationValue"
tools:text="22 luglio 2020 alle 22:20" />
</LinearLayout>

</LinearLayout>

</com.google.android.material.card.MaterialCardView>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ Operating system: iOS 13.5.1; Model: iPhone XS; Exposure notifications: Active;
<string name="support_info_item_bluetoothEnabled">Bluetooth</string>
<string name="support_info_item_appVersion">App version</string>
<string name="support_info_item_connectionType">Connection</string>
<string name="support_info_item_lastencheck">Ultima verifica</string>
<string name="support_info_item_lastencheck_none">Nessuna</string>
<string name="support_info_item_lastencheck_date">%s alle %s</string>
<string name="permission_tutorial_deactivate_service_first_message_android">To protect your health and the health of your loved ones, only disable the service if necessary and reactivate it as soon as you can.</string>
<string name="support_info_active">Active</string>
<string name="support_info_not_active">Not active</string>
Expand Down

0 comments on commit 00716c5

Please sign in to comment.