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

Add formatted content description for Expiration Date text field #10185

Merged
merged 21 commits into from
Feb 21, 2025

Conversation

tjclawson-stripe
Copy link
Collaborator

@tjclawson-stripe tjclawson-stripe commented Feb 14, 2025

Summary

Adds custom content description for expiry date text field
Adds formatExpirationDateForAccessibility which takes raw input from Expiry Date text field and returns a resolvable string formatted with month and year

For the following inputs, a screen reader will announce:
"" -> Expiration date. Two digit month and two digit year, empty
"4 /" -> Expiration date. April and two digit year, empty
"4 / 2" -> Expiration date. April and two digit year, incomplete
"4 / 25" -> Expiration date. April 2025

Motivation

Improve accessibility

Testing

  • Added tests
  • Modified tests
  • Manually verified
Screen.Recording.2025-02-14.at.4.57.05.PM.mov

return resolvableString(R.string.stripe_expiration_date_empty_content_description)
}

val canOnlyBeSingleDigitMonth = input.isNotBlank() && !(input[0] == '0' || input[0] == '1')
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 split logic taken from ExpiryDateVisualTransformation

Copy link
Contributor

github-actions bot commented Feb 14, 2025

Diffuse output:

OLD: paymentsheet-example-release-master.apk (signature: V1, V2)
NEW: paymentsheet-example-release-pr.apk (signature: V1, V2)

          │            compressed            │          uncompressed          
          ├───────────┬───────────┬──────────┼──────────┬──────────┬──────────
 APK      │ old       │ new       │ diff     │ old      │ new      │ diff     
──────────┼───────────┼───────────┼──────────┼──────────┼──────────┼──────────
      dex │   4.1 MiB │   4.1 MiB │ +3.9 KiB │    9 MiB │    9 MiB │ +1.8 KiB 
     arsc │   2.4 MiB │   2.4 MiB │   +3 KiB │  2.4 MiB │  2.4 MiB │   +3 KiB 
 manifest │   5.1 KiB │   5.1 KiB │      0 B │ 25.7 KiB │ 25.7 KiB │      0 B 
      res │ 910.9 KiB │ 910.9 KiB │     -1 B │  1.4 MiB │  1.4 MiB │      0 B 
   native │   2.6 MiB │   2.6 MiB │      0 B │    6 MiB │    6 MiB │      0 B 
    asset │   1.6 MiB │   1.6 MiB │    -15 B │  1.6 MiB │  1.6 MiB │    -15 B 
    other │   1.4 MiB │   1.4 MiB │     +5 B │  1.6 MiB │  1.6 MiB │      0 B 
──────────┼───────────┼───────────┼──────────┼──────────┼──────────┼──────────
    total │  12.9 MiB │  12.9 MiB │ +6.9 KiB │ 22.1 MiB │ 22.1 MiB │ +4.8 KiB 

 DEX     │ old   │ new   │ diff             
─────────┼───────┼───────┼──────────────────
   files │     1 │     1 │  0               
 strings │ 42726 │ 42732 │ +6 (+73 -67)     
   types │ 15332 │ 15335 │ +3 (+63 -60)     
 classes │ 12940 │ 12943 │ +3 (+19 -16)     
 methods │ 62624 │ 62624 │  0 (+4270 -4270) 
  fields │ 41621 │ 41628 │ +7 (+3341 -3334) 

 ARSC    │ old  │ new  │ diff       
─────────┼──────┼──────┼────────────
 configs │  243 │  243 │  0         
 entries │ 6267 │ 6271 │ +4 (+4 -0)
APK
     compressed      │     uncompressed     │                                           
──────────┬──────────┼───────────┬──────────┤                                           
 size     │ diff     │ size      │ diff     │ path                                      
