Skip to content

Commit

Permalink
Merge 3436ae1 into 75f331e
Browse files Browse the repository at this point in the history
  • Loading branch information
ktiniatros authored Sep 29, 2021
2 parents 75f331e + 3436ae1 commit d55c86a
Show file tree
Hide file tree
Showing 27 changed files with 222 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import nl.rijksoverheid.ctr.appconfig.persistence.*
import nl.rijksoverheid.ctr.appconfig.repositories.ConfigRepository
import nl.rijksoverheid.ctr.appconfig.repositories.ConfigRepositoryImpl
import nl.rijksoverheid.ctr.appconfig.usecases.*
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
Expand All @@ -26,7 +28,7 @@ import retrofit2.Retrofit
* @param path Path for the config api, for example "holder" to fetch the config from <baseurl>/holder/config
* @param versionCode version code
*/
fun appConfigModule(path: String, versionCode: Int) = module {
fun appConfigModule(cdnUrl: String, path: String, versionCode: Int) = module {
factory<ConfigRepository> { ConfigRepositoryImpl(get()) }
factory<AppConfigUseCase> { AppConfigUseCaseImpl(get(), get(), get(), get()) }
factory<AppStatusUseCase> {
Expand Down Expand Up @@ -62,7 +64,7 @@ fun appConfigModule(path: String, versionCode: Int) = module {
single {
val okHttpClient = get<OkHttpClient>(OkHttpClient::class).newBuilder().build()
val retrofit = get<Retrofit>(Retrofit::class)
val baseUrl = retrofit.baseUrl().newBuilder().addPathSegments("$path/").build()
val baseUrl = cdnUrl.toHttpUrl().newBuilder().addPathSegments("$path/").build()
retrofit.newBuilder().baseUrl(baseUrl).client(okHttpClient).build()
.create(AppConfigApi::class.java)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.view.ContextThemeWrapper
import android.view.accessibility.AccessibilityManager
import androidx.annotation.AttrRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat
import nl.rijksoverheid.ctr.design.R

/*
Expand Down Expand Up @@ -35,10 +36,17 @@ fun Context.isScreenReaderOn(): Boolean {
return false
}

fun Context.getThemeColor(@AttrRes attribute: Int): ColorStateList = TypedValue().let {
fun Context.getThemeColorStateList(@AttrRes attribute: Int): ColorStateList = TypedValue().let {
theme.resolveAttribute(
attribute,
it,
true
); AppCompatResources.getColorStateList(this, it.resourceId)
}

fun Context.getAttrColor(@AttrRes id: Int): Int {
val resolvedAttr = TypedValue()
this.theme.resolveAttribute(id, resolvedAttr, true)
val colorRes = resolvedAttr.run { if (resourceId != 0) resourceId else data }
return ContextCompat.getColor(this, colorRes)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.BulletSpan
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
Expand Down Expand Up @@ -40,6 +41,14 @@ class HtmlTextViewWidget @JvmOverloads constructor(
private val HEADING_MARGIN_MULTIPLIER = 1.0f
private val LIST_ITEM_MARGIN_MULTIPLIER = 0.25f

private val textColorPrimary by lazy {
context.getAttrColor(android.R.attr.textColorPrimary)
}

private val textColorLink by lazy {
context.getAttrColor(android.R.attr.textColorLink)
}

// Reflects the unparsed HTML text shown in the subviews. Can only be set internally.
var text: String? = null
private set
Expand All @@ -59,10 +68,12 @@ class HtmlTextViewWidget @JvmOverloads constructor(
if (htmlText?.isNotEmpty() == true) {
setHtmlText(
htmlText = htmlText.toString(),
htmlTextColor = getColor(R.styleable.HtmlTextViewWidget_htmlTextColor, textColorPrimary),
htmlTextColorLink = getColor(R.styleable.HtmlTextViewWidget_htmlTextColorLink, textColorLink),
htmlLinksEnabled = getBoolean(R.styleable.HtmlTextViewWidget_enableHtmlLinks, HTML_LINKS_ENABLED),
paragraphMarginMultiplier = getFloat(R.styleable.HtmlTextViewWidget_enableHtmlLinks, PARAGRAPH_MARGIN_MULTIPLIER),
headingMarginMultiplier = getFloat(R.styleable.HtmlTextViewWidget_enableHtmlLinks, HEADING_MARGIN_MULTIPLIER),
listItemMarginMultiplier = getFloat(R.styleable.HtmlTextViewWidget_enableHtmlLinks, LIST_ITEM_MARGIN_MULTIPLIER)
listItemMarginMultiplier = getFloat(R.styleable.HtmlTextViewWidget_enableHtmlLinks, LIST_ITEM_MARGIN_MULTIPLIER),
)
}
} finally {
Expand All @@ -89,6 +100,8 @@ class HtmlTextViewWidget @JvmOverloads constructor(
fun setHtmlText(
htmlText: String,
htmlLinksEnabled: Boolean = HTML_LINKS_ENABLED,
htmlTextColor: Int = textColorPrimary,
htmlTextColorLink: Int = textColorLink,
paragraphMarginMultiplier: Float = PARAGRAPH_MARGIN_MULTIPLIER,
headingMarginMultiplier: Float = HEADING_MARGIN_MULTIPLIER,
listItemMarginMultiplier: Float = LIST_ITEM_MARGIN_MULTIPLIER
Expand All @@ -109,6 +122,8 @@ class HtmlTextViewWidget @JvmOverloads constructor(
// Step 3: Add a HtmlTextView for each part of the Spannable
parts.forEachIndexed { index, part ->
val textView = HtmlTextView(context)
textView.setTextColor(htmlTextColor)
textView.setLinkTextColor(htmlTextColorLink)
textView.text = part

// Mark as heading?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import com.google.android.material.button.MaterialButton
import nl.rijksoverheid.ctr.design.R
import nl.rijksoverheid.ctr.design.ext.getThemeColor
import nl.rijksoverheid.ctr.design.ext.getThemeColorStateList

class OutlinedToggleButtonWidget @JvmOverloads constructor(
context: Context,
Expand All @@ -32,7 +32,7 @@ class OutlinedToggleButtonWidget @JvmOverloads constructor(
fun setToggled(isToggled: Boolean) {
this.isToggled = isToggled
if (isToggled) {
backgroundTintList = context.getThemeColor(R.attr.colorSurface)
backgroundTintList = context.getThemeColorStateList(R.attr.colorSurface)
setStrokeColorResource(R.color.primary_blue)
ViewCompat.setElevation(this, 2f)
contentDescription = "$text - ${context.getString(R.string.accessibility_label_selected)}"
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
</declare-styleable>
<declare-styleable name="HtmlTextViewWidget">
<attr name="htmlText" format="string" />
<attr name="htmlTextColor" format="color" />
<attr name="htmlTextColorLink" format="color" />
<attr name="enableHtmlLinks" format="boolean" />
<attr name="listItemMarginMultiplier" format="float" />
<attr name="headingMarginMultiplier" format="float" />
Expand Down
5 changes: 4 additions & 1 deletion holder/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

def appVersionCode = System.getenv("GITHUB_RUN_NUMBER") != null ? System.getenv("GITHUB_RUN_NUMBER").toInteger() : 1000000
version = "2.3.2"
version = "2.3.3"
archivesBaseName = "holder-v${version}-${appVersionCode}"

android {
Expand Down Expand Up @@ -40,6 +40,7 @@ android {
"{" +
"\"sha256/lR7gRvqDMW5nhsCMRPE7TKLq0tJkTWMxQ5HAzHCIfQ0=\"" +
"}"
buildConfigField "String", "CDN_API_URL", "\"https://holder-api-cdn.coronacheck.nl/v5/\""
manifestPlaceholders = [appLabel: "@string/app_name", deepLinkHost: "coronacheck.nl", digidSchema: "coronacheck"]

javaCompileOptions {
Expand Down Expand Up @@ -89,13 +90,15 @@ android {
}
acc {
buildConfigField "String", "BASE_API_URL", "\"https://holder-api.acc.coronacheck.nl/v5/\""
buildConfigField "String", "CDN_API_URL", "\"https://holder-api-cdn.acc.coronacheck.nl/v5/\""
buildConfigField "String", "DIGI_D_BASE_URL", "\"https://tvs.acc.coronacheck.nl\""
buildConfigField "String", "DIGI_D_CLIENT_ID", "\"cc_app\""
buildConfigField "String", "DIGI_D_REDIRECT_URI", "\"https://web.acc.coronacheck.nl/app/auth2\""
buildConfigField "String[]", "CERTIFICATE_PINS",
"{" +
"\"sha256/lR7gRvqDMW5nhsCMRPE7TKLq0tJkTWMxQ5HAzHCIfQ0=\"" +
"}"
buildConfigField "String", "CDN_API_URL", "\"https://holder-api-cdn.acc.coronacheck.nl/v5/\""
dimension "environment"
versionNameSuffix "-acc"
applicationIdSuffix ".acc"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ abstract class BaseFragment(contentLayoutId: Int) : Fragment(contentLayoutId) {
*/
abstract fun onButtonClickWithRetryAction()

open fun onButtonClickWithRetryTitle(): Int {
return R.string.dialog_retry
}

/**
* Get the current [Flow] for this screen
*/
Expand All @@ -33,7 +37,7 @@ abstract class BaseFragment(contentLayoutId: Int) : Fragment(contentLayoutId) {
context = requireContext(),
title = R.string.dialog_no_internet_connection_title,
message = getString(R.string.dialog_no_internet_connection_description),
positiveButtonText = R.string.dialog_retry,
positiveButtonText = onButtonClickWithRetryTitle(),
positiveButtonCallback = {
onButtonClickWithRetryAction()
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ open class HolderApplication : SharedApplication(), Configuration.Provider {
BuildConfig.CERTIFICATE_PINS,
),
sharedModule,
appConfigModule("holder", BuildConfig.VERSION_CODE),
appConfigModule(BuildConfig.CDN_API_URL,"holder", BuildConfig.VERSION_CODE),
introductionModule,
*getAdditionalModules().toTypedArray(),
designModule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import nl.rijksoverheid.ctr.holder.persistence.database.usecases.*
import nl.rijksoverheid.ctr.holder.ui.create_qr.util.GreenCardUtil
import nl.rijksoverheid.ctr.shared.models.ErrorResult
import nl.rijksoverheid.ctr.shared.models.NetworkRequestResult
import java.time.OffsetDateTime

/*
* Copyright (c) 2021 De Staat der Nederlanden, Ministerie van Volksgezondheid, Welzijn en Sport.
Expand All @@ -23,8 +24,12 @@ interface HolderDatabaseSyncer {
* Synchronized the database. Does cleanup in the database based on expiration dates and can resync with remote
* @param expectedOriginType If not null checks if the remote credentials contain this origin. Will return [DatabaseSyncerResult.MissingOrigin] if it's not present.
* @param syncWithRemote If true and the data call to resync succeeds, clear all green cards in the database and re-add them
* @param previousSyncResult The previous result outputted by this [sync] if known
*/
suspend fun sync(expectedOriginType: OriginType? = null, syncWithRemote: Boolean = true): DatabaseSyncerResult
suspend fun sync(
expectedOriginType: OriginType? = null,
syncWithRemote: Boolean = true,
previousSyncResult: DatabaseSyncerResult? = null): DatabaseSyncerResult
}

class HolderDatabaseSyncerImpl(
Expand All @@ -39,7 +44,8 @@ class HolderDatabaseSyncerImpl(

override suspend fun sync(
expectedOriginType: OriginType?,
syncWithRemote: Boolean
syncWithRemote: Boolean,
previousSyncResult: DatabaseSyncerResult?
): DatabaseSyncerResult {
return withContext(Dispatchers.IO) {
mutex.withLock {
Expand Down Expand Up @@ -93,9 +99,15 @@ class HolderDatabaseSyncerImpl(
)
}
is NetworkRequestResult.Failed.CoronaCheckHttpError -> {
DatabaseSyncerResult.Failed.ServerError(
errorResult = remoteGreenCardsResult.errorResult
)
if (previousSyncResult == null) {
DatabaseSyncerResult.Failed.ServerError.FirstTime(
errorResult = remoteGreenCardsResult.errorResult
)
} else {
DatabaseSyncerResult.Failed.ServerError.MultipleTimes(
errorResult = remoteGreenCardsResult.errorResult
)
}
}
else -> {
DatabaseSyncerResult.Failed.Error(
Expand All @@ -106,21 +118,23 @@ class HolderDatabaseSyncerImpl(
}
}
} else {
DatabaseSyncerResult.Success
previousSyncResult ?: DatabaseSyncerResult.Success
}
}
}
}
}

sealed class DatabaseSyncerResult {
object Loading : DatabaseSyncerResult()
object Success : DatabaseSyncerResult()
object MissingOrigin : DatabaseSyncerResult()

sealed class Failed(open val errorResult: ErrorResult): DatabaseSyncerResult() {
data class NetworkError(override val errorResult: ErrorResult, val hasGreenCardsWithoutCredentials: Boolean): Failed(errorResult)
data class ServerError(override val errorResult: ErrorResult): Failed(errorResult)
data class Error(override val errorResult: ErrorResult): Failed(errorResult)
sealed class Failed(open val errorResult: ErrorResult, open val failedAt: OffsetDateTime): DatabaseSyncerResult() {
data class NetworkError(override val errorResult: ErrorResult, val hasGreenCardsWithoutCredentials: Boolean): Failed(errorResult, OffsetDateTime.now())
sealed class ServerError(override val errorResult: ErrorResult): Failed(errorResult, OffsetDateTime.now()) {
data class FirstTime(override val errorResult: ErrorResult) : ServerError(errorResult)
data class MultipleTimes(override val errorResult: ErrorResult) : ServerError(errorResult)
}
data class Error(override val errorResult: ErrorResult): Failed(errorResult, OffsetDateTime.now())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,10 @@ import org.koin.androidx.viewmodel.scope.emptyState
CommercialTestCodeFragmentDirections.actionYourEvents(
type = YourEventsFragmentType.RemoteProtocol3Type(
mapOf(result.remoteTestResult to result.signedResponseWithTestResult.rawResponse),
originType = OriginType.Test
originType = OriginType.Test,
fromCommercialTestCode = true
),
toolbarTitle = getString(R.string.commercial_test_type_title)
toolbarTitle = getString(R.string.commercial_test_type_title),
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import nl.rijksoverheid.ctr.holder.persistence.database.DatabaseSyncerResult
import nl.rijksoverheid.ctr.holder.persistence.database.entities.OriginType
import nl.rijksoverheid.ctr.holder.ui.create_qr.items.YourEventWidget
import nl.rijksoverheid.ctr.holder.ui.create_qr.models.*
import nl.rijksoverheid.ctr.holder.ui.create_qr.usecases.ConfigProvidersUseCase
import nl.rijksoverheid.ctr.holder.ui.create_qr.util.InfoScreenUtil
import nl.rijksoverheid.ctr.holder.ui.create_qr.util.RemoteEventUtil
import nl.rijksoverheid.ctr.holder.ui.create_qr.util.RemoteProtocol3Util
Expand Down Expand Up @@ -57,9 +56,15 @@ class YourEventsFragment : BaseFragment(R.layout.fragment_your_events) {

private val yourEventsViewModel: YourEventsViewModel by viewModel()

private val configProvidersUseCase: ConfigProvidersUseCase by inject()
override fun onButtonClickWithRetryTitle(): Int {
return R.string.my_overview
}

override fun onButtonClickWithRetryAction() {
navigateSafety(YourEventsFragmentDirections.actionMyOverview())
}

private fun retrieveGreenCards() {
when (val type = args.type) {
is YourEventsFragmentType.TestResult2 -> {
yourEventsViewModel.saveNegativeTest2(
Expand Down Expand Up @@ -91,7 +96,11 @@ class YourEventsFragment : BaseFragment(R.layout.fragment_your_events) {
is YourEventsFragmentType.RemoteProtocol3Type -> {
return when (type.originType) {
is OriginType.Test -> {
HolderFlow.DigidTest
if (type.fromCommercialTestCode) {
HolderFlow.CommercialTest
} else {
HolderFlow.DigidTest
}
}
is OriginType.Recovery -> {
HolderFlow.Recovery
Expand Down Expand Up @@ -547,7 +556,7 @@ class YourEventsFragment : BaseFragment(R.layout.fragment_your_events) {

private fun handleButton(binding: FragmentYourEventsBinding) {
binding.bottom.setButtonClick {
onButtonClickWithRetryAction()
retrieveGreenCards()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sealed class YourEventsFragmentType : Parcelable {
val remoteEvents: Map<RemoteProtocol3, ByteArray>,
val originType: OriginType,
val eventProviders: List<EventProvider> = emptyList(),
val fromCommercialTestCode: Boolean = false
) : YourEventsFragmentType(), Parcelable

@Parcelize
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
/*
* Copyright (c) 2021 De Staat der Nederlanden, Ministerie van Volksgezondheid, Welzijn en Sport.
* Licensed under the EUROPEAN UNION PUBLIC LICENCE v. 1.2
*
* SPDX-License-Identifier: EUPL-1.2
*
*/
package nl.rijksoverheid.ctr.holder.ui.create_qr.models

sealed class DashboardErrorState {
object None: DashboardErrorState()
object RetryErrorState: DashboardErrorState()
object HelpdeskErrorState: DashboardErrorState()
}

data class DashboardItems(
val domesticItems: List<DashboardItem>,
val internationalItems: List<DashboardItem>
)
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package nl.rijksoverheid.ctr.holder.ui.create_qr.repositories

import android.net.NetworkRequest
import android.util.Base64
import nl.rijksoverheid.ctr.api.factory.NetworkRequestResultFactory
import nl.rijksoverheid.ctr.shared.models.NetworkRequestResult
Expand Down
Loading

0 comments on commit d55c86a

Please sign in to comment.