Commit b087f1c8 authored by Harri Kirik's avatar Harri Kirik
Browse files

Merge branch 'feature/COVAPP-462-cross-country-strings' into 'develop'

Update cross-country strings

See merge request hoia/dp3t-app-android!135
parents a39d9b47 b7b235f6
...@@ -175,6 +175,7 @@ class DebugMenuFragment : MvvmFragment(), ViewBindingHolder<FragmentDebugBinding ...@@ -175,6 +175,7 @@ class DebugMenuFragment : MvvmFragment(), ViewBindingHolder<FragmentDebugBinding
buttonDebugStateContactNotification.setOnClickListener { notifier.createNewContactNotification(requireActivity(), -1) } buttonDebugStateContactNotification.setOnClickListener { notifier.createNewContactNotification(requireActivity(), -1) }
buttonDebugStatePreShareScreen.setOnClickListener { setupAndNavigateToPreShareScreen() } buttonDebugStatePreShareScreen.setOnClickListener { setupAndNavigateToPreShareScreen() }
buttonDebugStateShareScreenError.setOnClickListener { showShareDeniedErrorDialog() } buttonDebugStateShareScreenError.setOnClickListener { showShareDeniedErrorDialog() }
buttonDebugStateShareScreenSuccess.setOnClickListener { showShareSuccessScreen() }
buttonDebugStateOpenSettingsAndScrollToCrossCountry.setOnClickListener { openSettingsAndScrollToCrossCountry() } buttonDebugStateOpenSettingsAndScrollToCrossCountry.setOnClickListener { openSettingsAndScrollToCrossCountry() }
buttonDebugStateCrossCountryPopUp.setOnClickListener { openCrossCountryPopUp() } buttonDebugStateCrossCountryPopUp.setOnClickListener { openCrossCountryPopUp() }
} }
...@@ -282,6 +283,11 @@ class DebugMenuFragment : MvvmFragment(), ViewBindingHolder<FragmentDebugBinding ...@@ -282,6 +283,11 @@ class DebugMenuFragment : MvvmFragment(), ViewBindingHolder<FragmentDebugBinding
findNavController().navigate(DebugMenuFragmentDirections.crossCountryPopUp()) findNavController().navigate(DebugMenuFragmentDirections.crossCountryPopUp())
} }
private fun showShareSuccessScreen() {
// Navigate
findNavController().navigate(DebugMenuFragmentDirections.confirmInfectionResult(PatientPortalResult.DebugJustDone))
}
companion object { companion object {
private const val TAG_DIALOG_ERROR = "DebugFragment.TAG_DIALOG_ERROR" private const val TAG_DIALOG_ERROR = "DebugFragment.TAG_DIALOG_ERROR"
private const val TAG_DIALOG_SHARE_ERROR = "DebugFragment.TAG_DIALOG_SHARE_ERROR" private const val TAG_DIALOG_SHARE_ERROR = "DebugFragment.TAG_DIALOG_SHARE_ERROR"
......
...@@ -30,14 +30,14 @@ object IcefireEnvironment : Environment { ...@@ -30,14 +30,14 @@ object IcefireEnvironment : Environment {
ru = "https://www.hoia.me/ru?source=app" ru = "https://www.hoia.me/ru?source=app"
) )
override val contactInfoPageUrl: LocalizedUrl = LocalizedUrl( override val contactInfoPageUrl: LocalizedUrl = LocalizedUrl(
et = "https://www.hoia.me/contact?source=app", et = "https://www.hoia.me/close-contact?source=app",
en = "https://www.hoia.me/en/contact?source=app", en = "https://www.hoia.me/en/close-contact?source=app",
ru = "https://www.hoia.me/ru/contact?source=app" ru = "https://www.hoia.me/ru/close-contact?source=app"
) )
override val privacyPolicyUrl: LocalizedUrl = LocalizedUrl( override val privacyPolicyUrl: LocalizedUrl = LocalizedUrl(
et = "https://hoia.me/privacy?source=app", et = "https://www.hoia.me/privacy?source=app",
en = "https://hoia.me/en/privacy?source=app", en = "https://www.hoia.me/en/privacy?source=app",
ru = "https://hoia.me/ru/privacy?source=app" ru = "https://www.hoia.me/ru/privacy?source=app"
) )
override val covidInstructionsUrl: LocalizedUrl = LocalizedUrl( override val covidInstructionsUrl: LocalizedUrl = LocalizedUrl(
et = "https://www.terviseamet.ee/et/patsiendi-koduse-ravi-juhend-covid-19-korral", et = "https://www.terviseamet.ee/et/patsiendi-koduse-ravi-juhend-covid-19-korral",
...@@ -45,9 +45,14 @@ object IcefireEnvironment : Environment { ...@@ -45,9 +45,14 @@ object IcefireEnvironment : Environment {
ru = "https://www.terviseamet.ee/ru/instrukciya-po-lecheniyu-na-domu-pacienta-s-covid-19" ru = "https://www.terviseamet.ee/ru/instrukciya-po-lecheniyu-na-domu-pacienta-s-covid-19"
) )
override val healthBoardRecommendationsUrl: LocalizedUrl = LocalizedUrl( override val healthBoardRecommendationsUrl: LocalizedUrl = LocalizedUrl(
et = "https://www.terviseamet.ee/et/lahikontaktse-juhis", et = "https://www.terviseamet.ee/et/lahikontaktse-juhis#est",
en = "https://www.terviseamet.ee/et/lahikontaktse-juhis#ENG", en = "https://www.terviseamet.ee/et/lahikontaktse-juhis#eng",
ru = "https://www.terviseamet.ee/et/lahikontaktse-juhis#RUS" ru = "https://www.terviseamet.ee/et/lahikontaktse-juhis#rus"
)
override val gotSickAbroadUrl: LocalizedUrl = LocalizedUrl(
et = "https://www.hoia.me/hoia-euroopas?source=app",
en = "https://www.hoia.me/en/hoia-in-europe?source=app",
ru = "https://hoia.me/ru/hoia-v-yevrope?source=app"
) )
override val appLogEnabled: Boolean = BuildConfig.DEBUG override val appLogEnabled: Boolean = BuildConfig.DEBUG
override val crashAppOnUndeliverableException: Boolean = BuildConfig.DEBUG override val crashAppOnUndeliverableException: Boolean = BuildConfig.DEBUG
...@@ -55,9 +60,4 @@ object IcefireEnvironment : Environment { ...@@ -55,9 +60,4 @@ object IcefireEnvironment : Environment {
override val allowInfectionConfirmationStartWithoutGAEN: Boolean = BuildConfig.DEBUG override val allowInfectionConfirmationStartWithoutGAEN: Boolean = BuildConfig.DEBUG
override val federationGatewayUsageForDP3TBackend: FederationGatewayUsageForDP3TBackend = FederationGatewayUsageForDP3TBackend.Enabled override val federationGatewayUsageForDP3TBackend: FederationGatewayUsageForDP3TBackend = FederationGatewayUsageForDP3TBackend.Enabled
override val federationGatewayUsageForPatientPortal: FederationGatewayUsageForPatientPortal = FederationGatewayUsageForPatientPortal.Enabled override val federationGatewayUsageForPatientPortal: FederationGatewayUsageForPatientPortal = FederationGatewayUsageForPatientPortal.Enabled
override val gotSickAbroadUrl: LocalizedUrl = LocalizedUrl(
et = "https://www.hoia.me/got-sick-abroad?source=app",
en = "https://www.hoia.me/got-sick-abroad/en?source=app",
ru = "https://www.hoia.me/got-sick-abroad/ru?source=app"
)
} }
...@@ -27,6 +27,10 @@ interface Environment { ...@@ -27,6 +27,10 @@ interface Environment {
val covidInstructionsUrl: LocalizedUrl val covidInstructionsUrl: LocalizedUrl
val healthBoardRecommendationsUrl: LocalizedUrl val healthBoardRecommendationsUrl: LocalizedUrl
val privacyPolicyUrl: LocalizedUrl val privacyPolicyUrl: LocalizedUrl
/**
* URL to Hoia.me page's got sick abroad information.
*/
val gotSickAbroadUrl: LocalizedUrl
// Is app logging enabled? // Is app logging enabled?
val appLogEnabled: Boolean val appLogEnabled: Boolean
// Should we display the long version string with backend and SDK info? // Should we display the long version string with backend and SDK info?
...@@ -45,8 +49,4 @@ interface Environment { ...@@ -45,8 +49,4 @@ interface Environment {
* Flag to use when doing PP side infection confirmation. See [FederationGatewayUsageForPatientPortal] for more. * Flag to use when doing PP side infection confirmation. See [FederationGatewayUsageForPatientPortal] for more.
*/ */
val federationGatewayUsageForPatientPortal: FederationGatewayUsageForPatientPortal val federationGatewayUsageForPatientPortal: FederationGatewayUsageForPatientPortal
/**
* URL to Hoia.me page's got sick abroad information.
*/
val gotSickAbroadUrl: LocalizedUrl
} }
...@@ -69,6 +69,16 @@ fun TextView.addUrlSpans() { ...@@ -69,6 +69,16 @@ fun TextView.addUrlSpans() {
fun TextView.setTextWithClickableSpan(source: String, clickablePart: String, clickListener: () -> Unit) { fun TextView.setTextWithClickableSpan(source: String, clickablePart: String, clickListener: () -> Unit) {
val spannable = SpannableString(source) val spannable = SpannableString(source)
addClickableSpan(spannable, clickablePart, clickListener)
this.text = spannable
movementMethod = LinkMovementMethod.getInstance()
}
private fun TextView.addClickableSpan(
spannable: SpannableString,
clickablePart: String,
clickListener: () -> Unit
) {
spannable.addSpan( spannable.addSpan(
clickablePart, clickablePart,
object : ClickableSpan() { object : ClickableSpan() {
...@@ -82,8 +92,6 @@ fun TextView.setTextWithClickableSpan(source: String, clickablePart: String, cli ...@@ -82,8 +92,6 @@ fun TextView.setTextWithClickableSpan(source: String, clickablePart: String, cli
} }
} }
) )
this.text = spannable
movementMethod = LinkMovementMethod.getInstance()
} }
private fun updateDrawStateWithPaint(paint: TextPaint, context: Context) { private fun updateDrawStateWithPaint(paint: TextPaint, context: Context) {
......
...@@ -17,6 +17,7 @@ import org.dpppt.android.app.common.util.ViewBindingHolder ...@@ -17,6 +17,7 @@ import org.dpppt.android.app.common.util.ViewBindingHolder
import org.dpppt.android.app.common.util.ViewModelFactory import org.dpppt.android.app.common.util.ViewModelFactory
import org.dpppt.android.app.common.util.addUrlSpans import org.dpppt.android.app.common.util.addUrlSpans
import org.dpppt.android.app.common.util.exhaustive import org.dpppt.android.app.common.util.exhaustive
import org.dpppt.android.app.common.util.setTextWithBoldSpans
import org.dpppt.android.app.common.util.setTextWithClickableSpan import org.dpppt.android.app.common.util.setTextWithClickableSpan
import org.dpppt.android.app.databinding.FragmentContactsBinding import org.dpppt.android.app.databinding.FragmentContactsBinding
import org.dpppt.android.app.di.Injector import org.dpppt.android.app.di.Injector
...@@ -64,8 +65,8 @@ class ContactsFragment : MvvmFragment(R.layout.fragment_contacts), ViewBindingHo ...@@ -64,8 +65,8 @@ class ContactsFragment : MvvmFragment(R.layout.fragment_contacts), ViewBindingHo
private fun handleAction(action: ContactsViewModel.Action) { private fun handleAction(action: ContactsViewModel.Action) {
when (action) { when (action) {
is ContactsViewModel.Action.NavigateHome -> findNavController().navigate(ContactsFragmentDirections.home()) is ContactsViewModel.Action.NavigateHome -> returnHomeWithoutRestart()
is ContactsViewModel.Action.OpenContactsInfoUrl -> startActivity(Intent(Intent.ACTION_VIEW).setData(Uri.parse(action.url))) is ContactsViewModel.Action.OpenContactsInfoUrl -> startActivitySafely(Intent(Intent.ACTION_VIEW).setData(Uri.parse(action.url)))
is ContactsViewModel.Action.OpenHealthBoardRecommendationsUrl -> startActivitySafely( is ContactsViewModel.Action.OpenHealthBoardRecommendationsUrl -> startActivitySafely(
Intent(Intent.ACTION_VIEW).setData( Intent(Intent.ACTION_VIEW).setData(
Uri.parse(action.url) Uri.parse(action.url)
...@@ -74,26 +75,33 @@ class ContactsFragment : MvvmFragment(R.layout.fragment_contacts), ViewBindingHo ...@@ -74,26 +75,33 @@ class ContactsFragment : MvvmFragment(R.layout.fragment_contacts), ViewBindingHo
}.exhaustive }.exhaustive
} }
private fun returnHomeWithoutRestart() {
findNavController().popBackStack()
}
private fun showContacts(contacts: InfectedStatus) { private fun showContacts(contacts: InfectedStatus) {
if (contacts !is InfectedStatus.HasContacts) { if (contacts !is InfectedStatus.HasContacts) {
return return
} }
requireBinding { requireBinding {
titleView.text = resources.getQuantityString(R.plurals.contacts_detected_title, contacts.num, contacts.num) titleView.text = resources.getQuantityString(R.plurals.contacts_detected_title, contacts.num, contacts.num)
descriptionStayHomeView.text = setupStayHomeText(contacts)
getString(R.string.contacts_detected_text_stay_home, DateUtils.getFormattedLocalDate(contacts.stayHomeUntilDate))
} }
} }
private fun FragmentContactsBinding.setupStayHomeText(contacts: InfectedStatus.HasContacts) {
val dateString = DateUtils.getFormattedLocalDate(contacts.stayHomeUntilDate)
val message = getString(R.string.contacts_detected_text_stay_home, dateString)
descriptionStayHomeView.setTextWithBoldSpans(message, dateString)
}
private fun initClickableText() { private fun initClickableText() {
requireBinding { requireBinding {
descriptionCallView.addUrlSpans() descriptionCallView.addUrlSpans()
healthBoardRecommendationsView.setTextWithClickableSpan( healthBoardRecommendationsView.setTextWithClickableSpan(
getString(R.string.contacts_health_board_recommendations_link), getString(R.string.contacts_health_board_recommendations),
getString(R.string.contacts_health_board_recommendations_link_clickable_part) getString(R.string.contacts_health_board_recommendations_clickable_part),
) { ) { viewModel.healthBoardRecommendationsClicked() }
viewModel.healthBoardRecommendationsClicked()
}
} }
} }
} }
...@@ -32,4 +32,14 @@ sealed class PatientPortalResult : Parcelable { ...@@ -32,4 +32,14 @@ sealed class PatientPortalResult : Parcelable {
return "PatientPortalResult.Error(exception=$exception)" return "PatientPortalResult.Error(exception=$exception)"
} }
} }
/**
* A debug option that allows to navigate directly to specific steps in the infection confirmation process.
*/
@Parcelize
object DebugJustDone : PatientPortalResult() {
override fun toString(): String {
return "PatientPortalResult.DebugJustDone()"
}
}
} }
...@@ -17,11 +17,11 @@ import androidx.navigation.fragment.findNavController ...@@ -17,11 +17,11 @@ import androidx.navigation.fragment.findNavController
import mobi.lab.mvvm.MvvmFragment import mobi.lab.mvvm.MvvmFragment
import org.dpppt.android.app.BuildConfig import org.dpppt.android.app.BuildConfig
import org.dpppt.android.app.R import org.dpppt.android.app.R
import org.dpppt.android.app.common.util.ViewBindingHolder import org.dpppt.android.app.common.util.DateUtils
import org.dpppt.android.app.common.util.FragmentBindingHolder import org.dpppt.android.app.common.util.FragmentBindingHolder
import org.dpppt.android.app.common.util.ViewBindingHolder
import org.dpppt.android.app.common.util.ViewModelFactory import org.dpppt.android.app.common.util.ViewModelFactory
import org.dpppt.android.app.common.util.exhaustive import org.dpppt.android.app.common.util.exhaustive
import org.dpppt.android.app.common.util.DateUtils
import org.dpppt.android.app.common.util.setTextWithBoldSpans import org.dpppt.android.app.common.util.setTextWithBoldSpans
import org.dpppt.android.app.databinding.FragmentHomeBinding import org.dpppt.android.app.databinding.FragmentHomeBinding
import org.dpppt.android.app.di.Injector import org.dpppt.android.app.di.Injector
......
...@@ -15,6 +15,7 @@ import org.dpppt.android.app.domain.usecase.infection.patientportal.PreparePatie ...@@ -15,6 +15,7 @@ import org.dpppt.android.app.domain.usecase.infection.patientportal.PreparePatie
import org.dpppt.android.app.domain.usecase.infection.request.DeleteConfirmInfectionRequestUseCase import org.dpppt.android.app.domain.usecase.infection.request.DeleteConfirmInfectionRequestUseCase
import org.dpppt.android.app.util.dispose import org.dpppt.android.app.util.dispose
import timber.log.Timber import timber.log.Timber
import java.lang.IllegalArgumentException
import javax.inject.Inject import javax.inject.Inject
class ConfirmInfectionPatientPortalViewModel @Inject constructor( class ConfirmInfectionPatientPortalViewModel @Inject constructor(
...@@ -74,6 +75,10 @@ class ConfirmInfectionPatientPortalViewModel @Inject constructor( ...@@ -74,6 +75,10 @@ class ConfirmInfectionPatientPortalViewModel @Inject constructor(
cleanupAndContinueWithTheResult(portalResult) cleanupAndContinueWithTheResult(portalResult)
true true
} }
is PatientPortalResult.DebugJustDone -> {
// Not supported here
throw IllegalArgumentException("The PatientPortalResult.DebugJustDone is not supported for this screen!")
}
}.exhaustive }.exhaustive
} }
......
...@@ -46,6 +46,7 @@ class ConfirmInfectionResultViewModel @Inject constructor( ...@@ -46,6 +46,7 @@ class ConfirmInfectionResultViewModel @Inject constructor(
PatientPortalResult.InProgress -> { PatientPortalResult.InProgress -> {
// No-op, will not happen here // No-op, will not happen here
} }
is PatientPortalResult.DebugJustDone -> onSendInfectedStatusSuccess()
}.exhaustive }.exhaustive
} }
......
...@@ -78,7 +78,8 @@ class MyDataFragment : MvvmFragment(R.layout.fragment_my_data), ViewBindingHolde ...@@ -78,7 +78,8 @@ class MyDataFragment : MvvmFragment(R.layout.fragment_my_data), ViewBindingHolde
when (action) { when (action) {
is MyDataViewModel.Action.ShowDeleteSuccess -> showDeleteSuccess() is MyDataViewModel.Action.ShowDeleteSuccess -> showDeleteSuccess()
is MyDataViewModel.Action.ShowDeleteError -> showDeleteError(action.error) is MyDataViewModel.Action.ShowDeleteError -> showDeleteError(action.error)
is MyDataViewModel.Action.NavigateToHomeRestart -> findNavController().navigate(MyDataFragmentDirections.homeRestart()) is MyDataViewModel.Action.NavigateToHomeRestart -> returnHomeWithRestart()
is MyDataViewModel.Action.NavigateToHomeWithoutRestart -> returnHomeWithoutRestart()
is MyDataViewModel.Action.OpenPrivacyPolicyUrl -> startActivitySafely( is MyDataViewModel.Action.OpenPrivacyPolicyUrl -> startActivitySafely(
Intent(Intent.ACTION_VIEW).setData( Intent(Intent.ACTION_VIEW).setData(
Uri.parse( Uri.parse(
...@@ -90,6 +91,14 @@ class MyDataFragment : MvvmFragment(R.layout.fragment_my_data), ViewBindingHolde ...@@ -90,6 +91,14 @@ class MyDataFragment : MvvmFragment(R.layout.fragment_my_data), ViewBindingHolde
}.exhaustive }.exhaustive
} }
private fun returnHomeWithRestart() {
findNavController().navigate(MyDataFragmentDirections.homeRestart())
}
private fun returnHomeWithoutRestart() {
findNavController().popBackStack()
}
private fun showDeleteSuccess() { private fun showDeleteSuccess() {
showToast(R.string.my_data_delete_success) showToast(R.string.my_data_delete_success)
} }
......
...@@ -28,7 +28,7 @@ class MyDataViewModel @Inject constructor( ...@@ -28,7 +28,7 @@ class MyDataViewModel @Inject constructor(
} }
fun onReturnHomeClicked() { fun onReturnHomeClicked() {
restartToHome() returnToHome()
} }
fun onPrivacyPolicyClicked() { fun onPrivacyPolicyClicked() {
...@@ -54,6 +54,10 @@ class MyDataViewModel @Inject constructor( ...@@ -54,6 +54,10 @@ class MyDataViewModel @Inject constructor(
_action.value = Event(Action.NavigateToHomeRestart) _action.value = Event(Action.NavigateToHomeRestart)
} }
private fun returnToHome() {
_action.value = Event(Action.NavigateToHomeWithoutRestart)
}
private fun onDeleteSuccess() { private fun onDeleteSuccess() {
_action.value = Event(Action.ShowDeleteSuccess) _action.value = Event(Action.ShowDeleteSuccess)
restartToHome() restartToHome()
...@@ -68,5 +72,6 @@ class MyDataViewModel @Inject constructor( ...@@ -68,5 +72,6 @@ class MyDataViewModel @Inject constructor(
data class ShowDeleteError(val error: DomainException) : Action() data class ShowDeleteError(val error: DomainException) : Action()
data class OpenPrivacyPolicyUrl(val url: String) : Action() data class OpenPrivacyPolicyUrl(val url: String) : Action()
object NavigateToHomeRestart : Action() object NavigateToHomeRestart : Action()
object NavigateToHomeWithoutRestart : Action()
} }
} }
package org.dpppt.android.app.settings package org.dpppt.android.app.settings
import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
...@@ -26,6 +27,7 @@ import org.dpppt.android.app.common.util.ViewBindingHolder ...@@ -26,6 +27,7 @@ import org.dpppt.android.app.common.util.ViewBindingHolder
import org.dpppt.android.app.common.util.ViewModelFactory import org.dpppt.android.app.common.util.ViewModelFactory
import org.dpppt.android.app.common.util.exhaustive import org.dpppt.android.app.common.util.exhaustive
import org.dpppt.android.app.common.util.getAppVersionString import org.dpppt.android.app.common.util.getAppVersionString
import org.dpppt.android.app.common.util.getTextWithBlueSpans
import org.dpppt.android.app.databinding.FragmentSettingsBinding import org.dpppt.android.app.databinding.FragmentSettingsBinding
import org.dpppt.android.app.di.Injector import org.dpppt.android.app.di.Injector
import org.dpppt.android.app.storage.SecureStorage import org.dpppt.android.app.storage.SecureStorage
...@@ -65,6 +67,10 @@ class SettingsFragment : MvvmFragment(), ViewBindingHolder<FragmentSettingsBindi ...@@ -65,6 +67,10 @@ class SettingsFragment : MvvmFragment(), ViewBindingHolder<FragmentSettingsBindi
initViewModel() initViewModel()
viewModel.start(tracingViewModel.appStatusLiveData, args.scrollDestination, savedInstanceState == null) viewModel.start(tracingViewModel.appStatusLiveData, args.scrollDestination, savedInstanceState == null)
setOnBackPressed() setOnBackPressed()
setupViews(view)
}
private fun setupViews(view: View) {
requireBinding { requireBinding {
batteryButton.setOnClickListener { batteryButton.setOnClickListener {
viewModel.batteryButtonClicked() viewModel.batteryButtonClicked()
...@@ -74,13 +80,25 @@ class SettingsFragment : MvvmFragment(), ViewBindingHolder<FragmentSettingsBindi ...@@ -74,13 +80,25 @@ class SettingsFragment : MvvmFragment(), ViewBindingHolder<FragmentSettingsBindi
viewModel.activateBluetooth() viewModel.activateBluetooth()
} }
buttonBack.setOnClickListener { navigateBack() } buttonBack.setOnClickListener { navigateBack() }
setupVersionView(view.context)
versionText.text = getAppVersionString(view.context, env.showLongVersionInfo)
versionText.setOnClickListener { viewModel.onVersionClicked() }
languageLayout.setOnClickListener { showLanguageSelectionDialog() } languageLayout.setOnClickListener { showLanguageSelectionDialog() }
setupCrossCountryView(view.context)
} }
} }
private fun FragmentSettingsBinding.setupVersionView(context: Context) {
versionText.text = getAppVersionString(context, env.showLongVersionInfo)
versionText.setOnClickListener { viewModel.onVersionClicked() }
}
private fun FragmentSettingsBinding.setupCrossCountryView(context: Context) {
crossCountryDescription.text = context.getTextWithBlueSpans(
getString(R.string.settings_cross_country_description),
getString(R.string.settings_cross_country_description_blue_part),
)
crossCountryDescription.setOnClickListener { viewModel.crossCountryInfoLinkClicked() }
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
viewModel.start(tracingViewModel.appStatusLiveData, args.scrollDestination, false) viewModel.start(tracingViewModel.appStatusLiveData, args.scrollDestination, false)
...@@ -103,9 +121,12 @@ class SettingsFragment : MvvmFragment(), ViewBindingHolder<FragmentSettingsBindi ...@@ -103,9 +121,12 @@ class SettingsFragment : MvvmFragment(), ViewBindingHolder<FragmentSettingsBindi
} }
is SettingsViewModel.Action.OpenPlayStoreUrl -> is SettingsViewModel.Action.OpenPlayStoreUrl ->
startActivitySafely(Intent(Intent.ACTION_VIEW).setData(Uri.parse(URL_PLAY_STORE))) startActivitySafely(Intent(Intent.ACTION_VIEW).setData(Uri.parse(URL_PLAY_STORE)))
SettingsViewModel.Action.ScrollToCrossCountryItem -> { is SettingsViewModel.Action.ScrollToCrossCountryItem -> {
scrollToCrossCountryItem() scrollToCrossCountryItem()
} }
is SettingsViewModel.Action.OpenCrossCountryInfoUrl -> {
startActivitySafely(Intent(Intent.ACTION_VIEW).setData(Uri.parse(action.url)))
}
}.exhaustive }.exhaustive
} }
......
...@@ -23,6 +23,7 @@ import org.dpppt.android.app.domain.usecase.dp3t.GaenStartUseCase ...@@ -23,6 +23,7 @@ import org.dpppt.android.app.domain.usecase.dp3t.GaenStartUseCase
import org.dpppt.android.app.domain.usecase.dp3t.GaenStopUseCase import org.dpppt.android.app.domain.usecase.dp3t.GaenStopUseCase
import org.dpppt.android.app.domain.usecase.dp3t.GaenSyncUseCase import org.dpppt.android.app.domain.usecase.dp3t.GaenSyncUseCase
import org.dpppt.android.app.domain.usecase.dp3t.IsGaenWorkingUseCase import org.dpppt.android.app.domain.usecase.dp3t.IsGaenWorkingUseCase
import org.dpppt.android.app.domain.usecase.infopage.CreateGotSickAbroadPageUrlUseCase
import org.dpppt.android.app.domain.usecase.permissions.CheckBatteryOptimizationUseCase import org.dpppt.android.app.domain.usecase.permissions.CheckBatteryOptimizationUseCase
import org.dpppt.android.app.main.model.TracingStatusInterface import org.dpppt.android.app.main.model.TracingStatusInterface
import org.dpppt.android.app.util.dispose import org.dpppt.android.app.util.dispose
...@@ -36,7 +37,8 @@ class SettingsViewModel @Inject constructor( ...@@ -36,7 +37,8 @@ class SettingsViewModel @Inject constructor(
private val gaenStartUseCase: GaenStartUseCase, private val gaenStartUseCase: GaenStartUseCase,
private val gaenStopUseCase: GaenStopUseCase, private val gaenStopUseCase: GaenStopUseCase,
private val activityService: ActivityService, private val activityService: ActivityService,
private val syncUseCase: GaenSyncUseCase private val syncUseCase: GaenSyncUseCase,
private val createGotSickAbroadPageUrlUseCase: CreateGotSickAbroadPageUrlUseCase
) : ViewModel() { ) : ViewModel() {
private val _action = MutableLiveData<Event<Action>>() private val _action = MutableLiveData<Event<Action>>()
...@@ -53,6 +55,9 @@ class SettingsViewModel @Inject constructor( ...@@ -53,6 +55,9 @@ class SettingsViewModel @Inject constructor(
private var disposables: List<Disposable> = listOf() private var disposables: List<Disposable> = listOf()
// Let's use a different disposable for links as these are one-shot things
private var linkDisposable: Disposable? = null
private val tracingStatusObserver = Observer(::tracingStatusChanged) private val tracingStatusObserver = Observer(::tracingStatusChanged)
fun start(status: LiveData<TracingStatusInterface>, settingsScrollDestination: SettingsScrollDestination, isFirstStart: Boolean) { fun start(status: LiveData<TracingStatusInterface>, settingsScrollDestination: SettingsScrollDestination, isFirstStart: Boolean) {
...@@ -191,6 +196,20 @@ class SettingsViewModel @Inject constructor( ...@@ -191,6 +196,20 @@ class SettingsViewModel @Inject constructor(
{ error -> Timber.e(error, "Sync error") } { error -> Timber.e(error, "Sync error") }
) )
fun crossCountryInfoLinkClicked() {
dispose(linkDisposable)
// For now this will be the same URL as on the Home screen
linkDisposable = createGotSickAbroadPageUrlUseCase.execute()
.backgroundToMain()
.subscribe(
{ url -> _action.value = Event(Action.OpenCrossCountryInfoUrl(url)) },
{ error ->
Timber.e(error, "crossCountryInfoLinkClicked")
// NO-OP: This should not happen atm. But for the future we still want to consume this
}
)
}
sealed class Action { sealed class Action {
data class GaenError(val e: Throwable) : Action() data class GaenError(val e: Throwable) : Action()
object BluetoothError : Action() object BluetoothError : Action()
...@@ -198,5 +217,6 @@ class SettingsViewModel @Inject constructor( ...@@ -198,5 +217,6 @@ class SettingsViewModel @Inject constructor(
data class ShowPlayServicesUpdateDialog(val isUpdateRequired: Boolean) : Action() data class ShowPlayServicesUpdateDialog(val isUpdateRequired: Boolean) : Action()
object OpenPlayStoreUrl : Action() object OpenPlayStoreUrl : Action()
object ScrollToCrossCountryItem : Action() object ScrollToCrossCountryItem : Action()
data class OpenCrossCountryInfoUrl(val url: String) : Action()
} }
} }