──────────┼──────────┼───────────┼──────────┼───────────────────────────────────────────
  4.1 MiB │ +3.9 KiB │     9 MiB │ +1.8 KiB │ ∆ classes.dex                             
  2.4 MiB │   +3 KiB │   2.4 MiB │   +3 KiB │ ∆ resources.arsc                          
  6.6 KiB │    -13 B │   6.5 KiB │    -13 B │ ∆ assets/dexopt/baseline.prof             
   54 KiB │     +9 B │   120 KiB │      0 B │ ∆ META-INF/CERT.SF                        
 50.6 KiB │     -3 B │ 119.9 KiB │      0 B │ ∆ META-INF/MANIFEST.MF                    
    1 KiB │     -2 B │     917 B │     -2 B │ ∆ assets/dexopt/baseline.profm            
    783 B │     -2 B │   1.6 KiB │      0 B │ ∆ res/Bh.xml                              
    907 B │     +2 B │   2.4 KiB │      0 B │ ∆ res/YB.xml                              
    270 B │     -1 B │     120 B │      0 B │ ∆ META-INF/version-control-info.textproto 
  1.2 KiB │     +1 B │   3.7 KiB │      0 B │ ∆ res/BH.xml                              
    951 B │     +1 B │   2.5 KiB │      0 B │ ∆ res/de.xml                              
  1.1 KiB │     -1 B │   3.2 KiB │      0 B │ ∆ res/nn.xml                              
    464 B │     -1 B │     728 B │      0 B │ ∆ res/zE.xml                              
    539 B │     -1 B │     952 B │      0 B │ ∆ res/zd.xml                              
──────────┼──────────┼───────────┼──────────┼───────────────────────────────────────────
  6.6 MiB │ +6.9 KiB │  11.7 MiB │ +4.8 KiB │ (total)
DEX
STRINGS:

   old   │ new   │ diff         
  ───────┼───────┼──────────────
   42726 │ 42732 │ +6 (+73 -67) 
  
  + _this_clearAndSetSemantics
  + LU0/O;
  + LU0/P;
  + LU0/Q;
  + LU0/S;
  + LU1/k;
  + LU2/m;
  + LU3/C;
  + LU3/D;
  + LX8/W1;
  + LX8/X1;
  + Lm6/I;
  + Lm8/T1;
  + Lm8/U1;
  + Lm8/V1;
  + Lm8/W1;
  + Lm8/X1;
  + Lm8/Y1;
  + Lm8/Z1;
  + Lr9/q0;
  + MMMM
  + VLLLZLLLZLLLLZZZL
  + VLZILLIILZZII
  + VLZILLIILZZLII
  + VLZZLLLZZZLLLLLLLI
  + VLZZLLLZZZLLLLLLLLI
  + [LT/R0;
  + [LT/Z1;
  + [LT/p3;
  + [LT/t1;
  + [LT/z0;
  + [LU3/D;
  + [LX8/C0;
  + [LX8/E0;
  + [LX8/E1;
  + [LX8/H1;
  + [LX8/I0;
  + [LX8/L1;
  + [LX8/N0;
  + [LX8/R1;
  + [LX8/X1;
  + [LX8/Y0;
  + [LX8/b1;
  + [LX8/e0;
  + [LX8/e1;
  + [LX8/h0;
  + [LX8/l1;
  + [LX8/q1;
  + [LX8/s0;
  + [LX8/t1;
  + [LX8/v0;
  + [LX8/x1;
  + [LX8/y0;
  + [LX8/y1;
  + [Lg9/I0;
  + [Lg9/M0;
  + [Lg9/O0;
  + [Lg9/b0;
  + [Lg9/v0;
  + [Lm6/H;
  + [Lm8/H1;
  + [Lm8/I1;
  + [Lm8/J1;
  + [Lm8/N1;
  + [Lm8/o0;
  + [Lr9/O;
  + [Lr9/d0;
  + [Lr9/f0;
  + [Lr9/o0;
  + [Ls5/T0;
  + formatExpirationDateForAccessibility
  + formatExpirationDateForAccessibility(Ljava/lang/String;)Lcom/stripe/android/core/strings/ResolvableString;
  + ~~R8{"backend":"dex","compilation-mode":"release","has-checksums":false,"min-api":21,"pg-map-id":"1edae72","r8-mode":"full","version":"8.8.27"}
  
  - LD0/e;
  - LSa/f;
  - LT/A3;
  - LT/B3;
  - LT/w3;
  - LT/x3;
  - LT/y3;
  - LT/z3;
  - Lg9/A1;
  - Lg9/B1;
  - Lg9/C1;
  - Lg9/D1;
  - Lg9/E1;
  - Lg9/F1;
  - Lg9/z1;
  - Ls5/j1;
  - VLLLZLLLZLLLLZZL
  - VLLZII
  - VLZILLIILII
  - VLZILLIILLII
  - VLZZLLLZZLLLLLLLI
  - VLZZLLLZZLLLLLLLLI
  - [LT/F0;
  - [LT/X0;
  - [LT/f2;
  - [LT/v3;
  - [LT/z1;
  - [LU3/B;
  - [LX8/B0;
  - [LX8/C1;
  - [LX8/D0;
  - [LX8/F1;
  - [LX8/G0;
  - [LX8/J1;
  - [LX8/L0;
  - [LX8/P1;
  - [LX8/T1;
  - [LX8/U0;
  - [LX8/Z0;
  - [LX8/c1;
  - [LX8/d0;
  - [LX8/g0;
  - [LX8/j1;
  - [LX8/m1;
  - [LX8/r0;
  - [LX8/r1;
  - [LX8/u0;
  - [LX8/v1;
  - [LX8/w1;
  - [LX8/x0;
  - [Lg9/N0;
  - [Lg9/S0;
  - [Lg9/V0;
  - [Lg9/d0;
  - [Lg9/x0;
  - [Lm6/C;
  - [Lm8/A1;
  - [Lm8/B1;
  - [Lm8/C1;
  - [Lm8/G1;
  - [Lm8/h0;
  - [Lr9/N;
  - [Lr9/c0;
  - [Lr9/e0;
  - [Lr9/n0;
  - [Ls5/W0;
  - ~~R8{"backend":"dex","compilation-mode":"release","has-checksums":false,"min-api":21,"pg-map-id":"2144531","r8-mode":"full","version":"8.8.27"}
  

TYPES:

   old   │ new   │ diff         
  ───────┼───────┼──────────────
   15332 │ 15335 │ +3 (+63 -60) 
  
  + LU0/O;
  + LU0/P;
  + LU0/Q;
  + LU0/S;
  + LU1/k;
  + LU2/m;
  + LU3/C;
  + LU3/D;
  + LX8/W1;
  + LX8/X1;
  + Lm6/I;
  + Lm8/T1;
  + Lm8/U1;
  + Lm8/V1;
  + Lm8/W1;
  + Lm8/X1;
  + Lm8/Y1;
  + Lm8/Z1;
  + Lr9/q0;
  + [LT/R0;
  + [LT/Z1;
  + [LT/p3;
  + [LT/t1;
  + [LT/z0;
  + [LU3/D;
  + [LX8/C0;
  + [LX8/E0;
  + [LX8/E1;
  + [LX8/H1;
  + [LX8/I0;
  + [LX8/L1;
  + [LX8/N0;
  + [LX8/R1;
  + [LX8/X1;
  + [LX8/Y0;
  + [LX8/b1;
  + [LX8/e0;
  + [LX8/e1;
  + [LX8/h0;
  + [LX8/l1;
  + [LX8/q1;
  + [LX8/s0;
  + [LX8/t1;
  + [LX8/v0;
  + [LX8/x1;
  + [LX8/y0;
  + [LX8/y1;
  + [Lg9/I0;
  + [Lg9/M0;
  + [Lg9/O0;
  + [Lg9/b0;
  + [Lg9/v0;
  + [Lm6/H;
  + [Lm8/H1;
  + [Lm8/I1;
  + [Lm8/J1;
  + [Lm8/N1;
  + [Lm8/o0;
  + [Lr9/O;
  + [Lr9/d0;
  + [Lr9/f0;
  + [Lr9/o0;
  + [Ls5/T0;
  
  - LD0/e;
  - LSa/f;
  - LT/A3;
  - LT/B3;
  - LT/w3;
  - LT/x3;
  - LT/y3;
  - LT/z3;
  - Lg9/A1;
  - Lg9/B1;
  - Lg9/C1;
  - Lg9/D1;
  - Lg9/E1;
  - Lg9/F1;
  - Lg9/z1;
  - Ls5/j1;
  - [LT/F0;
  - [LT/X0;
  - [LT/f2;
  - [LT/v3;
  - [LT/z1;
  - [LU3/B;
  - [LX8/B0;
  - [LX8/C1;
  - [LX8/D0;
  - [LX8/F1;
  - [LX8/G0;
  - [LX8/J1;
  - [LX8/L0;
  - [LX8/P1;
  - [LX8/T1;
  - [LX8/U0;
  - [LX8/Z0;
  - [LX8/c1;
  - [LX8/d0;
  - [LX8/g0;
  - [LX8/j1;
  - [LX8/m1;
  - [LX8/r0;
  - [LX8/r1;
  - [LX8/u0;
  - [LX8/v1;
  - [LX8/w1;
  - [LX8/x0;
  - [Lg9/N0;
  - [Lg9/S0;
  - [Lg9/V0;
  - [Lg9/d0;
  - [Lg9/x0;
  - [Lm6/C;
  - [Lm8/A1;
  - [Lm8/B1;
  - [Lm8/C1;
  - [Lm8/G1;
  - [Lm8/h0;
  - [Lr9/N;
  - [Lr9/c0;
  - [Lr9/e0;
  - [Lr9/n0;
  - [Ls5/W0;
  

METHODS:

   old   │ new   │ diff            
  ───────┼───────┼─────────────────
   62624 │ 62624 │ 0 (+4270 -4270) 
  
  + A.i E(p, int, p) → u
  + A6.d r(String) → e1
  + A7.h2 <init>(C, Continuation, int)
  + A7.r <init>(f, O, List, b, l)
  + B3.e b(a, float) → float
  + B5.v <init>(d, boolean, g1, u, e)
  + B5.v a(v, boolean, g1, u, e, int) → v
  + B7.X <init>(f1, h)
  + B7.d0 <init>(Z, Y0)
  + C.w <init>(int, a, a, a, u1, a, a, a2)
  + C.z <init>(f, p, O, boolean, int, int, g, Function1,
...✂
ARSC
ENTRIES:

   old  │ new  │ diff       
  ──────┼──────┼────────────
   6267 │ 6271 │ +4 (+4 -0) 
  + string/stripe_expiration_date_content_description
  + string/stripe_expiration_date_empty_content_description
  + string/stripe_expiration_date_month_complete_content_description
  + string/stripe_expiration_date_year_incomplete_content_description

@tjclawson-stripe tjclawson-stripe marked this pull request as ready for review February 18, 2025 17:24
@tjclawson-stripe tjclawson-stripe requested review from a team as code owners February 18, 2025 17:24

return input.resolvableString
} catch (e: Exception) {
return input.resolvableString
Copy link
Collaborator

Choose a reason for hiding this comment

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

which exceptions are we catching here and why is it ok to ignore them?

Can you consider:

  • catching specific exceptions here
  • adding a comment about why it is ok that we are ignoring the exceptions

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated to ParseException and left a comment on why it's fine to ignore. ParseException should never be thrown but since the text passed in here is coming directly from the TextField input we don't want to crash the app if somehow a non numeric string is entered

amk-stripe
amk-stripe previously approved these changes Feb 18, 2025
amk-stripe
amk-stripe previously approved these changes Feb 18, 2025
amk-stripe
amk-stripe previously approved these changes Feb 18, 2025
@tjclawson-stripe tjclawson-stripe enabled auto-merge (squash) February 18, 2025 22:38
@tjclawson-stripe tjclawson-stripe enabled auto-merge (squash) February 18, 2025 22:38
samer-stripe
samer-stripe previously approved these changes Feb 19, 2025
@tjclawson-stripe tjclawson-stripe merged commit fc31cc9 into master Feb 21, 2025
16 checks passed
@tjclawson-stripe tjclawson-stripe deleted the tyler/mobilesdk-2530 branch February 21, 2025 15:46
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.

3 participants