Skip to content

Commit

Permalink
Merge pull request #793 from minvws/2380-deeplink-onboarding-verifier
Browse files Browse the repository at this point in the history
2380 deeplink onboarding verifier
  • Loading branch information
ktiniatros authored Oct 28, 2021
2 parents c6a858d + 2a717df commit 3cfacee
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SetupFragment : Fragment(R.layout.fragment_setup) {

override fun onStart() {
super.onStart()
appStatusViewModel.refresh(mobileCoreWrapper)
appStatusViewModel.refresh(mobileCoreWrapper, true)
}

private fun setObservers() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import nl.rijksoverheid.ctr.shared.MobileCoreWrapper
import nl.rijksoverheid.ctr.shared.livedata.EventObserver
import nl.rijksoverheid.ctr.shared.utils.IntentUtil
import nl.rijksoverheid.ctr.verifier.databinding.ActivityMainBinding
import nl.rijksoverheid.ctr.verifier.ui.scanqr.ScanQrViewModel
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel

Expand All @@ -30,11 +31,15 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
class VerifierMainActivity : AppCompatActivity() {

private val introductionViewModel: IntroductionViewModel by viewModel()
private val appStatusViewModel: AppConfigViewModel by viewModel()
private val appConfigViewModel: AppConfigViewModel by viewModel()
private val scanQrViewModel: ScanQrViewModel by viewModel()
private val mobileCoreWrapper: MobileCoreWrapper by inject()
private val dialogUtil: DialogUtil by inject()
private val intentUtil: IntentUtil by inject()

private var isFreshStart: Boolean = true // track if this is a fresh start of the app
private var returnUri: String? = null // return uri to external app given as argument from deeplink
private var hasHandledDeeplink: Boolean = false

override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.AppTheme)
Expand All @@ -45,10 +50,19 @@ class VerifierMainActivity : AppCompatActivity() {
setProductionFlags()

observeStatuses()
}

// Force retrieval of config once on startup for clock deviation checks
if (introductionViewModel.getIntroductionStatus() is IntroductionStatus.IntroductionFinished) {
appStatusViewModel.refresh(mobileCoreWrapper, force = isFreshStart)
override fun onStart() {
super.onStart()
if (isIntroductionFinished()) {
if (isFreshStart) {
// Force retrieval of config once on startup for clock deviation checks
appConfigViewModel.refresh(mobileCoreWrapper, force = true)
} else {
// Only get app config on every app foreground when introduction is finished and the app has already started
appConfigViewModel.refresh(mobileCoreWrapper)
}
isFreshStart = false
}
}

Expand All @@ -61,11 +75,45 @@ class VerifierMainActivity : AppCompatActivity() {
navController.navigate(R.id.action_introduction, IntroductionFragment.getBundle(it))
})

appStatusViewModel.appStatusLiveData.observe(this, EventObserver {
appConfigViewModel.appStatusLiveData.observe(this, EventObserver {
handleAppStatus(it, navController)
})

navController.addOnDestinationChangedListener { _, destination, arguments ->
// Persist deeplink return uri in case it's not used immediately because of onboarding
if (destination.id == R.id.nav_main) {
arguments?.getString("returnUri")?.let { returnUri = it }
}
navigateDeeplink(navController)

// verifier can stay active for a long time, so it is not sufficient
// to try to refresh the config only every time the app resumes.
// We do track if the app was recently (re)started to avoid double config calls
if (!isFreshStart && isIntroductionFinished()) {
appConfigViewModel.refresh(mobileCoreWrapper)
} else {
isFreshStart = false
}
}
}

private fun navigateDeeplink(navController: NavController) {
if (returnUri != null && !hasHandledDeeplink && isIntroductionFinished()) {
hasHandledDeeplink = true
navController.navigate(
// Show scan instructions before scanner when it's not shown before
if (scanQrViewModel.hasSeenScanInstructions()) {
RootNavDirections.actionScanner(returnUri)
} else {
RootNavDirections.actionScanInstructions(returnUri)
}
)
}
}

private fun isIntroductionFinished() =
introductionViewModel.getIntroductionStatus() is IntroductionStatus.IntroductionFinished

private fun handleAppStatus(
appStatus: AppStatus,
navController: NavController
Expand Down Expand Up @@ -105,16 +153,4 @@ class VerifierMainActivity : AppCompatActivity() {
)
}
}

override fun onStart() {
super.onStart()
// Only get app config on every app foreground when introduction is finished and the app has already started
if (introductionViewModel.getIntroductionStatus() is IntroductionStatus.IntroductionFinished && !isFreshStart) {
appStatusViewModel.refresh(mobileCoreWrapper)
}

if (isFreshStart) {
isFreshStart = false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,16 @@ import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupWithNavController
import nl.rijksoverheid.ctr.appconfig.AppConfigViewModel
import nl.rijksoverheid.ctr.appconfig.persistence.AppConfigPersistenceManager
import nl.rijksoverheid.ctr.appconfig.usecases.CachedAppConfigUseCase
import nl.rijksoverheid.ctr.design.BaseMainFragment
import nl.rijksoverheid.ctr.design.ext.isScreenReaderOn
import nl.rijksoverheid.ctr.design.ext.styleTitle
import nl.rijksoverheid.ctr.design.menu.about.AboutThisAppData
import nl.rijksoverheid.ctr.design.menu.about.AboutThisAppFragment
import nl.rijksoverheid.ctr.introduction.IntroductionViewModel
import nl.rijksoverheid.ctr.introduction.ui.status.models.IntroductionStatus
import nl.rijksoverheid.ctr.shared.MobileCoreWrapper
import nl.rijksoverheid.ctr.shared.ext.launchUrl
import nl.rijksoverheid.ctr.verifier.databinding.FragmentMainBinding
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel

class VerifierMainFragment :
BaseMainFragment(R.layout.fragment_main, setOf(R.id.nav_scan_qr, R.id.nav_about_this_app)) {
Expand All @@ -43,12 +38,8 @@ class VerifierMainFragment :
private var _navController: NavController? = null
private val navController get() = _navController!!

private val appConfigViewModel: AppConfigViewModel by sharedViewModel()
private val introductionViewModel: IntroductionViewModel by sharedViewModel()
private val mobileCoreWrapper: MobileCoreWrapper by inject()
private val cachedAppConfigUseCase: CachedAppConfigUseCase by inject()
private val appConfigPersistenceManager: AppConfigPersistenceManager by inject()
private var isFreshStart: Boolean = true // track if this is a fresh start of the app

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Expand Down Expand Up @@ -93,19 +84,6 @@ class VerifierMainFragment :
childFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
_navController = navHostFragment.navController

// verifier can stay active for a long time, so it is not sufficient
// to try to refresh the config only every time the app resumes.
// We do track if the app was recently (re)started to avoid double config calls
navController.addOnDestinationChangedListener { _, _, _ ->
if (introductionViewModel.getIntroductionStatus() is IntroductionStatus.IntroductionFinished) {
if (!isFreshStart) {
appConfigViewModel.refresh(mobileCoreWrapper)
} else {
isFreshStart = false
}
}
}

val appBarConfiguration = AppBarConfiguration(
topLevelDestinations,
binding.drawerLayout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import android.widget.ScrollView
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.viewpager2.widget.ViewPager2
import nl.rijksoverheid.ctr.introduction.IntroductionData
import nl.rijksoverheid.ctr.introduction.ui.onboarding.OnboardingPagerAdapter
Expand All @@ -41,6 +42,8 @@ class ScanInstructionsFragment : Fragment(R.layout.fragment_scan_instructions) {
private var _binding: FragmentScanInstructionsBinding? = null
private val binding get() = _binding!!

private val args: ScanInstructionsFragmentArgs by navArgs()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Expand Down Expand Up @@ -74,7 +77,7 @@ class ScanInstructionsFragment : Fragment(R.layout.fragment_scan_instructions) {
// Instructions have been opened, set as seen
scanQrViewModel.setScanInstructionsSeen()
findNavController().popBackStack(R.id.nav_scan_qr, false)
scannerUtil.launchScanner(requireActivity())
scannerUtil.launchScanner(requireActivity(), args.returnUri)
} else {
binding.viewPager.currentItem = currentItem + 1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package nl.rijksoverheid.ctr.verifier.ui.scanner.utils
import android.app.Activity
import androidx.navigation.Navigation
import nl.rijksoverheid.ctr.verifier.R
import nl.rijksoverheid.ctr.verifier.RootNavDirections

/*
* Copyright (c) 2021 De Staat der Nederlanden, Ministerie van Volksgezondheid, Welzijn en Sport.
Expand All @@ -12,13 +13,13 @@ import nl.rijksoverheid.ctr.verifier.R
*
*/
interface ScannerUtil {
fun launchScanner(activity: Activity)
fun launchScanner(activity: Activity, returnUri: String? = null)
}

class ScannerUtilImpl : ScannerUtil {

override fun launchScanner(activity: Activity) {
override fun launchScanner(activity: Activity, returnUri: String?) {
Navigation.findNavController(activity, R.id.main_nav_host_fragment)
.navigate(R.id.action_scanner)
.navigate(RootNavDirections.actionScanner(returnUri))
}
}
10 changes: 3 additions & 7 deletions verifier/src/main/res/navigation/verifier_nav_graph_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

<action
android:id="@+id/action_scan_instructions"
app:destination="@id/nav_scan_instructions"
app:destination="@id/scan_instructions_nav"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
Expand All @@ -38,12 +38,8 @@
android:label="@string/about_this_app"
tools:layout="@layout/fragment_about_app" />

<fragment
android:id="@+id/nav_scan_instructions"
android:name="nl.rijksoverheid.ctr.verifier.ui.instructions.ScanInstructionsFragment"
android:label="@string/scan_instructions"
tools:layout="@layout/fragment_scan_instructions" />

<include app:graph="@navigation/verifier_nav_graph_scanner" />

<include app:graph="@navigation/verifier_nav_graph_scan_instructions" />

</navigation>
38 changes: 36 additions & 2 deletions verifier/src/main/res/navigation/verifier_nav_graph_root.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@
<fragment
android:id="@+id/nav_main"
android:name="nl.rijksoverheid.ctr.verifier.VerifierMainFragment"
tools:layout="@layout/fragment_main" />
tools:layout="@layout/fragment_main">

<deepLink app:uri=".*/verifier/scan?returnUri={returnUri}" />

<argument
android:name="returnUri"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
</fragment>

<action
android:id="@+id/action_introduction"
Expand Down Expand Up @@ -59,8 +68,33 @@
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@id/nav_scanner" />
app:popUpTo="@id/nav_scanner">

<argument
android:name="returnUri"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
</action>

<action
android:id="@+id/action_scan_instructions"
app:destination="@id/scan_instructions_nav"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@id/root_nav"
app:popUpToInclusive="true">

<argument
android:name="returnUri"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
</action>

<include app:graph="@navigation/verifier_nav_graph_scanner" />
<include app:graph="@navigation/verifier_nav_graph_scan_instructions" />

</navigation>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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
~
-->

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scan_instructions_nav"
app:startDestination="@+id/nav_scan_instructions">

<fragment
android:id="@+id/nav_scan_instructions"
android:name="nl.rijksoverheid.ctr.verifier.ui.instructions.ScanInstructionsFragment"
android:label="@string/scan_instructions"
tools:layout="@layout/fragment_scan_instructions">

<argument
android:name="returnUri"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
</fragment>

</navigation>
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
android:name="nl.rijksoverheid.ctr.verifier.ui.scanner.VerifierQrScannerFragment"
tools:layout="@layout/fragment_scanner">

<deepLink app:uri=".*/verifier/scan?returnUri={returnUri}" />

<argument
android:name="returnUri"
android:defaultValue="@null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ class VerifierMainActivityTest : AutoCloseKoinTest() {
@Test
fun `If app status is not NoActionRequired navigate to app status`() {
val scenario = launchVerifierMainActivity(
appStatus = AppStatus.Error
introductionStatus = IntroductionStatus.IntroductionNotFinished(IntroductionData()),
appStatus = AppStatus.Error,
)

scenario.onActivity {
assertEquals(
it.findNavController(R.id.main_nav_host_fragment).currentDestination?.id,
R.id.nav_app_status
R.id.nav_introduction
)
}
}
Expand Down

0 comments on commit 3cfacee

Please sign in to comment.