Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Identity][Compose] Remove all fragments and use a Compose NavHost #5981

Merged
merged 2 commits into from
Jan 12, 2023

Conversation

ccen-stripe
Copy link
Collaborator

@ccen-stripe ccen-stripe commented Jan 8, 2023

Summary

Final PR to fully migrate Identity SDK to jetpack compose.

Before the SDK use a NavController to navigate between Fragments. This PR replaced all fragments with a IdentityNavGraph with different composables. Each composable is represented by a String route.

Before the PR

  • We already have an abstraction of Fragment/composable: IdentityTopLevelDestination and its subclasses
  • We already created the DestinationRoute abstract class, which dynamically populates the route from routeBase?argName1={argName1}&argName2={argName2} to routeBase?argName1=value1&argName2=value2, and exposed static method to fetch the arguments from NavBackStackEntry(similar to FinancialConnection' ManualEntrySuccess.microdeposits methods), see ErrorDestination.errorTitle for details
  • We created a extension method NavController.navigateTo(destination: IdentityTopLevelDestination), its implementation was to navigate between fragmentIds

Bellow is a 1-to-1 mapping between Fragments and subclasses of IdentityTopLevelDestination.

Fragment Destination
ConsentFragment ConsentDestination
DocSelectionFragment DocSelectionDestination
DriverLicenseScanFragment DriverLicenseScanDestination
IDLicenseScanFragment IDScanDestination
PassportScanFragment PassportScanDestination
DriverLicenseUploadFragment DriverLicenseUploadDestination
IDLicenseUploadFragment IDUploadDestination
PassportUploadFragment PassportUploadDestination
ConfirmationFragment after screenshot
ErrorFragment ErrorDestination
CouldNotCaptureFragment CouldNotCaptureDestination
CameraPermissionDeniedFragment CameraPermissionDeniedDestination

After the PR:

  • IdentityTopLevelDestination and their subclasses is moved to their own files
  • IdentityNavGraph created, creating a NavHost with different composables
  • NavController.navigateTo(destination: IdentityTopLevelDestination) implementation changed from fragmentId to routes
    internal fun NavController.navigateTo(destination: IdentityTopLevelDestination) {
        // before: call NavController.navigate(destination.fragmentId: Int)
        // after: call NavController.navigate(destination.route: String)
    
  • Before fragmentIds are used as indicator of a screen, now we checked the route string instead
    • NavController.clearDataAndNavigateUp - checking which screen is in backStackEntry
    • IdentityActivity.isConsent/IdentityActivity.isConfirmation/IdentityActivity.isErrorThatShouldFail - checking what is the current screen
    • ErrorScreen's backButton destination - indicating which screen to popUp to when back is pressed
  • Removed all fragments/tests/legacy UI/navgraph xmls
  • Note: we removed the encapsulating MdcTheme on individual screens as now we have it in the NavHost, apart from that there are no changes in the screens. These are all the Screen files:
    • ConfirmationScreen
    • ConsentScreen
    • DocSelectionScreen
    • DocumentScanScreen
    • ErrorScreen
    • SelfieScreen
    • UploadScreen

Motivation

Go full Jetpack Compose

Testing

  • Added tests
  • Modified tests
  • Manually verified

Screenshots

Before After
before screenshot after screenshot

Changelog

import com.stripe.android.identity.analytics.IdentityAnalyticsRequestFactory
import com.stripe.android.identity.networking.models.Requirement

internal abstract class IdentityTopLevelDestination(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: The content of this class is not changed(except the one place below) but just moved from NavigationDestinations.kt


internal class PassportScanDestination(
internal abstract class DocumentScanDestination(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DocumentScanDestination is the super class of PassportScanDestination, IDScanDestination and DriverLicenseScanDestination, as their parameters list are exactly the same


internal class PassportUploadDestination(
internal abstract class DocumentUploadDestination(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DocumentUploadDestination is the super class of PassportUploadDestination , IDUploadDestination and DriverLicenseUploadDestination, as their parameters list are exactly the same

@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2023

Diffuse output:

OLD: identity-example-release-base.apk (signature: none)
NEW: identity-example-release-pr.apk (signature: none)

          │            compressed            │           uncompressed            
          ├───────────┬───────────┬──────────┼───────────┬───────────┬───────────
 APK      │ old       │ new       │ diff     │ old       │ new       │ diff      
──────────┼───────────┼───────────┼──────────┼───────────┼───────────┼───────────
      dex │   1.9 MiB │   1.9 MiB │ -2.1 KiB │   4.2 MiB │   4.2 MiB │  -9.1 KiB 
     arsc │   1.1 MiB │   1.1 MiB │ -1.3 KiB │   1.1 MiB │   1.1 MiB │  -1.3 KiB 
 manifest │   2.2 KiB │   2.2 KiB │     -1 B │   7.7 KiB │   7.7 KiB │       0 B 
      res │ 427.3 KiB │ 425.2 KiB │ -2.1 KiB │ 655.1 KiB │ 647.8 KiB │  -7.3 KiB 
   native │   6.2 MiB │   6.2 MiB │      0 B │  15.7 MiB │  15.7 MiB │       0 B 
    asset │   7.3 KiB │   7.2 KiB │   -105 B │   7.1 KiB │     7 KiB │    -105 B 
    other │  29.6 KiB │  29.6 KiB │      0 B │  29.9 KiB │  29.9 KiB │       0 B 
──────────┼───────────┼───────────┼──────────┼───────────┼───────────┼───────────
    total │   9.6 MiB │   9.6 MiB │ -5.6 KiB │  21.7 MiB │  21.7 MiB │ -17.8 KiB 

 DEX     │ old   │ new   │ diff                 
─────────┼───────┼───────┼──────────────────────
   files │     1 │     1 │    0                 
 strings │ 21536 │ 21454 │  -82 (+2488 -2570)   
   types │  7702 │  7696 │   -6 (+2232 -2238)   
 classes │  6671 │  6667 │   -4 (+2113 -2117)   
 methods │ 33020 │ 32898 │ -122 (+16669 -16791) 
  fields │ 16875 │ 16869 │   -6 (+9508 -9514)   

 ARSC    │ old  │ new  │ diff         
─────────┼──────┼──────┼──────────────
 configs │  261 │  260 │  -1 (+0 -1)  
 entries │ 4880 │ 4845 │ -35 (+2 -37)
APK
     compressed     │    uncompressed     │                                
─────────┬──────────┼─────────┬───────────┤                                
 size    │ diff     │ size    │ diff      │ path                           
─────────┼──────────┼─────────┼───────────┼────────────────────────────────
 1.9 MiB │ -2.1 KiB │ 4.2 MiB │  -9.1 KiB │ ∆ classes.dex                  
         │ -1.4 KiB │         │    -6 KiB │ - res/PQ.xml                   
 1.1 MiB │ -1.3 KiB │ 1.1 MiB │  -1.3 KiB │ ∆ resources.arsc               
         │   -651 B │         │  -1.3 KiB │ - res/HH.xml                   
   127 B │   +127 B │     5 B │      +5 B │ + META-INF/services/r8.y       
   127 B │   +127 B │     5 B │      +5 B │ + META-INF/services/w8.j       
         │   -127 B │         │      -5 B │ - META-INF/services/t8.y       
         │   -127 B │         │      -5 B │ - META-INF/services/y8.j       
 6.5 KiB │    -70 B │ 6.4 KiB │     -70 B │ ∆ assets/dexopt/baseline.prof  
   739 B │    -35 B │   607 B │     -35 B │ ∆ assets/dexopt/baseline.profm 
   519 B │     -6 B │   840 B │       0 B │ ∆ res/zq.xml                   
   382 B │     -3 B │   532 B │       0 B │ ∆ res/-o.xml                   
   710 B │     -3 B │ 1.4 KiB │       0 B │ ∆ res/Am.xml                   
   884 B │     -3 B │ 2.4 KiB │       0 B │ ∆ res/C7.xml                   
   517 B │     +3 B │   988 B │       0 B │ ∆ res/SS.xml                   
   692 B │     -2 B │ 1.4 KiB │       0 B │ ∆ res/-Y.xml                   
   615 B │     +2 B │ 1.2 KiB │       0 B │ ∆ res/38.xml                   
   327 B │     -2 B │   388 B │       0 B │ ∆ res/43.xml                   
 1.1 KiB │     -2 B │   3 KiB │       0 B │ ∆ res/GQ.xml                   
   767 B │     +2 B │ 1.8 KiB │       0 B │ ∆ res/Hy.xml                   
   740 B │     +2 B │ 1.5 KiB │       0 B │ ∆ res/Ig.xml                   
   566 B │     -2 B │ 1.2 KiB │       0 B │ ∆ res/LN.xml                   
   770 B │     +2 B │ 1.8 KiB │       0 B │ ∆ res/Ld.xml                   
   791 B │     +2 B │ 1.8 KiB │       0 B │ ∆ res/Qc.xml                   
   718 B │     -2 B │ 1.5 KiB │       0 B │ ∆ res/Re.xml                   
   361 B │     +2 B │   440 B │       0 B │ ∆ res/SH.xml                   
   665 B │     +2 B │ 1.3 KiB │       0 B │ ∆ res/TK.xml                   
   430 B │     -2 B │   636 B │       0 B │ ∆ res/XT.xml                   
   707 B │     -2 B │ 1.5 KiB │       0 B │ ∆ res/Y-.xml                   
   961 B │     -2 B │ 2.7 KiB │       0 B │ ∆ res/ZD.xml                   
 1.2 KiB │     +2 B │ 3.4 KiB │       0 B │ ∆ res/e1.xml                   
   646 B │     +2 B │ 1.3 KiB │       0 B │ ∆ res/fL.xml                   
   357 B │     -2 B │   440 B │       0 B │ ∆ res/iL.xml                   
   619 B │     -2 B │ 1.2 KiB │       0 B │ ∆ res/jH.xml                   
   603 B │     -2 B │ 1.3 KiB │       0 B │ ∆ res/kI.xml                   
   763 B │     +2 B │ 1.9 KiB │       0 B │ ∆ res/o-.xml                   
   688 B │     -2 B │ 1.5 KiB │       0 B │ ∆ res/oT.xml                   
   508 B │     +2 B │   956 B │       0 B │ ∆ res/va.xml                   
   509 B │     +2 B │   956 B │       0 B │ ∆ res/wn.xml                   
 2.2 KiB │     -1 B │ 7.7 KiB │       0 B │ ∆ AndroidManifest.xml          
   395 B │     +1 B │   528 B │       0 B │ ∆ res/-c.xml                   
   408 B │     -1 B │   592 B │       0 B │ ∆ res/0N.xml                   
   380 B │     -1 B │   528 B │       0 B │ ∆ res/65.xml                   
   764 B │     -1 B │ 1.4 KiB │       0 B │ ∆ res/BA.xml                   
   398 B │     +1 B │   612 B │       0 B │ ∆ res/CG.xml                   
 1.1 KiB │     -1 B │ 3.1 KiB │       0 B │ ∆ res/Cm.xml                   
   583 B │     +1 B │   1 KiB │       0 B │ ∆ res/DS.xml                   
   445 B │     -1 B │   768 B │       0 B │ ∆ res/Di.xml                   
   718 B │     +1 B │ 1.5 KiB │       0 B │ ∆ res/Ey.xml                   
 1.1 KiB │     +1 B │ 3.1 KiB │       0 B │ ∆ res/FR.xml                   
   580 B │     -1 B │ 1.1 KiB │       0 B │ ∆ res/I-.xml                   
   601 B │     -1 B │ 1.1 KiB │       0 B │ ∆ res/MP1.xml                  
   706 B │     +1 B │ 1.5 KiB │       0 B │ ∆ res/NA.xml                   
   413 B │     -1 B │   564 B │       0 B │ ∆ res/O8.xml                   
   781 B │     -1 B │ 1.7 KiB │       0 B │ ∆ res/Os.xml                   
   261 B │     -
...✂
DEX
STRINGS:

   old   │ new   │ diff              
  ───────┼───────┼───────────────────
   21536 │ 21454 │ -82 (+2488 -2570) 
  +  cannot use the same route as the graph 
  + _entry
  + _this_AppBar
  + _this_NavHost
  + _this_navigate
  + _this_PopulateVisibleList
  + , you will need CreationExtras to use AndroidViewModel with the default ViewModelProvider.Factory
  + >;JJF
  + >;JJFII)V
  + >;TT;
  + CONFIRMATION
  + CONSENT
  + Cannot have an empty start destination route
  + Cannot pop up to an empty route
  + ERROR_SHOULD_FAIL
  + IdentityNavGraph.kt
  + LLLLLFLI
  + La1/a2_a;
  + La1/a2_b;
  + La1/a2_c;
  + La1/a2_d;
  + La1/a2_e;
  + La1/a2_f;
  + La1/f2_a;
  + La1/f2_b;
  + La1/l2_a;
  + La1/m2<
  + La1/q2_a;
  + La1/s2_a;
  + La1/s2_a<
  + La1/s2_b;
  + La1/s2<
  + La1/t1<
  + La1/v1<
  + La1/w2_a;
  + La1/w2_b_a;
  + La1/w2_b;
  + La1/y2<
  + La3/a_a;
  + La3/a_b;
  + La3/a_c;
  + La3/a_d;
  + La3/a_e_a;
  + La3/a_e;
  + La3/a_f;
  + La3/a_g;
  + La3/a_h;
  + La3/a_i;
  + La3/a_j;
  + La3/a_k;
  + La3/a_l;
  + La3/a_m;
  + La3/b_a;
  + La3/b_b;
  + La3/b_c;
  + La3/b_d;
  + La3/b_e;
  + La3/b_f;
  + La3/b_g;
  + La3/b_h;
  + La3/b_i;
  + La3/b_j;
  + La3/b_k;
  + La3/b_l;
  + La3/b_m;
  + La3/b;
  + La3/c;
  + La3/d;
  + La3/e_a;
  + La3/e;
  + La3/e<
  + La4/a_a;
  + La4/a_b;
  + La4/a0;
  + La4/b0;
  + La4/b;
  + La4/c_a;
  + La4/c_b;
  + La4/c;
  + La4/d;
  + La4/e_a;
  + La4/e_b;
  + La4/e;
  + La4/f;
  + La4/g;
  + La4/h;
  + La4/i_a;
  + La4/i_b;
  + La4/i;
  + La4/j;
  + La4/k;
  + La4/l;
  + La4/m;
  + La4/n;
  + La4/o_a;
  + La4/o_b;
  + La4/o_c;
  + La4/o_d;
  + La4/o_e;
  + La4/o_f;
  + La4/o;
  + La4/p;
  + La4/q;
  + La4/r;
  + La4/s;
  + La4/t;
  + La4/u;
  + La4/v;
  + La4/w;
  + La4/x;
  + La4/y;
  + La4/z;
  + La6/d;
  + La6/e;
  + La6/f;
  + La6/g;
  + La6/g<
  + La6/h_a;
  + La6/h_b;
  + La6/h;
  + La6/i_a;
  + La6/i;
  + La6/j;
  + La6/k_a;
  + La6/k_b;
  + La6/k;
  + La6/l;
  + La6/m;
  + La6/n;
  + La6/o;
  + La6/p;
  + La6/q_a;
  + La6/q_b;
  + La6/q;
  + La6/r;
  + La7/a_a;
  + La7/d;
  + La7/e;
  + La8/e_a;
  + La8/f_a_a;
  + La8/f_a;
  + La8/f_b_a;
  + La8/f_b;
  + La8/f_c;
  + La8/f_c<
  + Landroidx/activity/p;
  + Landroidx/activity/q;
  + Landroidx/activity/result/g_a;
  + Landroidx/activity/result/g_b;
  + Landroidx/activity/result/i_a;
  + Landroidx/appcompat/widget/c0_a;
  + Landroidx/appcompat/widget/c0_b;
  + Landroidx/appcompat/widget/c0_c;
  + Landroidx/appcompat/widget/c0_d;
  + Landroidx/appcompat/widget/c0_e;
  + Landroidx/appcompat/widget/c0_f;
  + Landroidx/appcompat/widget/c0_g_a;
  + Landroidx/appcompat/widget/c0_g_b;
  + Landroidx/appcompat/widget/c0_g_c;
  + Landroidx/appcompat/widget/c0_g;
  + Landroidx/appcompat/widget/c0_h_a;
  + Landroidx/appcompat/widget/c0_h;
  + Landroidx/appcompat/widget/c0_i;
  + Landroidx/appcompat/widget/d0_a;
  + Landroidx/appcompat/widget/d1_a;
  + Landroidx/appcompat/widget/d1_b;
  + Landroidx/appcompat/widget/d1_c_a;
  + Landroidx/appcompat/widget/d1_c;
  + Landroidx/appcompat/widget/e0_a;
  + Landroidx/appcompat/widget/e0_b;
  + Landroidx/appcompat/widget/e0_c;
  + Landroidx/appcompat/widget/e0_d;
  + Landroidx/appcompat/widget/e0_e;
  + Landroidx/appcompat/widget/e0_f;
  + Landroidx/appcompat/widget/f1_e;
  + Landroidx/appcompat/widget/f1_f;
  + Landroidx/appcompat/widget/f1_g;
  + Landroidx/appcompat/widget/k1_a;
  + Landroidx/appcompat/widget/m0_a;
  + Landroidx/appcompat/widget/m0_b;
  + Landroidx/appcompat/widget/m0_c;
  + Landroidx/appcompat/widget/m0_d;
  + Landroidx/appcompat/widget/m0_e;
  + Landroidx/appcompat/widget/m0_f;
  + Landroidx/appcompat/widget/t0_a;
  + Landroidx/appcompat/widget/t0_b;
  + Landroidx/appcompat/widget/t0_c;
  + Landroidx/appcompat/widget/t0_d;
  + Landroidx/appcompat/widget/v0_a;
  + Landroidx/appcompat/widget/v0_b;
  + Landroidx/appcompat/widget/w0_a;
  + Landroidx/appcompat/widget/z0_a;
  + Landroidx/appcompat/widget/z0_b;
  + Landroidx/appcompat/widget/z0_c;
  + Landroidx/appcompat/widget/z0_d;
  + Landroidx/appcompat/widget/z0_e;
  + Landroidx/appcompat/widget/z0_f;
  + Landroidx/appcompat/widget/z0_g;
  + Landroidx/compose/ui/platform/a0_a;
  + Landroidx/compose/ui/platform/a0_b;
  + Landroidx/compose/ui/platform/a0_c;
  + Landroidx/compose/ui/platform/a0_d;
  + Landroidx/compose/ui/platform/a0_e;
  + Landroidx/compose/ui/platform/a0_f;
  + Landroidx/compose/ui/platform/a0_g;
  + Landroidx/compose/ui/platform/a0_h;
  + Landroidx/compose/ui/platform/a0_i;
  + Landroidx/compose/ui/platform/a0_j;
...✂
ARSC
CONFIGS:

   old │ new │ diff       
  ─────┼─────┼────────────
   261 │ 260 │ -1 (+0 -1) 
  - navigation
  

ENTRIES:

   old  │ new  │ diff         
  ──────┼──────┼──────────────
   4880 │ 4845 │ -35 (+2 -37) 
  + string/description_close
  + string/description_go_back
  
  - id/IDScanFragment
  - id/IDUploadFragment
  - id/action_camera_permission_denied
  - id/action_global_IDScanFragment
  - id/action_global_IDScanPopUpToDocSelect
  - id/action_global_IDUploadFragment
  - id/action_global_IDUploadPopUpToDocSelect
  - id/action_global_confirmationFragment
  - id/action_global_consentFragment
  - id/action_global_couldNotCaptureFragment
  - id/action_global_docSelectionFragment
  - id/action_global_driverLicenseScanFragment
  - id/action_global_driverLicenseScanPopUpToDocSelect
  - id/action_global_driverLicenseUploadFragment
  - id/action_global_driverLicenseUploadPopUpToDocSelect
  - id/action_global_errorFragment
  - id/action_global_passportScanFragment
  - id/action_global_passportScanPopUpToDocSelect
  - id/action_global_passportUploadFragment
  - id/action_global_passportUploadPopUpToDocSelect
  - id/action_global_selfieFragment
  - id/cameraPermissionDeniedFragment
  - id/confirmationFragment
  - id/consentFragment
  - id/couldNotCaptureFragment
  - id/docSelectionFragment
  - id/driverLicenseScanFragment
  - id/driverLicenseUploadFragment
  - id/errorFragment
  - id/identity_nav_graph
  - id/identity_nav_host
  - id/passportScanFragment
  - id/passportUploadFragment
  - id/selfieFragment
  - id/top_app_bar
  - layout/identity_activity
  - navigation/identity_nav_graph

// If this happens, set the back button destination to [DEFAULT_BACK_BUTTON_DESTINATION]
const val UNEXPECTED_ROUTE = "UnexpectedRoute"

fun errorTitle(backStackEntry: NavBackStackEntry) =
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the parameters passed to a destination is set with destinationRoute.withParams method.
destinationRoute is something like Error?arg1={arg1}&arg2={arg2}
destinationRoute.withParams set the params with actual values Error?arg1=value1&arg2=value2.

This would in turn created a NavBackStackEntry with a bundle with "arg1"="value1", "arg2"="value2" , then we created these static function to fetch corresponding entries. This is a slightly generalized version of FinancialConnection's ManualEntrySuccess.microdeposits

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 love it!

@@ -53,92 +52,90 @@ internal fun ConfirmationScreen(
val verificationPageState by identityViewModel.verificationPage.observeAsState(Resource.loading())
val context = LocalContext.current

MdcTheme {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: all Screen changes are just removing the encapsulating MdcTheme, as we now have it in the NavHost

* Navigate to the [IdentityTopLevelDestination] by calling NavController.navigate(fragmentID, bundle).
*/
internal fun NavController.navigateTo(destination: IdentityTopLevelDestination) {
navigate(destination.routeWithArgs) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was changed from navigate(fragmentId) to navigate(routeWithArgs)

awush-stripe
awush-stripe previously approved these changes Jan 10, 2023
Base automatically changed from ccen/fixViewModelScope to master January 10, 2023 19:10
Copy link
Collaborator

@carlosmuvi-stripe carlosmuvi-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! a few comments.

Comment on lines +196 to +202
onBackPressedCallback =
IdentityActivityOnBackPressedCallback(
this,
navController,
identityViewModel
)
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be under a LaunchedEffect? so that it doesn't get retriggered on recompositions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is wrapped within a LaunchedEffect in IdentityNavGraph: link

import androidx.navigation.navArgument
import com.stripe.android.identity.networking.models.CollectedDataParam

internal class CameraPermissionDeniedDestination(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this to pass params as an abstraction 👏

// If this happens, set the back button destination to [DEFAULT_BACK_BUTTON_DESTINATION]
const val UNEXPECTED_ROUTE = "UnexpectedRoute"

fun errorTitle(backStackEntry: NavBackStackEntry) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 love it!

identityViewModel.verificationArgs.brandLogo,
verificationPage,
onConsentAgreed = {
coroutineScope.launch {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be run using viewModelScope instead? otherwise the api call would be cancelled if the component leaves the composition.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I think it's OK because postVerificationPageDataAndMaybeNavigate post an API and triggers navigation(which would make ConsentScreen leaving the composition)

@ccen-stripe ccen-stripe merged commit 3484ef9 into master Jan 12, 2023
@ccen-stripe ccen-stripe deleted the ccen/composeFinal10 branch January 12, 2023 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants