Commit 0c4576f8 authored by stopcovid@lunabee.com's avatar stopcovid@lunabee.com
Browse files

Update to 3.4.0

- Fix SIDEP positive test
- trim DCC fields
- support DCC non-FR
- Change modules order main screen
parent 796d54ee
......@@ -201,7 +201,6 @@ internal fun ApiConfiguration.toDomain(gson: Gson) = Configuration(
),
cleaReportApiVersion = cleaReportApiVersion,
cleaStatusApiVersion = cleaStatusApiVersion,
displaySanitaryCertificatesValidation = displaySanitaryCertificatesValidation,
isAnalyticsOn = isAnalyticsOn,
analyticsApiVersion = analyticsApiVersion,
testCertificateValidityThresholds = gson.fromJson(testCertificateValidityThresholds, object : TypeToken<List<Int>>() {}.type),
......
......@@ -60,7 +60,6 @@ class Configuration(
var displaySanitaryCertificatesWallet: Boolean,
var walletOldCertificateThresholdInDays: Map<String, Float>,
var walletPublicKeys: List<WalletPublicKey>,
var displaySanitaryCertificatesValidation: Boolean,
var isAnalyticsOn: Boolean,
var analyticsApiVersion: String,
var testCertificateValidityThresholds: List<Int>,
......
......@@ -45,8 +45,8 @@ android {
applicationId "fr.gouv.android.stopcovid"
minSdkVersion 21
targetSdkVersion 30
versionCode 304
versionName "3.3.5"
versionCode 310
versionName "3.4.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
......
......@@ -777,7 +777,7 @@
"home.attestationSection.sanitaryCertificates.cell.subtitle":"Your test and vaccination certificates",
"flashWalletCodeController.title":"Scan",
"flashWalletCodeController.explanation":"Scan the QR Code on your SI-DEP document (test) or certificate (vaccination).",
"confirmWalletQrCodeController.title":"Test wallet",
"confirmWalletQrCodeController.title":"Wallet",
"confirmWalletQrCodeController.explanation.title":"You have just hit a TousAntiCovid link to add a certificate to your wallet.",
"confirmWalletQrCodeController.explanation.subtitle":"Do you want to add this certificate to your wallet?",
"confirmWalletQrCodeController.confirm":"Add",
......@@ -1014,5 +1014,9 @@
"documentExplanationController.vaccinCertificate.title": "Vaccination certificate",
"documentExplanationController.testCertificate.title": "Test certificate",
"documentExplanationController.vaccinCertificate.explanation": "Here is an example of the document from the Assurance Maladie with the vaccination certificate. The QR Code to scan with TousAntiCovid is highlighted with the orange square.\n\n🇪🇺 The brand new French \"EU Digital COVID Certificate\" is also accepted in TousAntiCovid.",
"documentExplanationController.testCertificate.explanation": "Here is an example of the SIDEP document for the test certificate. The QR Code to scan with TousAntiCovid is highlighted with the orange square.\n\n🇪🇺 The brand new French \"EU Digital COVID Certificate\" is also accepted in TousAntiCovid."
"documentExplanationController.testCertificate.explanation": "Here is an example of the SIDEP document for the test certificate. The QR Code to scan with TousAntiCovid is highlighted with the orange square.\n\n🇪🇺 The brand new French \"EU Digital COVID Certificate\" is also accepted in TousAntiCovid.",
"wallet.proof.europe.test.positiveSidepError": "🔴 This certificate is only valid in France, but not for crossing European borders.\nYou must go to https://sidep.gouv.fr to retrieve a recovery certificate and import it in TousAntiCovid.",
"walletController.certificateWarning": "🔴 You have at least one certificate that deserves your attention.",
"walletController.addForeignCertificate.alert.message": "Your \"COVID Europe Certificate\" is not French.\n\nYou can also add it to the wallet, but TousAntiCovid will not verify its authenticity.",
"walletController.addForeignCertificate.alert.add": "Add"
}
......@@ -988,5 +988,9 @@
"documentExplanationController.vaccinCertificate.title": "Attestation de vaccin",
"documentExplanationController.testCertificate.title": "Certificat de test",
"documentExplanationController.vaccinCertificate.explanation": "Voici un exemple de document de l'Assurance Maladie avec le certificat de vaccination. Le QR Code à flasher avec TousAntiCovid est à droite, indiqué par le carré orange.\n\n🇪🇺 Le nouveau \"Certificat COVID Numérique UE\" est également accepté dans TousAntiCovid.",
"documentExplanationController.testCertificate.explanation": "Voici un exemple de document SIDEP avec le certificat du test COVID. Le QR Code à flasher avec TousAntiCovid est à gauche, indiqué par le carré orange.\n\n🇪🇺 Le nouveau \"Certificat COVID Numérique UE\" est également accepté dans TousAntiCovid dès le 25 juin matin."
"documentExplanationController.testCertificate.explanation": "Voici un exemple de document SIDEP avec le certificat du test COVID. Le QR Code à flasher avec TousAntiCovid est à gauche, indiqué par le carré orange.\n\n🇪🇺 Le nouveau \"Certificat COVID Numérique UE\" est également accepté dans TousAntiCovid dès le 25 juin matin.",
"wallet.proof.europe.test.positiveSidepError": "🔴 Ce certificat n’est valable que sur le territoire français, mais pas pour passer les frontières européennes.\nVous devez vous rendre sur https://sidep.gouv.fr pour récupérer un certificat de rétablissement et l’importer dans TousAntiCovid.",
"walletController.certificateWarning": "🔴 Vous avez au moins un certificat qui mérite votre attention.",
"walletController.addForeignCertificate.alert.message": "Votre \"Certificat COVID Europe\" n'est pas français.\n\nVous pouvez l'ajouter également dans le carnet, mais TousAntiCovid ne vérifiera pas son authenticité.",
"walletController.addForeignCertificate.alert.add": "Ajouter"
}
......@@ -185,7 +185,6 @@ class MainActivity : BaseActivity() {
R.id.venueQrCodeFragment,
R.id.walletQRCodeFragment,
R.id.universalQrScanFragment,
R.id.verifyWalletQRCodeFragment,
R.id.vaccineCompletionFragment,
).contains(destination.id).let { noAppBarFragment ->
lifecycleScope.launchWhenResumed {
......
......@@ -34,8 +34,19 @@ val GreenCertificate.certificateType: WalletCertificateType?
fun GreenCertificate.formattedDateOfBirthDate(dateFormat: DateFormat): String =
yearMonthDayUsParser().parseOrNull(dateOfBirth)?.let(dateFormat::format) ?: dateOfBirth
val GreenCertificate.countryCode: String?
get() = when {
vaccinations?.lastOrNull() != null -> vaccinations?.lastOrNull()?.countryOfVaccination
tests?.lastOrNull() != null -> tests?.lastOrNull()?.countryOfVaccination
recoveryStatements?.lastOrNull() != null -> recoveryStatements?.lastOrNull()?.countryOfVaccination
else -> null
}
val GreenCertificate.isFrench: Boolean
get() = this.countryCode == Locale.FRANCE.country
val GreenCertificate.vaccineMedicinalProduct: String?
get() = vaccinations?.lastOrNull()?.medicinalProduct
get() = vaccinations?.lastOrNull()?.medicinalProduct?.trim()
val GreenCertificate.vaccineDate: Date?
get() = vaccinations?.lastOrNull()?.dateOfVaccination?.let(yearMonthDayUsParser()::parseOrNull)
......@@ -47,7 +58,10 @@ val GreenCertificate.vaccineDose: Pair<Int, Int>?
}
val GreenCertificate.testType: String?
get() = tests?.lastOrNull()?.typeOfTest
get() = tests?.lastOrNull()?.typeOfTest?.trim()
val GreenCertificate.testResultIsNegative: Boolean?
get() = tests?.lastOrNull()?.isResultNegative()
val GreenCertificate.testResultCode: String?
get() = tests?.lastOrNull()?.isResultNegative()?.let { isNegative ->
......
......@@ -93,4 +93,17 @@ fun String.fixQuoteInString(): String = replace("'", "")
fun String?.safeParseColor(): Int = Color.parseColor(this ?: "#0B0091")
fun String?.orNA(): String = this ?: "N/A"
\ No newline at end of file
fun String?.orNA(): String = this ?: "N/A"
// https://stackoverflow.com/a/35849652/10935947
val String.countryCodeToFlagEmoji: String
get() {
return try {
val firstLetter = Character.codePointAt(this, 0) - 0x41 + 0x1F1E6
val secondLetter = Character.codePointAt(this, 1) - 0x41 + 0x1F1E6
String(Character.toChars(firstLetter)) + String(Character.toChars(secondLetter))
} catch (e: Exception) {
Timber.e(e)
""
}
}
......@@ -100,12 +100,19 @@ fun WalletCertificate.fullDescription(strings: LocalizedStrings, configuration:
text = text?.replace("<$vaxCode>", vaccinationState.orNA())
text ?: ""
}
is EuropeanCertificate -> formatDccText(
strings["wallet.proof.europe.${this.type.code}.description"],
strings,
dateFormat,
analysisDateFormat
)
is EuropeanCertificate -> {
val prefix = if (this.greenCertificate.isFrench) {
""
} else {
this.greenCertificate.countryCode?.countryCodeToFlagEmoji ?: ""
}
formatDccText(
prefix + strings["wallet.proof.europe.${this.type.code}.description"],
strings,
dateFormat,
analysisDateFormat
)
}
}
}
......@@ -124,7 +131,7 @@ fun EuropeanCertificate.formatDccText(
Timber.e("Unexpected type ${this.type} with ${this.javaClass.simpleName}")
}
WalletCertificateType.VACCINATION_EUROPE -> {
val vacName = this.greenCertificate.vaccineMedicinalProduct?.let { strings["vac.product.$it"] }
val vacName = this.greenCertificate.vaccineMedicinalProduct?.let { strings["vac.product.$it"] ?: it }
formattedText = formattedText?.replace("<VACCINE_NAME>", vacName.orNA())
formattedText = formattedText?.replace("<DATE>", this.greenCertificate.vaccineDate?.let(dateFormat::format).orNA())
}
......@@ -135,7 +142,7 @@ fun EuropeanCertificate.formatDccText(
)
}
WalletCertificateType.SANITARY_EUROPE -> {
val testName = this.greenCertificate.testType?.let { strings["test.man.$it"] }
val testName = this.greenCertificate.testType?.let { strings["test.man.$it"] ?: it }
formattedText = formattedText?.replace("<ANALYSIS_CODE>", testName.orNA())
val testResult = this.greenCertificate.testResultCode?.let { strings["wallet.proof.europe.test.$it"] }
formattedText = formattedText?.replace("<ANALYSIS_RESULT>", testResult.orNA())
......
......@@ -12,6 +12,9 @@ package com.lunabeestudio.stopcovid.fastitem
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.text.Spannable
import android.text.method.LinkMovementMethod
import android.text.style.URLSpan
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
......@@ -26,7 +29,8 @@ import com.mikepenz.fastadapter.binding.AbstractBindingItem
class QrCodeCardItem : AbstractBindingItem<ItemQrCodeCardBinding>() {
var generateBarcode: (() -> Bitmap)? = null
var text: String? = null
var mainDescription: String? = null
var footerDescription: Spannable? = null
var tag1Text: String? = null
var tag2Text: String? = null
var formatText: String? = null
......@@ -58,7 +62,15 @@ class QrCodeCardItem : AbstractBindingItem<ItemQrCodeCardBinding>() {
override fun bindView(binding: ItemQrCodeCardBinding, payloads: List<Any>) {
super.bindView(binding, payloads)
binding.textView.text = text
binding.mainDescriptionTextView.text = mainDescription
binding.footerDescriptionTextView.setTextOrHide(footerDescription)
footerDescription?.let { spannable ->
if (spannable.nextSpanTransition(0, spannable.length, URLSpan::class.java) != spannable.length) {
binding.footerDescriptionTextView.movementMethod = LinkMovementMethod.getInstance()
} else {
binding.footerDescriptionTextView.movementMethod = null
}
}
val bitmap = generateBarcode?.invoke()
binding.imageView.setImageBitmap(bitmap)
......
......@@ -184,7 +184,7 @@ class AttestationsFragment : MainFragment() {
}
return qrCodeCardItem {
this.generateBarcode = generateBarcode
text = attestation.footer
mainDescription = attestation.footer
share = strings["attestationsController.menu.share"]
delete = strings["attestationsController.menu.delete"]
this.allowShare = allowShare
......@@ -222,7 +222,7 @@ class AttestationsFragment : MainFragment() {
)
}
actionContentDescription = strings["accessibility.hint.otherActions"]
identifier = text.hashCode().toLong()
identifier = mainDescription.hashCode().toLong()
}
}
}
......@@ -27,6 +27,7 @@ import com.lunabeestudio.stopcovid.databinding.FragmentFullscreenDccBinding
import com.lunabeestudio.stopcovid.extension.dccCertificatesManager
import com.lunabeestudio.stopcovid.extension.formatDccText
import com.lunabeestudio.stopcovid.extension.fullName
import com.lunabeestudio.stopcovid.extension.isFrench
import com.lunabeestudio.stopcovid.extension.robertManager
import com.lunabeestudio.stopcovid.extension.secureKeystoreDataSource
import com.lunabeestudio.stopcovid.model.EuropeanCertificate
......@@ -77,7 +78,7 @@ class FullscreenDccFragment : ForceLightFragment(R.layout.fragment_fullscreen_dc
.map { certificates ->
certificates
?.filterIsInstance<EuropeanCertificate>()
?.firstOrNull { it.keyCertificateId == args.keyCertificateId }
?.firstOrNull { it.value == args.certificateValue }
}
.observe(viewLifecycleOwner) { europeanCertificate ->
this.europeanCertificate = europeanCertificate
......@@ -89,6 +90,7 @@ class FullscreenDccFragment : ForceLightFragment(R.layout.fragment_fullscreen_dc
val europeanCertificate = europeanCertificate ?: return
binding?.apply {
logosImageView.isVisible = europeanCertificate.greenCertificate.isFrench
val minLines = strings["europeanCertificate.fullscreen.englishDescription.${europeanCertificate.type.code}"]
?.count { it == '\n' }
?.plus(1)
......
......@@ -452,6 +452,12 @@ class ProximityFragment : TimeMainFragment() {
}
addSectionSeparator(items)
// Attestation
if (robertManager.configuration.displayAttestation || robertManager.configuration.displaySanitaryCertificatesWallet) {
addAttestationItems(items)
addSectionSeparator(items)
}
// Health items
addHealthItems(items, showAsSick)
if (robertManager.configuration.displayIsolation) {
......@@ -465,22 +471,16 @@ class ProximityFragment : TimeMainFragment() {
}
addSectionSeparator(items)
// News items
addNewsItems(items)
addSectionSeparator(items)
// Attestation
if (robertManager.configuration.displayAttestation || robertManager.configuration.displaySanitaryCertificatesWallet) {
addAttestationItems(items)
addSectionSeparator(items)
}
// Venue items
if (robertManager.configuration.displayRecordVenues) {
addVenueItems(items, isSick)
addSectionSeparator(items)
}
// News items
addNewsItems(items)
addSectionSeparator(items)
// More items
addMoreItems(items)
addSectionSeparator(items)
......@@ -984,13 +984,6 @@ class ProximityFragment : TimeMainFragment() {
Action(R.drawable.ic_settings, strings["common.settings"]) {
findNavControllerOrNull()?.safeNavigate(ProximityFragmentDirections.actionProximityFragmentToManageDataFragment())
},
Action(R.drawable.ic_2d_doc, strings["home.moreSection.verifySanitaryCertificate"]) {
findNavControllerOrNull()?.safeNavigate(
ProximityFragmentDirections.actionProximityFragmentToVerifyWalletQRCodeFragment()
)
}.takeIf {
robertManager.configuration.displaySanitaryCertificatesValidation
},
Action(R.drawable.ic_privacy, strings["home.moreSection.privacy"]) {
findNavControllerOrNull()?.safeNavigate(ProximityFragmentDirections.actionProximityFragmentToPrivacyFragment())
},
......
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/04/05 - for the TOUS-ANTI-COVID project
*/
package com.lunabeestudio.stopcovid.fragment
import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.lunabeestudio.stopcovid.coreui.extension.findNavControllerOrNull
import com.lunabeestudio.stopcovid.extension.dccCertificatesManager
import com.lunabeestudio.stopcovid.extension.robertManager
import com.lunabeestudio.stopcovid.extension.safeNavigate
import com.lunabeestudio.stopcovid.extension.showUnknownErrorAlert
import com.lunabeestudio.stopcovid.manager.WalletManager
import com.lunabeestudio.stopcovid.model.WalletCertificateInvalidSignatureException
import com.lunabeestudio.stopcovid.model.WalletCertificateMalformedException
import com.lunabeestudio.stopcovid.model.WalletCertificateNoKeyError
import kotlinx.coroutines.launch
import timber.log.Timber
class VerifyWalletQRCodeFragment : QRCodeFragment() {
private val robertManager by lazy {
requireContext().robertManager()
}
private val dccCertificatesManager by lazy {
requireContext().dccCertificatesManager()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
isReadyToStartScanFlow = true
}
override fun getTitleKey(): String = "flashDataMatrixCodeController.title"
override fun getExplanationKey(): String = "flashDataMatrixCodeController.explanation"
override fun onCodeScanned(code: String) {
lifecycleScope.launch {
try {
WalletManager.verifyCertificateCodeValue(
robertManager.configuration,
code,
dccCertificatesManager.certificates,
null,
)
findNavControllerOrNull()?.safeNavigate(
VerifyWalletQRCodeFragmentDirections.actionVerifyWalletQRCodeFragmentToVerifyWalletResultFragment(
code
)
)
} catch (e: Exception) {
catchWalletException(e) {
resumeQrCodeReader()
}
}
}
}
private fun catchWalletException(e: Exception, listener: DialogInterface.OnDismissListener?) {
Timber.e(e)
when (e) {
is WalletCertificateInvalidSignatureException -> showInvalidCertificateSignatureAlert(listener)
is WalletCertificateMalformedException -> showMalformedCertificateAlert(listener)
is WalletCertificateNoKeyError -> showInvalidCertificateSignatureAlert(listener)
else -> showUnknownErrorAlert(listener)
}
}
private fun showMalformedCertificateAlert(listener: DialogInterface.OnDismissListener?) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(strings["wallet.proof.error.1.title"])
.setMessage(strings["wallet.proof.error.1.message"])
.setPositiveButton(strings["common.ok"], null)
.setOnDismissListener(listener)
.show()
}
private fun showInvalidCertificateSignatureAlert(listener: DialogInterface.OnDismissListener?) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(strings["wallet.proof.error.2.title"])
.setMessage(strings["wallet.proof.error.2.message"])
.setPositiveButton(strings["common.ok"], null)
.setOnDismissListener(listener)
.show()
}
}
\ No newline at end of file
package com.lunabeestudio.stopcovid.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.navArgs
import com.lunabeestudio.stopcovid.coreui.extension.appCompatActivity
import com.lunabeestudio.stopcovid.coreui.extension.findNavControllerOrNull
import com.lunabeestudio.stopcovid.coreui.fragment.BaseFragment
import com.lunabeestudio.stopcovid.databinding.FragmentVerifyWalletResultBinding
import com.lunabeestudio.stopcovid.extension.dccCertificatesManager
import com.lunabeestudio.stopcovid.extension.fullDescription
import com.lunabeestudio.stopcovid.extension.robertManager
import com.lunabeestudio.stopcovid.extension.safeNavigate
import com.lunabeestudio.stopcovid.manager.WalletManager
import com.lunabeestudio.stopcovid.model.WalletCertificate
import kotlinx.coroutines.launch
class VerifyWalletResultFragment : BaseFragment() {
private var binding: FragmentVerifyWalletResultBinding? = null
private val args: VerifyWalletResultFragmentArgs by navArgs()
private val titleKey: String = "flashDataMatrixCodeController.title"
private var certificate: WalletCertificate? = null
private val robertManager by lazy {
requireContext().robertManager()
}
private val dccCertificatesManager by lazy {
requireContext().dccCertificatesManager()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
lifecycleScope.launch {
certificate = try {
WalletManager.verifyCertificateCodeValue(
robertManager.configuration,
args.certificateCode,
dccCertificatesManager.certificates,
null,
)
} catch (e: Exception) {
null
}
refreshScreen()
}
binding = FragmentVerifyWalletResultBinding.inflate(inflater, container, false)
return binding?.root
}
override fun refreshScreen() {
appCompatActivity?.supportActionBar?.title = strings[titleKey]
binding?.textView?.text = certificate?.fullDescription(strings, robertManager.configuration)
binding?.button?.text = strings["walletCertificateVerifiedController.validateAnotherProof"]
binding?.button?.setOnClickListener {
findNavControllerOrNull()?.safeNavigate(
VerifyWalletResultFragmentDirections.actionVerifyWalletResultFragmentToVerifyWalletQRCodeFragment()
)
}
}
}
\ No newline at end of file
......@@ -48,11 +48,13 @@ import com.lunabeestudio.stopcovid.extension.shortDescription
import com.lunabeestudio.stopcovid.extension.showUnknownErrorAlert
import com.lunabeestudio.stopcovid.extension.statusStringKey
import com.lunabeestudio.stopcovid.extension.tagStringKey
import com.lunabeestudio.stopcovid.extension.testResultIsNegative
import com.lunabeestudio.stopcovid.extension.vaccineDose
import com.lunabeestudio.stopcovid.fastitem.QrCodeCardItem
import com.lunabeestudio.stopcovid.fastitem.bigTitleItem
import com.lunabeestudio.stopcovid.fastitem.qrCodeCardItem
import com.lunabeestudio.stopcovid.manager.ShareManager
import com.lunabeestudio.stopcovid.manager.WalletManager
import com.lunabeestudio.stopcovid.model.EuropeanCertificate
import com.lunabeestudio.stopcovid.model.FrenchCertificate
import com.lunabeestudio.stopcovid.model.SanitaryCertificate
......@@ -116,6 +118,20 @@ class WalletCertificateFragment : MainFragment() {
identifier = items.size.toLong()
}
val hasSidepErrorCertificate = viewModel.certificates.value?.any { certificate ->
(certificate as? EuropeanCertificate)?.greenCertificate?.testResultIsNegative == false
} == true
if (hasSidepErrorCertificate) {
items += captionItem {
text = strings["walletController.certificateWarning"]
identifier = text.hashCode().toLong()
}
items += spaceItem {
spaceRes = R.dimen.spacing_large
identifier = items.size.toLong()
}
}
if (!viewModel.recentCertificates.isNullOrEmpty()) {
items += bigTitleItem {
text = strings["walletController.recentCertificatesSection.title"]
......@@ -196,7 +212,15 @@ class WalletCertificateFragment : MainFragment() {
return qrCodeCardItem {
this.generateBarcode = generateBarcode
text = certificate.fullDescription(strings, robertManager.configuration)
mainDescription = certificate.fullDescription(strings, robertManager.configuration)
footerDescription = if ((certificate as? EuropeanCertificate)?.greenCertificate?.testResultIsNegative == false) {
// Fix SIDEP has generated positive test instead of recovery
val span = strings["wallet.proof.europe.test.positiveSidepError"]?.let { SpannableString(it) }
span?.let { Linkify.addLinks(it, Linkify.WEB_URLS) }
span
} else {
null
}
share = strings["walletController.menu.share"]
delete = strings["walletController.menu.delete"]
convertText = strings["walletController.menu.convertToEurope"]
......@@ -220,7 +244,7 @@ class WalletCertificateFragment : MainFragment() {
val uri = barcodeBitmap?.let { bitmap ->
ShareManager.getShareCaptureUriFromBitmap(requireContext(), bitmap, "qrCode")
}
val text = text.takeIf { uri != null }
val text = mainDescription.takeIf { uri != null }
ShareManager.shareImageAndText(requireContext(), uri, text) {
strings["common.error.unknown"]?.let { showErrorSnackBar(it) }
}
......@@ -240,7 +264,7 @@ class WalletCertificateFragment : MainFragment() {
if (certificate is EuropeanCertificate) {
findParentFragmentByType<WalletContainerFragment>()?.findNavControllerOrNull()?.safeNavigate(
WalletContainerFragmentDirections.actionWalletContainerFragmentToFullscreenDccFragment(
certificate.keyCertificateId,
certificate.value,
)
)
} else {
......@@ -328,7 +352,14 @@ class WalletCertificateFragment : MainFragment() {
private suspend fun processConvertedCertificate(certificateCode: String, certificateFormat: WalletCertificateType.Format?): Boolean {
return try {
val certificate = viewModel.processCodeValue(requireContext(), certificateCode, certificateFormat)
val certificate = WalletManager.verifyCertificateCodeValue(
robertManager.configuration,
certificateCode,
dccCertificatesManager.certificates,
certificateFormat,
)
viewModel.saveCertificate(requireContext(), certificate)
val vaccination = (certificate as? EuropeanCertificate)?.greenCertificate?.vaccinations?.lastOrNull()
if (vaccination != null && vaccination.doseNumber >= vaccination.totalSeriesOfDoses) {
......
......@@ -20,6 +20,7 @@ import androidx.fragment.app.setFragmentResultListener
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope