From 3f81a9aa59a38981b6ea04e6b2b871421e860e78 Mon Sep 17 00:00:00 2001 From: David Estes Date: Tue, 8 Oct 2024 16:23:29 -0700 Subject: [PATCH 01/12] Some Link GIT_VALID_PII_OVERRIDE --- .../Link/back_button.imageset/Contents.json | 23 +++ .../Link/back_button.imageset/back_button.png | Bin 0 -> 839 bytes .../back_button.imageset/back_button@2x.png | Bin 0 -> 1025 bytes .../back_button.imageset/back_button@3x.png | Bin 0 -> 1025 bytes .../icon_add_bordered.imageset/Contents.json | 23 +++ .../icon_add_bordered.png | Bin 0 -> 1073 bytes .../icon_add_bordered@2x.png | Bin 0 -> 1481 bytes .../icon_add_bordered@3x.png | Bin 0 -> 459 bytes .../Link/icon_cancel.imageset/Contents.json | 23 +++ .../Link/icon_cancel.imageset/icon_cancel.png | Bin 0 -> 912 bytes .../icon_cancel.imageset/icon_cancel@2x.png | Bin 0 -> 1270 bytes .../icon_cancel.imageset/icon_cancel@3x.png | Bin 0 -> 1270 bytes .../icon_link_error.imageset/Contents.json | 21 +++ .../icon_link_error@3x.png | Bin 0 -> 466 bytes .../icon_link_success.imageset/Contents.json | 21 +++ .../icon_link_success@3x.png | Bin 0 -> 461 bytes .../Link/icon_menu.imageset/Contents.json | 21 +++ .../Link/icon_menu.imageset/icon_menu@3x.png | Bin 0 -> 152 bytes .../Contents.json | 23 +++ .../icon_menu_horizontal.png | Bin 0 -> 670 bytes .../icon_menu_horizontal@2x.png | Bin 0 -> 812 bytes .../icon_menu_horizontal@3x.png | Bin 0 -> 172 bytes .../Link/Extensions/Button+Link.swift | 70 +++++++++ .../Link/Extensions/ConfirmButton+Link.swift | 39 +++++ .../Link/ButtonLinkSnapshotTests.swift | 79 ++++++++++ .../Link/LinkBadgeViewSnapshotTest.swift | 59 +++++++ .../LinkCardEditElementSnapshotTests.swift | 75 +++++++++ ...LinkInlineSignupElementSnapshotTests.swift | 123 +++++++++++++++ ...InstantDebitMandateViewSnapshotTests.swift | 78 ++++++++++ .../Link/LinkNavigationBarSnapshotTests.swift | 89 +++++++++++ .../Link/LinkNoticeViewSnapshotTests.swift | 51 +++++++ ...LinkPaymentMethodPickerSnapshotTests.swift | 108 +++++++++++++ .../Link/LinkToastSnapshotTests.swift | 41 +++++ .../LinkVerificationViewSnapshotTests.swift | 84 ++++++++++ ...kViewController-WalletViewModelTests.swift | 144 ++++++++++++++++++ 35 files changed, 1195 insertions(+) create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button@2x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered@2x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel@2x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/icon_link_error@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/icon_link_success@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/icon_menu@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/Contents.json create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal@2x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal@3x.png create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Button+Link.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/ConfirmButton+Link.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/Contents.json new file mode 100644 index 00000000000..f831e5441f5 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "back_button.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "back_button@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "back_button@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button.png new file mode 100644 index 0000000000000000000000000000000000000000..bfc423f96585186235325457542cea004f7e4e4c GIT binary patch literal 839 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|T2doC(|mmy zw18|523AHP24;{FAY@>aVqgWc85q16rQz%#Mh&PMCI*J~Oa>OHnkXO*0vxV%QuQiw3qZOUY$~jP%-qzHM1_jnoV;SI3R@+x3M(KRB&@Hb09I0xZL1XF8=&Bv zUzDm~re~mMpk&9TprBw=l#*r@P?Wt5Z@Sn2DRmzV368|&p4rRy77T3YHG z80i}s=>k>g7FXt#Bv$C=6)QswftllyTAW;zSx}OhpQivaH!&%{w8U0P31kr*K-^i9 znTD__uNdkrpa=CqGWv#k2KsQbfm&@qqE`MznW;dVLFU^T+JIG}h(YbK(Fa+Ms()9P3E9be|H;uwD46@z?{RYGB3FhO?R!t;e`@YA zE}X%~&vrj!^}+X2i&++{pS;G#$LY0U&AgJv#Vn__dd-igDi$}--jgQvtH77B`b4J2 zMvfmY4iX==*#9WSpEA_WPP6q-zx7q}!40o{Yu$MZC6=)ZA6Kp7ekY)?`PKU^FmdKI;Vst0OR8U`Tzg` literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button@2x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8b83c43bce34ad8f81804b0104fa8598d7400a56 GIT binary patch literal 1025 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}EvXTnX}-P; zT0k}j11qBt12aeo5Hc`IF|dN!3=Ce3(r|VVqXtwB69YqgCIbspO%#v@0S_Ps>W0$H z3m6e5E?|PIHdw%nV1u-2@G|lPDb50q$YKTtZeb8+WSBKa0%%%fW=KRygs+cPa(=E} zVoH8es$NBI0Z12vO@$SZnVVXYs8ErclUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO| zi&7QL^bGV2l1AfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL% z(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjoGZknv$b36P8?Z_gF{nK@`XI}Z90Tzw zSQO}0J1!f2c(B=VNya^72L|#+PZ!6K4A!?ZBK?jS2)ML|c6b+vwj5z+V%-1dy#1Yq z$qIT$MJX>MpnY6^c#QW(t7VCBEw!J*DI50|U0@o6zl?Rx(a&!#J=dFA_ z>&UF^L)UHeC5rsilS)5b($v~`u6=`k4EOFsa~;$U-A+6F!RMc6!s~{O4PRB0B6E*j zd*W~U-nHR}^W*#{hW(oRnYOC6eOk}-c_96y+WfsOiqbesKpKspdoF_kd{xX{< zm3^&h_m}Ny)>+7s>AT9evY*>&_XUHMA^YBMS@Nk?``y<+yqhOg-<$f`<>C&Dy(|5f z9^LIxS^YB5=C;_<>Vr!@)~t}_z7bY_iAnOlbz<`e#itjngi8gqCvvh+oSCqnH*;pE;??!n z|CP^N(ae7}|Fp|reKV1dvwE6;to4&IX^y@5dS~JZ@AdLf=?%byYTM3X`n!M d&@x!Vbl+#v9NWy`)Y+hX;OXk;vd$@?2>_%=SBn4u literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/back_button.imageset/back_button@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..8b83c43bce34ad8f81804b0104fa8598d7400a56 GIT binary patch literal 1025 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}EvXTnX}-P; zT0k}j11qBt12aeo5Hc`IF|dN!3=Ce3(r|VVqXtwB69YqgCIbspO%#v@0S_Ps>W0$H z3m6e5E?|PIHdw%nV1u-2@G|lPDb50q$YKTtZeb8+WSBKa0%%%fW=KRygs+cPa(=E} zVoH8es$NBI0Z12vO@$SZnVVXYs8ErclUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO| zi&7QL^bGV2l1AfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL% z(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjoGZknv$b36P8?Z_gF{nK@`XI}Z90Tzw zSQO}0J1!f2c(B=VNya^72L|#+PZ!6K4A!?ZBK?jS2)ML|c6b+vwj5z+V%-1dy#1Yq z$qIT$MJX>MpnY6^c#QW(t7VCBEw!J*DI50|U0@o6zl?Rx(a&!#J=dFA_ z>&UF^L)UHeC5rsilS)5b($v~`u6=`k4EOFsa~;$U-A+6F!RMc6!s~{O4PRB0B6E*j zd*W~U-nHR}^W*#{hW(oRnYOC6eOk}-c_96y+WfsOiqbesKpKspdoF_kd{xX{< zm3^&h_m}Ny)>+7s>AT9evY*>&_XUHMA^YBMS@Nk?``y<+yqhOg-<$f`<>C&Dy(|5f z9^LIxS^YB5=C;_<>Vr!@)~t}_z7bY_iAnOlbz<`e#itjngi8gqCvvh+oSCqnH*;pE;??!n z|CP^N(ae7}|Fp|reKV1dvwE6;to4&IX^y@5dS~JZ@AdLf=?%byYTM3X`n!M d&@x!Vbl+#v9NWy`)Y+hX;OXk;vd$@?2>_%=SBn4u literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/Contents.json new file mode 100644 index 00000000000..0e0263b9db1 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icon_add_bordered.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_add_bordered@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_add_bordered@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered.png new file mode 100644 index 0000000000000000000000000000000000000000..15d2508054dd255bab5660fe4672834549aabf70 GIT binary patch literal 1073 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|T2doC(|mmy zw18|523AHP24;{FAY@>aVqgWc85q16rQz%#Mh&PMCI*J~Oa>OHnkXO*0vxV%QuQiw3qZOUY$~jP%-qzHM1_jnoV;SI3R@+x3M(KRB&@Hb09I0xZL1XF8=&Bv zUzDm~re~mMpk&9TprBw=l#*r@P?Wt5Z@Sn2DRmzV368|&p4rRy77T3YHG z80i}s=>k>g7FXt#Bv$C=6)QswftllyTAW;zSx}OhpQivaH!&%{w8U0P31kr*K-^i9 znTD__uNdkrpa=CqGWv#k2KsQbfm&@qqE`MznW;dVLFU^T+JIG}h(YbK(Fa+M6;*k9CpvrfpjGa*O)jqZ?&!7hWp6x}w+E*Z&Cf#;z*?M}p)&gwN^T zY{BoS(y#VtYK6|N$VcZ20=d`Lh-Wh`-Xq2t*Zq4@V8h`PlAIabDi$Zdu^P@z7?J5boSyWHv z_PBXpyeW1y+S#?qZcVkO`jh!Ddfq&cTfEXXAe3*L-~oqia&vQ6p4*pr=552<`mQa9 z9QUd2etv>&-;15EzHQaL)A3b>OGm+wy-NL(nAQ`^o#F?(J&Kq5S6bf{HtEf^ zf7V&|*t=e_+*~FrCU$|1tHAZlN*SAuEi4aCzdPsp+bc$~oXz4>%Vvw%CoL@g!VeyQ zp18v?zI%_tUAs+RT{h}o&0XYu>g@r)dyL9Y92%cbYu@y_orUjGs(bs~xtE@YUwr#P zBUH?LPTmp4{9vKVJw3Jg?`f+pwR`P1mNZWAcm205fU$37>}8!5v(g)9 eyPbaNbwIxJU0R0p(#cAoeBW0$H z3m6e5E?|PIHdw%nV1u-2@G|lPDb50q$YKTtZeb8+WSBKa0%%%fW=KRygs+cPa(=E} zVoH8es$NBI0Z12vO@$SZnVVXYs8ErclUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO| zi&7QL^bGV2l1AfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL% z(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjoGZknv$b36P8?Z_gF{nK@`XI}Z90Tzw zSQO}0J1!f2c(B=VNya^7XJBBi^mK6y$zXjuGdk~zfk@l!g}UEwa|>BBu-Gs=*=%6i zcF5}nSI$D41Je8o8~N5X1+o1*KiPQe3lwl-){#VeHJV8;Z$vOSD?#%X2sTmL&g`qc45d_+w*5e2r4o8K)U>{OlY&!9G_QwPWAD zP%eKKdVqsnOr~Foo6BaA5KI5p;%5gUCZ2owaSr3@|8w4HJ-@E`DAccbuPs~pu5;y< zhA$Qt$+FjZX=hj6_AqYyZ0}N*G@JF_0t@ycwj#Oe3Zr+uihKz?ZT2EJXGGlIJc@N-TpSgwcCN^bH;&pr_@pf!^|5k89nC1O zuzHYZ!*xzZLiG%*>T8ig$C#qdt#|kG6)>o3tmX`pHrrd_o4?-2^vl`3G6~K};eW40 z>|B2>bzA2jUBT9^jz?~uVdxjzTH11)KTJ_>V)pV0E^VTHCQW)5r{A&UTX2Azg{?~T zvm)P-e80H9iW9NR1b)8!bo2b-R~~9+@)2B>H5I)jq3@H-I~h;rsrsGY2j){t_|vJF;8-xjARrp4vs8G6w>*Gwv<8QL$&5eF-n4 zrT@h`!Jm3tS>#F^WvBe_`+4F@SqjhcGkQ^<=9Vn<>t8#~Ea1A;LB3Nt4+LtJ4%%K@ p70t`icAP)kaLyJr?M>Wg>h)(XWIZ->?gUVI=IQF^vd$@?2>>MVC&B;# literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_add_bordered.imageset/icon_add_bordered@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..4571fd931ce22701e2106663dd5d41be91c03533 GIT binary patch literal 459 zcmV;+0W|)JP)C6MlhnUXFq-vN4e z&iI}V_c_K3XMrRuYk$|q0Mcu5FYqzPW z>#z?6Pyhu`00q#00kJ!daX+xCXHerjm!Ub*yQ0T{j^;?OWOe9S068}hyMuFfR}1Ve zU)Wtwak^Y6rcMtopqS|;FqguP88;HxZ>{vaT!MKsicgZh&lwkvRYTL%c(G^8m)zEe z7Ngi literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/Contents.json new file mode 100644 index 00000000000..2f1b18ab5fa --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icon_cancel.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_cancel@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_cancel@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..e27b64694d02da460301e3536ca7f31c5e42379d GIT binary patch literal 912 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|T2doC(|mmy zw18|523AHP24;{FAY@>aVqgWc85q16rQz%#Mh&PMCI*J~Oa>OHnkXO*0vxV%QuQiw3qZOUY$~jP%-qzHM1_jnoV;SI3R@+x3M(KRB&@Hb09I0xZL1XF8=&Bv zUzDm~re~mMpk&9TprBw=l#*r@P?Wt5Z@Sn2DRmzV368|&p4rRy77T3YHG z80i}s=>k>g7FXt#Bv$C=6)QswftllyTAW;zSx}OhpQivaH!&%{w8U0P31kr*K-^i9 znTD__uNdkrpa=CqGWv#k2KsQbfm&@qqE`MznW;dVLFU^T+JIG}h(YbK(Fa+MU0Xy>F zWotk1N_g8n^LDu3?!CeLwCg0#?Fo;aB;j8?U-yTKRG&rlx>FIkf6vBns&6-Vr2naV zf|1&^-G^VkEBctF{G@b2`}AG@S5q&y-C2~rcI6}QI{o84bHlmk=~?gBRms%<8C>m` zbS~iD`Y5sU@-j@8Zj*9X%#uERzxnq`_sRB3EQWqBCqGk>zqOxPLHqsHC!Pns*`BZc zW~2V`{|PA-ZC literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel@2x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb51c456b4b1e17e90fff5b5d13cf4f4baa3cab GIT binary patch literal 1270 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}EvXTnX}-P; zT0k}j11qBt12aeo5Hc`IF|dN!3=Ce3(r|VVqXtwB69YqgCIbspO%#v@0S_Ps>W0$H z3m6e5E?|PIHdw%nV1u-2@G|lPDb50q$YKTtZeb8+WSBKa0%%%fW=KRygs+cPa(=E} zVoH8es$NBI0Z12vO@$SZnVVXYs8ErclUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO| zi&7QL^bGV2l1AfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL% z(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjoGZknv$b36P8?Z_gF{nK@`XI}Z90Tzw zSQO}0J1!f2c(B=VNya^7XJBAj=IP=XlEM0RhIii;2cEXs(_5Yi#Vl=2U>4di_wSns z9`gq(8G1*jC4Z2U`#0s6in^DTr~2ePm&hWmsW*7*N95)=io%S|m2l)U}a%qgKH2 zWoOU*EtP(#Z?>iP@_||Mn=b4u+cFAY5 zulH538#DKA?7S;;+uEa4;?j{eE5|~v=lgPhUE33JE8k3N$9iFVR!WdY_iAjo#e$83L!>uKhgcsM*B(Aywnk z3dw2m;rHM2E%{>c&Q|k#{qY^Y*l#!9SiC)@K7;cnt5sp_1%>xIT_;XHXP=t#+4;@p zgI~*+a+KYjESC7G)>?+YRo?Z2&E)PIYlQ1w`6bRfvN__&6u*@HSI_y%iT$=av!icDhHGsl7Rc5$thH=mfs7fHzIB&`tk?_O@m-uUc}frkB#+WpZ-M4s*5 zc;xil2l-M4`CS{$V(%}0rZ<1}2Q`jU+t128JG@6#jiW7=_4}p>$<0ruM5>;hNh|y^#&ir YQ+j?^&N%VU6qNZrUHx3vIVCg!05Ub+fdBvi literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_cancel.imageset/icon_cancel@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb51c456b4b1e17e90fff5b5d13cf4f4baa3cab GIT binary patch literal 1270 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}EvXTnX}-P; zT0k}j11qBt12aeo5Hc`IF|dN!3=Ce3(r|VVqXtwB69YqgCIbspO%#v@0S_Ps>W0$H z3m6e5E?|PIHdw%nV1u-2@G|lPDb50q$YKTtZeb8+WSBKa0%%%fW=KRygs+cPa(=E} zVoH8es$NBI0Z12vO@$SZnVVXYs8ErclUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO| zi&7QL^bGV2l1AfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL% z(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjoGZknv$b36P8?Z_gF{nK@`XI}Z90Tzw zSQO}0J1!f2c(B=VNya^7XJBAj=IP=XlEM0RhIii;2cEXs(_5Yi#Vl=2U>4di_wSns z9`gq(8G1*jC4Z2U`#0s6in^DTr~2ePm&hWmsW*7*N95)=io%S|m2l)U}a%qgKH2 zWoOU*EtP(#Z?>iP@_||Mn=b4u+cFAY5 zulH538#DKA?7S;;+uEa4;?j{eE5|~v=lgPhUE33JE8k3N$9iFVR!WdY_iAjo#e$83L!>uKhgcsM*B(Aywnk z3dw2m;rHM2E%{>c&Q|k#{qY^Y*l#!9SiC)@K7;cnt5sp_1%>xIT_;XHXP=t#+4;@p zgI~*+a+KYjESC7G)>?+YRo?Z2&E)PIYlQ1w`6bRfvN__&6u*@HSI_y%iT$=av!icDhHGsl7Rc5$thH=mfs7fHzIB&`tk?_O@m-uUc}frkB#+WpZ-M4s*5 zc;xil2l-M4`CS{$V(%}0rZ<1}2Q`jU+t128JG@6#jiW7=_4}p>$<0ruM5>;hNh|y^#&ir YQ+j?^&N%VU6qNZrUHx3vIVCg!05Ub+fdBvi literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/Contents.json new file mode 100644 index 00000000000..42245a1ec1d --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_link_error@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/icon_link_error@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_error.imageset/icon_link_error@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..84a7a861ec667974897a82e0fcff0549bde62053 GIT binary patch literal 466 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-st^qzFu0Wb{aOc&l??6+;OM?7@ z8Ti5)=AF3ybd9@gN^xVVrS`7=qR_dki+Z^lSHjefGrjEHzeVZ9$$J(Tnw1Mp+O{Y>>RtIvVos0o zmmYgA@hJ=bwH@iyp7Y`8RP7m$Cl^iqw)LOP%htuoRtmPQuXCEh!}-=#1X}KR*cu&F zkbKAW;V%a3hH0$pJ~~-$XVI7;v13`Ib(U0xLBPdJ4iTH0^SCu6ZZ2i)WkoF^3&Hhg-g8Rj5lsbejxK* zChlnTr(ZFRJGix#ey?F(P`tE{zjt-ahm*b9EAs2#ZLin3y?;%<`coe3#0RIYTo!!k zdBjSn&Xn(s+KI}_f091pIv-ZrOg8@3%d|-a@PlH;)78&qol`;+08}lm AivR!s literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/Contents.json new file mode 100644 index 00000000000..1573b0fbe20 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_link_success@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/icon_link_success@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_link_success.imageset/icon_link_success@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..db8ff7fc4b52d04c117dea5ca82a7400cb3b44e0 GIT binary patch literal 461 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sHUT~%u0Wb>a6w-UWT|&u8A^- z*o$Uff5^W3GP}4qbKlL?1`f~8ayx(8<8Z;ODs_s=pGw1=ZkY@Fw@m%oam;=FM{_;* zC+BT1Se7^_+xqeOWK4|XW;eUyF#lP0_?Ha(n#E@n>L04xf7gkqTmJLPYt7RO&OKi? z|JuQ*l;!Fv^QNUuo_x7Du4?U{eGi_TJ@ocwV5WFMb(qPm*886w7RCOs6@5|m@Vn#z zx6K9BatxDZwB8O*>{sw!dnh_TK}K-t0Sl#!!wqL9eEQ#SD8;O&v+V-w8>M^9(?2wt zNJPCj#dUgrM^3?u*Jl17GEc{BynQDxOJ8N_oUJ#1i5E!~_5a}dbr%#Vp00i_>zopr E04#L2IsgCw literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/Contents.json new file mode 100644 index 00000000000..c34bcd9af97 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_menu@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/icon_menu@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu.imageset/icon_menu@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..202876bfaada6e2b920edad8863afbe03a517e5b GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^JV0!~!2%@vj|A@mQt_THjv*Dd-d^0u+hD-sa?#w$ zEy4IkOU^VwBc{bOm|7enu6Pu@`%&=RdUNdfuu>Pk)O45&v_jNjqy@u(_suoHNiW22WQ%mvv4FO#qqA BI1c~- literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/Contents.json b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/Contents.json new file mode 100644 index 00000000000..7edcc25ee4e --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "icon_menu_horizontal.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_menu_horizontal@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_menu_horizontal@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..2fc3f99532e8f22f45a1e2229c20fce8c9642488 GIT binary patch literal 670 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~d!3HGTx9oodq!^2X+?^QKos)S9=?Nk^)#sNw%$0gl~X? zbAC~(f|;Iyo`I4bmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGw zZ(yWvWTXpJp<7&;SCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>< zNoE?tro3XPw}2kh2g&Fg>KW+6%?4_<0f}1q7iFdbZ3dZdXJ`Xfi6REI$3`DyIg(=_ zJ_U;cy=up0qYn=@J1)t%hwQ+R^z(Fa43UsbPDn`LV0fhO@JH|zTTp_-77LHZ^%`}Y zOClR*uy)LMJnB%i+dAHCQy|4z;1OBOz`!jG!i)^F=12fdi_8p(D2ed(u}aR* z)k{ptPfFFR$SnZrVz8;O0y1+`OA-|-a&z*EttxDlz$&bOY>=?Nk^)#sNw%$0gl~X? zbAC~(f|;Iyo`I4bmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGw zZ(yWvWTXpJp<7&;SCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>< zNoE?tro3XPw}2kh2g&Fg>KW+6%?4_<0f}1q7iFdbZ3dZdXJ`Xfi6REI$3`DyIg(=_ zJ_U;cy=up0qYn=@J1)t%hwQ+RyyNNO7-Au~cJgjMCPfjKa9y)s+Slqf^@>G#8@3Owtom#I(&h{ z;E2vjn+R@u)1X>E@6Ya?TkmD_`*2;%-uUfG)f)SN3EJORYO?LM^FHsItXL@cwpiwM zdEApMOH1`N4@=kkX8%(cw0DsH_UE;F|DSn`eM%M23@)&*%~Rri5Np%mdKI;Vst0GU(sPXGV_ literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal@3x.png b/StripePaymentSheet/StripePaymentSheet/Resources/StripePaymentSheet.xcassets/Link/icon_menu_horizontal.imageset/icon_menu_horizontal@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..431051c7863fbc95694d952884569ff3c2c3ce20 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^20+Zi!2%@vHh;SXq>4RV978H@ZJoSP@PGmjb3KdO ziL?!#H+lpm8UyDjX&P8e<=Z_u?)fpM2A8FY5_5fQn2HTIWU^lun<}BdKP>7H(`56T z2CKTgeE55x9TG~mx9&e8V}HSE=k5(h?ko(9iAW0i5trSl@~q+_!>R9Sy}Lv`lH_`P WgUw&n#QXzV&*16m=d#Wzp$P!Lw?7~N literal 0 HcmV?d00001 diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Button+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Button+Link.swift new file mode 100644 index 00000000000..383afb5370c --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Button+Link.swift @@ -0,0 +1,70 @@ +// +// Button+Link.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 12/1/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeUICore +import UIKit + +extension Button.Configuration { + + static func linkPrimary() -> Self { + var configuration: Button.Configuration = .primary() + configuration.font = LinkUI.font(forTextStyle: .bodyEmphasized) + configuration.insets = LinkUI.buttonMargins + configuration.cornerRadius = LinkUI.cornerRadius + + // Colors + configuration.foregroundColor = .linkPrimaryButtonForeground + configuration.backgroundColor = .linkBrand + configuration.disabledBackgroundColor = .linkBrand + + configuration.colorTransforms.disabledForeground = .setAlpha(amount: 0.5) + configuration.colorTransforms.highlightedForeground = .darken(amount: 0.2) + + return configuration + } + + static func linkSecondary() -> Self { + var configuration: Button.Configuration = .linkPrimary() + + // Colors + configuration.foregroundColor = .linkSecondaryButtonForeground + configuration.backgroundColor = .linkSecondaryButtonBackground + configuration.disabledBackgroundColor = .linkSecondaryButtonBackground + + return configuration + } + + static func linkPlain() -> Self { + var configuration: Button.Configuration = .plain() + configuration.font = LinkUI.font(forTextStyle: .body) + configuration.foregroundColor = .linkBrandDark + configuration.disabledForegroundColor = nil + configuration.colorTransforms.highlightedForeground = .setAlpha(amount: 0.4) + configuration.colorTransforms.disabledForeground = .setAlpha(amount: 0.3) + return configuration + } + + static func linkBordered() -> Self { + var configuration: Button.Configuration = .plain() + configuration.font = LinkUI.font(forTextStyle: .detailEmphasized) + configuration.insets = .insets(top: 4, leading: 12, bottom: 4, trailing: 12) + configuration.borderWidth = 1 + configuration.cornerRadius = LinkUI.mediumCornerRadius + + // Colors + configuration.foregroundColor = .label + configuration.backgroundColor = .clear + configuration.borderColor = .linkControlBorder + + configuration.colorTransforms.highlightedForeground = .setAlpha(amount: 0.5) + configuration.colorTransforms.highlightedBorder = .setAlpha(amount: 0.5) + + return configuration + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/ConfirmButton+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/ConfirmButton+Link.swift new file mode 100644 index 00000000000..ab6795a9c91 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/ConfirmButton+Link.swift @@ -0,0 +1,39 @@ +// +// ConfirmButton+Link.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 1/12/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import UIKit + +extension ConfirmButton { + + static func makeLinkButton( + callToAction: CallToActionType, + compact: Bool = false, + didTap: @escaping () -> Void + ) -> ConfirmButton { + let button = ConfirmButton( + callToAction: callToAction, + appearance: LinkUI.appearance, + didTap: didTap + ) + + // Override the background color of the `.succeeded` state. Make it match + // the background color of the `.enabled` state. + // TODO(link): Needs refactor +// button.succeededBackgroundColor = ( +// LinkUI.appearance.primaryButton.backgroundColor ?? +// LinkUI.appearance.colors.primary +// ) + + button.directionalLayoutMargins = compact + ? LinkUI.compactButtonMargins + : LinkUI.buttonMargins + + return button + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift new file mode 100644 index 00000000000..0b59fe4e1b1 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift @@ -0,0 +1,79 @@ +// +// ButtonLinkSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 2/14/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import StripeCoreTestUtils +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripeUICore + +class ButtonLinkSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testPrimary() { + let sut = makeSUT(configuration: .linkPrimary(), title: "Primary Button") + verify(sut) + } + + func testSecondary() { + let sut = makeSUT(configuration: .linkSecondary(), title: "Secondary Button") + verify(sut) + } + + func testBordered() { + let sut = makeSUT(configuration: .linkBordered(), title: "Bordered Button") + verify(sut) + } + + func testPlain() { + let sut = makeSUT(configuration: .linkPlain(), title: "Plain Button") + verify(sut) + } + + func verify( + _ sut: Button, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + let size = sut.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) + sut.bounds = CGRect(origin: .zero, size: size) + STPSnapshotVerifyView(sut, file: file, line: line) + + sut.isHighlighted = true + STPSnapshotVerifyView(sut, identifier: "Highlighted", file: file, line: line) + + sut.isHighlighted = false + sut.isEnabled = false + STPSnapshotVerifyView(sut, identifier: "Disabled", file: file, line: line) + + sut.isHighlighted = false + sut.isEnabled = true + sut.isLoading = true + STPSnapshotVerifyView(sut, identifier: "Loading", file: file, line: line) + } + +} + +extension ButtonLinkSnapshotTests { + + func makeSUT( + configuration: Button.Configuration, + title: String + ) -> Button { + return Button(configuration: configuration, title: title) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift new file mode 100644 index 00000000000..d5f9d717492 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift @@ -0,0 +1,59 @@ +// +// LinkBadgeViewSnapshotTest.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 4/29/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkBadgeViewSnapshotTest: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testNeutral() { + verify( + LinkBadgeView( + type: .neutral, + text: "Neutral message" + ) + ) + } + + func testError() { + verify( + LinkBadgeView( + type: .error, + text: "Error message" + ) + ) + } + + func verify( + _ sut: UIView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + let size = sut.systemLayoutSizeFitting( + UIView.layoutFittingCompressedSize, + withHorizontalFittingPriority: .fittingSizeLevel, + verticalFittingPriority: .fittingSizeLevel + ) + + sut.bounds = CGRect(origin: .zero, size: size) + STPSnapshotVerifyView(sut, identifier: identifier, file: file, line: line) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift new file mode 100644 index 00000000000..c80772cf42f --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift @@ -0,0 +1,75 @@ +// +// LinkCardEditElementSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 10/3/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import UIKit + +@testable import Stripe +@testable@_spi(STP) import StripeCoreTestUtils +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripeUICore + +final class LinkCardEditElementSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // self.recordMode = true + + // `LinkCardEditElement` depends on `AddressSectionElement`, which requires + // address specs to be loaded in memory. + let expectation = expectation(description: "Load address specs") + AddressSpecProvider.shared.loadAddressSpecs { + expectation.fulfill() + } + + wait(for: [expectation], timeout: STPTestingNetworkRequestTimeout) + } + + func testDefault() { + let sut = makeSUT(isDefault: true) + verify(sut) + } + + func testNonDefault() { + let sut = makeSUT(isDefault: false) + verify(sut) + } + + func verify( + _ element: LinkCardEditElement, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + element.view.autosizeHeight(width: 340) + STPSnapshotVerifyView(element.view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkCardEditElementSnapshotTests { + + func makeSUT(isDefault: Bool) -> LinkCardEditElement { + let paymentMethod = ConsumerPaymentDetails( + stripeID: "1", + details: .card( + card: .init( + expiryYear: 2032, + expiryMonth: 1, + brand: "visa", + last4: "4242", + checks: nil + ) + ), + isDefault: isDefault + ) + + return LinkCardEditElement(paymentMethod: paymentMethod, configuration: .init()) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift new file mode 100644 index 00000000000..0d9e04bcd01 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift @@ -0,0 +1,123 @@ +// +// LinkInlineSignupElementSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 1/21/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +@_spi(STP) import StripeCoreTestUtils +@_spi(STP) import StripeUICore +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkInlineSignupElementSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testDefaultState() { + let sut = makeSUT() + verify(sut) + } + + func testExpandedState() { + let sut = makeSUT(saveCheckboxChecked: true, emailAddress: "user@example.com") + verify(sut) + } + + func testExpandedState_nonUS() { + let sut = makeSUT( + saveCheckboxChecked: true, + emailAddress: "user@example.com", + country: "CA" + ) + verify(sut) + } + + func testExpandedState_nonUS_preFilled() { + let sut = makeSUT( + saveCheckboxChecked: true, + emailAddress: "user@example.com", + country: "CA", + preFillName: "Jane Diaz", + preFillPhone: "+13105551234" + ) + verify(sut) + } + + func verify( + _ element: LinkInlineSignupElement, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + element.view.autosizeHeight(width: 340) + STPSnapshotVerifyView(element.view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkInlineSignupElementSnapshotTests { + + struct MockAccountService: LinkAccountServiceProtocol { + func lookupAccount( + withEmail email: String?, + completion: @escaping (Result) -> Void + ) { + completion( + .success( + PaymentSheetLinkAccount( + email: "user@example.com", + session: nil, + publishableKey: nil + ) + ) + ) + } + + func hasEmailLoggedOut(email: String) -> Bool { + // TODO(porter): Determine if we want to implement this in tests + return false + } + } + + func makeSUT( + saveCheckboxChecked: Bool = false, + emailAddress: String? = nil, + country: String = "US", + preFillName: String? = nil, + preFillPhone: String? = nil + ) -> LinkInlineSignupElement { + var configuration = PaymentSheet.Configuration() + configuration.merchantDisplayName = "[Merchant]" + configuration.defaultBillingDetails.name = preFillName + configuration.defaultBillingDetails.phone = preFillPhone + + let viewModel = LinkInlineSignupViewModel( + configuration: configuration, + accountService: MockAccountService(), + country: country + ) + + viewModel.saveCheckboxChecked = saveCheckboxChecked + viewModel.emailAddress = emailAddress + + if emailAddress != nil { + // Wait for account to load + let expectation = notNullExpectation(for: viewModel, keyPath: \.linkAccount) + wait(for: [expectation], timeout: 10) + } + + return .init(viewModel: viewModel) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift new file mode 100644 index 00000000000..b0646cce80b --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift @@ -0,0 +1,78 @@ +// +// LinkInstantDebitMandateViewSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 2/17/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI +@testable@_spi(STP) import StripeUICore + +class LinkInstantDebitMandateViewSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testDefault() { + let sut = makeSUT() + verify(sut) + } + + func testLocalization() { + performLocalizedSnapshotTest(forLanguage: "de") + performLocalizedSnapshotTest(forLanguage: "es") + performLocalizedSnapshotTest(forLanguage: "el-GR") + performLocalizedSnapshotTest(forLanguage: "it") + performLocalizedSnapshotTest(forLanguage: "ja") + performLocalizedSnapshotTest(forLanguage: "ko") + performLocalizedSnapshotTest(forLanguage: "zh-Hans") + } + +} + +// MARK: - Helpers + +extension LinkInstantDebitMandateViewSnapshotTests { + + func verify( + _ view: UIView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + view.autosizeHeight(width: 250) + STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) + } + + func performLocalizedSnapshotTest( + forLanguage language: String, + file: StaticString = #filePath, + line: UInt = #line + ) { + STPLocalizationUtils.overrideLanguage(to: language) + let sut = makeSUT() + STPLocalizationUtils.overrideLanguage(to: nil) + verify(sut, identifier: language, file: file, line: line) + } + +} + +// MARK: - Factory + +extension LinkInstantDebitMandateViewSnapshotTests { + + func makeSUT() -> LinkInstantDebitMandateView { + return LinkInstantDebitMandateView() + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift new file mode 100644 index 00000000000..b5900c44145 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift @@ -0,0 +1,89 @@ +// +// LinkNavigationBarSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 4/27/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkNavigationBarSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testDefault() { + let sut = makeSUT() + verify(sut) + + sut.showBackButton = true + verify(sut, identifier: "BackButton") + } + + func testWithEmailAddress() { + let sut = makeSUT() + sut.linkAccount = makeAccountStub(email: "user@example.com") + verify(sut) + + sut.showBackButton = true + verify(sut, identifier: "BackButton") + } + + func testWithLongEmailAddress() { + let sut = makeSUT() + sut.linkAccount = makeAccountStub(email: "a.very.very.long.customer.name@example.com") + verify(sut) + + sut.showBackButton = true + verify(sut, identifier: "BackButton") + } + + func verify( + _ sut: UIView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + let size = sut.systemLayoutSizeFitting( + CGSize(width: 375, height: UIView.layoutFittingCompressedSize.height), + withHorizontalFittingPriority: .required, + verticalFittingPriority: .fittingSizeLevel + ) + + sut.bounds = CGRect(origin: .zero, size: size) + STPSnapshotVerifyView(sut, identifier: identifier, file: file, line: line) + } + +} + +extension LinkNavigationBarSnapshotTests { + fileprivate struct LinkAccountStub: PaymentSheetLinkAccountInfoProtocol { + let email: String + let redactedPhoneNumber: String? + let isRegistered: Bool + let isLoggedIn: Bool + } + + fileprivate func makeAccountStub(email: String) -> LinkAccountStub { + return LinkAccountStub( + email: email, + redactedPhoneNumber: "+1********55", + isRegistered: true, + isLoggedIn: true + ) + } + + fileprivate func makeSUT() -> LinkNavigationBar { + return LinkNavigationBar() + } +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift new file mode 100644 index 00000000000..e62a1a1e6d3 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift @@ -0,0 +1,51 @@ +// +// LinkNoticeViewSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 3/31/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkNoticeViewSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testError() { + verify( + LinkNoticeView( + type: .error, + text: + "This card has expired. Update it to keep using it or use a different payment method." + ) + ) + } + + func verify( + _ sut: UIView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + let size = sut.systemLayoutSizeFitting( + CGSize(width: 340, height: UIView.layoutFittingCompressedSize.height), + withHorizontalFittingPriority: .required, + verticalFittingPriority: .fittingSizeLevel + ) + + sut.bounds = CGRect(origin: .zero, size: size) + STPSnapshotVerifyView(sut, identifier: identifier, file: file, line: line) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift new file mode 100644 index 00000000000..686715d582f --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift @@ -0,0 +1,108 @@ +// +// LinkPaymentMethodPickerSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 11/8/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import StripeCoreTestUtils +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkPaymentMethodPickerSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testNormal() { + let mockDataSource = MockDataSource() + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.layoutSubviews() + + verify(picker, identifier: "First Option") + + picker.selectedIndex = 1 + verify(picker, identifier: "Second Option") + } + + func testExpanded() { + let mockDataSource = MockDataSource() + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.layoutSubviews() + picker.setExpanded(true, animated: false) + + verify(picker) + } + + func testUnsupportedBankAccount() { + let mockDataSource = MockDataSource() + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.supportedPaymentMethodTypes = [.card] + picker.layoutSubviews() + picker.setExpanded(true, animated: false) + + verify(picker) + } + + func testEmpty() { + let mockDataSource = MockDataSource(empty: true) + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.layoutSubviews() + + verify(picker) + } + + func verify( + _ view: UIView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + view.autosizeHeight(width: 335) + view.backgroundColor = .white + STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkPaymentMethodPickerSnapshotTests { + + fileprivate final class MockDataSource: LinkPaymentMethodPickerDataSource { + let paymentMethods: [ConsumerPaymentDetails] + + init( + empty: Bool = false + ) { + self.paymentMethods = empty ? [] : LinkStubs.paymentMethods() + } + + func numberOfPaymentMethods(in picker: LinkPaymentMethodPicker) -> Int { + return paymentMethods.count + } + + func paymentPicker( + _ picker: LinkPaymentMethodPicker, + paymentMethodAt index: Int + ) -> ConsumerPaymentDetails { + return paymentMethods[index] + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift new file mode 100644 index 00000000000..7f6d910e09a --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift @@ -0,0 +1,41 @@ +// +// LinkToastSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 12/7/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkToastSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testSuccess() { + let toast = LinkToast(type: .success, text: "Success message!") + verify(toast) + } + + func verify( + _ toast: LinkToast, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + let size = toast.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) + toast.bounds = CGRect(origin: .zero, size: size) + STPSnapshotVerifyView(toast, identifier: identifier, file: file, line: line) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift new file mode 100644 index 00000000000..752ddeccf45 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift @@ -0,0 +1,84 @@ +// +// LinkVerificationViewSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 12/7/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import iOSSnapshotTestCase +import StripeCoreTestUtils +import UIKit + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkVerificationViewSnapshotTests: FBSnapshotTestCase { + + override func setUp() { + super.setUp() + // recordMode = true + } + + func testModal() { + let sut = makeSUT(mode: .modal) + verify(sut) + } + + func testModalWithErrorMessage() { + let sut = makeSUT(mode: .modal) + sut.errorMessage = "The provided verification code has expired." + verify(sut) + } + + func testInlineLogin() { + let sut = makeSUT(mode: .inlineLogin) + verify(sut) + } + + func testEmbedded() { + let sut = makeSUT(mode: .embedded) + verify(sut) + } + + func verify( + _ view: LinkVerificationView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + view.autosizeHeight(width: 340) + STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkVerificationViewSnapshotTests { + + struct LinkAccountStub: PaymentSheetLinkAccountInfoProtocol { + let email: String + let redactedPhoneNumber: String? + let isRegistered: Bool + let isLoggedIn: Bool + } + + func makeSUT(mode: LinkVerificationView.Mode) -> LinkVerificationView { + let sut = LinkVerificationView( + mode: mode, + linkAccount: LinkAccountStub( + email: "user@example.com", + redactedPhoneNumber: "+1********55", + isRegistered: true, + isLoggedIn: false + ) + ) + + sut.tintColor = .linkBrand + + return sut + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift new file mode 100644 index 00000000000..27bf3bf48d1 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift @@ -0,0 +1,144 @@ +// +// PayWithLinkViewController-WalletViewModelTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 3/31/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import StripeCoreTestUtils +import XCTest + +@testable@_spi(STP) import Stripe +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class PayWithLinkViewController_WalletViewModelTests: XCTestCase { + + func test_shouldRecollectCardCVC() throws { + let sut = try makeSUT() + + // Card with passing CVC checks + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card + XCTAssertFalse(sut.shouldRecollectCardCVC) + + // Card with failing CVC checks + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.cardWithFailingChecks + XCTAssertTrue( + sut.shouldRecollectCardCVC, + "Should recollect CVC when CVC checks are failing" + ) + + // Expired card + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.expiredCard + XCTAssertTrue(sut.shouldRecollectCardCVC, "Should recollect CVC when card has expired") + + // Bank account (CVC not supported) + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.bankAccount + XCTAssertFalse(sut.shouldRecollectCardCVC) + } + + func test_shouldRecollectCardExpiry() throws { + let sut = try makeSUT() + + // Non-expired card + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card + XCTAssertFalse(sut.shouldRecollectCardExpiryDate) + + // Expired card + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.expiredCard + XCTAssertTrue( + sut.shouldRecollectCardExpiryDate, + "Should recollect new expiry date when card has expired" + ) + + // Bank account (CVC not supported) + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.bankAccount + XCTAssertFalse(sut.shouldRecollectCardCVC) + } + + func test_shouldShowInstantDebitMandate() throws { + let sut = try makeSUT() + + // Card + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card + XCTAssertFalse(sut.shouldShowInstantDebitMandate) + + // Bank account + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.bankAccount + XCTAssertTrue(sut.shouldShowInstantDebitMandate) + } + + func test_confirmButtonStatus_shouldHandleNoSelection() throws { + let sut = try makeSUT() + + // No selection + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.notExisting + XCTAssertEqual( + sut.confirmButtonStatus, + .disabled, + "Button should be disabled when no payment method is selected" + ) + + // Selection + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card + XCTAssertEqual(sut.confirmButtonStatus, .enabled) + } + + func test_confirmButtonStatus_shouldHandleCVCRecollectionRequirements() throws { + let sut = try makeSUT() + + sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.cardWithFailingChecks + XCTAssertEqual( + sut.confirmButtonStatus, + .disabled, + "Button should be disabled when no CVC is provided and a card with failing CVC checks is selected" + ) + + // Provide a CVC + sut.cvc = "123" + XCTAssertEqual(sut.confirmButtonStatus, .enabled) + } +} + +extension PayWithLinkViewController_WalletViewModelTests { + + func makeSUT() throws -> PayWithLinkViewController.WalletViewModel { + // Link settings don't live in the PaymentIntent object itself, but in the /elements/sessions API response + // So we construct a minimal response (see STPPaymentIntentTest.testDecodedObjectFromAPIResponseMapping) to parse them + let paymentIntentJson = try XCTUnwrap(STPTestUtils.jsonNamed(STPTestJSONPaymentIntent)) + let orderedPaymentJson = ["card", "link"] + let paymentIntentResponse = [ + "payment_intent": paymentIntentJson, + "ordered_payment_method_types": orderedPaymentJson, + ] as [String: Any] + let linkSettingsJson = ["link_funding_sources": ["CARD"]] + let response = [ + "payment_method_preference": paymentIntentResponse, + "link_settings": linkSettingsJson, + ] + let paymentIntent = try XCTUnwrap( + STPPaymentIntent.decodedObject(fromAPIResponse: response) + ) + + return PayWithLinkViewController.WalletViewModel( + // TODO(ramont): Fully mock `PaymentSheetLinkAccount and remove this. + linkAccount: .init( + email: "user@example.com", + session: LinkStubs.consumerSession(), + publishableKey: nil + ), + context: .init( + intent: .paymentIntent(paymentIntent), + configuration: .init(), + shouldOfferApplePay: false, + shouldFinishOnClose: false, + callToAction: nil + ), + paymentMethods: LinkStubs.paymentMethods() + ) + } + +} From 4f2fea1e20da12df8b8eece787e89e944dcc15fa Mon Sep 17 00:00:00 2001 From: David Estes Date: Tue, 8 Oct 2024 16:54:42 -0700 Subject: [PATCH 02/12] Update tests --- .../project.pbxproj | 100 ++++++ .../Source/Helpers/Images.swift | 7 + .../Link/Components/Badge/LinkBadgeView.swift | 133 ++++++++ .../NavigationBar/LinkNavigationBar.swift | 189 +++++++++++ .../Components/Notice/LinkNoticeView.swift | 113 +++++++ .../LinkPaymentMethodPicker-AddButton.swift | 99 ++++++ .../LinkPaymentMethodPicker-Cell.swift | 280 ++++++++++++++++ ...kPaymentMethodPicker-CellContentView.swift | 138 ++++++++ .../LinkPaymentMethodPicker-Header.swift | 194 +++++++++++ .../LinkPaymentMethodPicker-RadioButton.swift | 114 +++++++ .../LinkPaymentMethodPicker.swift | 312 ++++++++++++++++++ .../Link/Components/Toast/LinkToast.swift | 182 ++++++++++ .../Link/Extensions/UIColor+Link.swift | 88 +++++ .../Views/LinkInstantDebitMandateView.swift | 119 +++++++ .../LinkKeyboardAvoidingScrollView.swift | 75 +++++ .../Link/ButtonLinkSnapshotTests.swift | 2 +- .../Link/LinkBadgeViewSnapshotTest.swift | 3 +- .../LinkCardEditElementSnapshotTests.swift | 75 ----- ...LinkInlineSignupElementSnapshotTests.swift | 123 ------- ...InstantDebitMandateViewSnapshotTests.swift | 3 +- .../Link/LinkNavigationBarSnapshotTests.swift | 3 +- .../Link/LinkNoticeViewSnapshotTests.swift | 3 +- ...LinkPaymentMethodPickerSnapshotTests.swift | 108 ------ .../Link/LinkToastSnapshotTests.swift | 3 +- .../LinkVerificationViewSnapshotTests.swift | 84 ----- ...kViewController-WalletViewModelTests.swift | 144 -------- .../Internal/UI/Views/CardBrandView.swift | 9 +- .../testBordered@3x.png | Bin 0 -> 6259 bytes .../testBordered_Disabled@3x.png | Bin 0 -> 6677 bytes .../testBordered_Highlighted@3x.png | Bin 0 -> 5985 bytes .../testBordered_Loading@3x.png | Bin 0 -> 4860 bytes .../testPlain@3x.png | Bin 0 -> 4655 bytes .../testPlain_Disabled@3x.png | Bin 0 -> 4080 bytes .../testPlain_Highlighted@3x.png | Bin 0 -> 4217 bytes .../testPlain_Loading@3x.png | Bin 0 -> 3937 bytes .../testPrimary@3x.png | Bin 0 -> 8346 bytes .../testPrimary_Disabled@3x.png | Bin 0 -> 7915 bytes .../testPrimary_Highlighted@3x.png | Bin 0 -> 8277 bytes .../testPrimary_Loading@3x.png | Bin 0 -> 6173 bytes .../testSecondary@3x.png | Bin 0 -> 10529 bytes .../testSecondary_Disabled@3x.png | Bin 0 -> 9844 bytes .../testSecondary_Highlighted@3x.png | Bin 0 -> 10487 bytes .../testSecondary_Loading@3x.png | Bin 0 -> 7034 bytes .../testError@3x.png | Bin 0 -> 5681 bytes .../testNeutral@3x.png | Bin 0 -> 4903 bytes .../testDefault@3x.png | Bin 0 -> 15988 bytes .../testLocalization_de@3x.png | Bin 0 -> 15988 bytes .../testLocalization_el_GR@3x.png | Bin 0 -> 15988 bytes .../testLocalization_es@3x.png | Bin 0 -> 15988 bytes .../testLocalization_it@3x.png | Bin 0 -> 15988 bytes .../testLocalization_ja@3x.png | Bin 0 -> 15988 bytes .../testLocalization_ko@3x.png | Bin 0 -> 15988 bytes .../testLocalization_zh_Hans@3x.png | Bin 0 -> 15988 bytes .../testDefault@3x.png | Bin 0 -> 8480 bytes .../testDefault_BackButton@3x.png | Bin 0 -> 3933 bytes .../testWithEmailAddress@3x.png | Bin 0 -> 8480 bytes .../testWithEmailAddress_BackButton@3x.png | Bin 0 -> 3933 bytes .../testWithLongEmailAddress@3x.png | Bin 0 -> 8480 bytes ...testWithLongEmailAddress_BackButton@3x.png | Bin 0 -> 3933 bytes .../testError@3x.png | Bin 0 -> 22057 bytes .../testSuccess@3x.png | Bin 0 -> 9807 bytes 61 files changed, 2161 insertions(+), 542 deletions(-) create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Badge/LinkBadgeView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Notice/LinkNoticeView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkKeyboardAvoidingScrollView.swift delete mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift delete mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift delete mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift delete mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift delete mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Disabled@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Highlighted@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Loading@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Disabled@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Highlighted@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Loading@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary_Disabled@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary_Highlighted@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary_Loading@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary_Disabled@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary_Highlighted@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary_Loading@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkBadgeViewSnapshotTest/testError@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkBadgeViewSnapshotTest/testNeutral@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testDefault@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_de@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_el_GR@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_es@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_it@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_ja@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_ko@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_zh_Hans@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testDefault@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testDefault_BackButton@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithEmailAddress@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithEmailAddress_BackButton@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithLongEmailAddress@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithLongEmailAddress_BackButton@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNoticeViewSnapshotTests/testError@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkToastSnapshotTests/testSuccess@3x.png diff --git a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj index 1eed31f853f..b430d5bd8d8 100644 --- a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj +++ b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj @@ -58,6 +58,21 @@ 31699A832BE183D40048677F /* DownloadManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31699A822BE183D40048677F /* DownloadManagerTest.swift */; }; 316B33122B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 316B33112B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift */; }; 31AD3BE72B0C2D080080C800 /* UIApplication+StripePaymentSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31AD3BE62B0C2D080080C800 /* UIApplication+StripePaymentSheet.swift */; }; + 31CC9B792CB5F69600E84A38 /* LinkNavigationBarSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B712CB5F69600E84A38 /* LinkNavigationBarSnapshotTests.swift */; }; + 31CC9B7D2CB5F69600E84A38 /* ButtonLinkSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B6C2CB5F69600E84A38 /* ButtonLinkSnapshotTests.swift */; }; + 31CC9B7E2CB5F69600E84A38 /* LinkNoticeViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B722CB5F69600E84A38 /* LinkNoticeViewSnapshotTests.swift */; }; + 31CC9B7F2CB5F69600E84A38 /* LinkPopupURLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B742CB5F69600E84A38 /* LinkPopupURLParserTests.swift */; }; + 31CC9B802CB5F69600E84A38 /* LinkToastSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B752CB5F69600E84A38 /* LinkToastSnapshotTests.swift */; }; + 31CC9B812CB5F69600E84A38 /* LinkInstantDebitMandateViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B702CB5F69600E84A38 /* LinkInstantDebitMandateViewSnapshotTests.swift */; }; + 31CC9B822CB5F69600E84A38 /* LinkURLGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B762CB5F69600E84A38 /* LinkURLGeneratorTests.swift */; }; + 31CC9B852CB5F69600E84A38 /* LinkBadgeViewSnapshotTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B6D2CB5F69600E84A38 /* LinkBadgeViewSnapshotTest.swift */; }; + 31CC9B972CB5F74A00E84A38 /* LinkNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B882CB5F74A00E84A38 /* LinkNavigationBar.swift */; }; + 31CC9B982CB5F74A00E84A38 /* LinkNoticeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B8A2CB5F74A00E84A38 /* LinkNoticeView.swift */; }; + 31CC9B9A2CB5F74A00E84A38 /* LinkToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B932CB5F74A00E84A38 /* LinkToast.swift */; }; + 31CC9B9C2CB5F74A00E84A38 /* LinkBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9B862CB5F74A00E84A38 /* LinkBadgeView.swift */; }; + 31CC9BA12CB5F93100E84A38 /* Button+Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA02CB5F93100E84A38 /* Button+Link.swift */; }; + 31CC9BA42CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA32CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift */; }; + 31CC9BA52CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA22CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift */; }; 31CDFC362BA8E66200B3DD91 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 31CDFC352BA8E66200B3DD91 /* PrivacyInfo.xcprivacy */; }; 335A19D93A5979557DB4CA4D /* PaymentMethodElementWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5012364ED0F2EEC6EC2AB52 /* PaymentMethodElementWrapper.swift */; }; 34CF08CBC636F596B8BA4C12 /* TextFieldElement+CardTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00C7F5905759525C9BF8BD4 /* TextFieldElement+CardTest.swift */; }; @@ -396,6 +411,21 @@ 31699A822BE183D40048677F /* DownloadManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManagerTest.swift; sourceTree = ""; }; 316B33112B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+StripePaymentSheetTest.swift"; sourceTree = ""; }; 31AD3BE62B0C2D080080C800 /* UIApplication+StripePaymentSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "UIApplication+StripePaymentSheet.swift"; path = "StripePaymentSheet/Source/Categories/UIApplication+StripePaymentSheet.swift"; sourceTree = ""; }; + 31CC9B6C2CB5F69600E84A38 /* ButtonLinkSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonLinkSnapshotTests.swift; sourceTree = ""; }; + 31CC9B6D2CB5F69600E84A38 /* LinkBadgeViewSnapshotTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkBadgeViewSnapshotTest.swift; sourceTree = ""; }; + 31CC9B702CB5F69600E84A38 /* LinkInstantDebitMandateViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkInstantDebitMandateViewSnapshotTests.swift; sourceTree = ""; }; + 31CC9B712CB5F69600E84A38 /* LinkNavigationBarSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNavigationBarSnapshotTests.swift; sourceTree = ""; }; + 31CC9B722CB5F69600E84A38 /* LinkNoticeViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNoticeViewSnapshotTests.swift; sourceTree = ""; }; + 31CC9B742CB5F69600E84A38 /* LinkPopupURLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPopupURLParserTests.swift; sourceTree = ""; }; + 31CC9B752CB5F69600E84A38 /* LinkToastSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkToastSnapshotTests.swift; sourceTree = ""; }; + 31CC9B762CB5F69600E84A38 /* LinkURLGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkURLGeneratorTests.swift; sourceTree = ""; }; + 31CC9B862CB5F74A00E84A38 /* LinkBadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkBadgeView.swift; sourceTree = ""; }; + 31CC9B882CB5F74A00E84A38 /* LinkNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNavigationBar.swift; sourceTree = ""; }; + 31CC9B8A2CB5F74A00E84A38 /* LinkNoticeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNoticeView.swift; sourceTree = ""; }; + 31CC9B932CB5F74A00E84A38 /* LinkToast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkToast.swift; sourceTree = ""; }; + 31CC9BA02CB5F93100E84A38 /* Button+Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Button+Link.swift"; sourceTree = ""; }; + 31CC9BA22CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkInstantDebitMandateView.swift; sourceTree = ""; }; + 31CC9BA32CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkKeyboardAvoidingScrollView.swift; sourceTree = ""; }; 31CDFC352BA8E66200B3DD91 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 32332E0DB0AE12377EBDDEF1 /* PaymentSheetIntentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentSheetIntentConfiguration.swift; sourceTree = ""; }; 32BDC53A88FB17F378C6B413 /* CardSectionWithScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardSectionWithScannerView.swift; sourceTree = ""; }; @@ -768,6 +798,49 @@ path = Services; sourceTree = ""; }; + 31CC9B872CB5F74A00E84A38 /* Badge */ = { + isa = PBXGroup; + children = ( + 31CC9B862CB5F74A00E84A38 /* LinkBadgeView.swift */, + ); + path = Badge; + sourceTree = ""; + }; + 31CC9B892CB5F74A00E84A38 /* NavigationBar */ = { + isa = PBXGroup; + children = ( + 31CC9B882CB5F74A00E84A38 /* LinkNavigationBar.swift */, + ); + path = NavigationBar; + sourceTree = ""; + }; + 31CC9B8B2CB5F74A00E84A38 /* Notice */ = { + isa = PBXGroup; + children = ( + 31CC9B8A2CB5F74A00E84A38 /* LinkNoticeView.swift */, + ); + path = Notice; + sourceTree = ""; + }; + 31CC9B942CB5F74A00E84A38 /* Toast */ = { + isa = PBXGroup; + children = ( + 31CC9B932CB5F74A00E84A38 /* LinkToast.swift */, + ); + path = Toast; + sourceTree = ""; + }; + 31CC9B952CB5F74A00E84A38 /* Components */ = { + isa = PBXGroup; + children = ( + 31CC9B872CB5F74A00E84A38 /* Badge */, + 31CC9B892CB5F74A00E84A38 /* NavigationBar */, + 31CC9B8B2CB5F74A00E84A38 /* Notice */, + 31CC9B942CB5F74A00E84A38 /* Toast */, + ); + path = Components; + sourceTree = ""; + }; 35C0AFFBC393AF76586DAE4A /* Localizations */ = { isa = PBXGroup; children = ( @@ -1028,6 +1101,8 @@ 843180340B5C7406A1117541 /* Views */ = { isa = PBXGroup; children = ( + 31CC9BA22CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift */, + 31CC9BA32CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift */, 13FB3274557B85BA4C9FA6C0 /* LinkLegalTermsView.swift */, E5240ECFD40B8605939C4E09 /* LinkMoreInfoView.swift */, ); @@ -1037,6 +1112,7 @@ 86FB97D65ED6CB44B3E8B66C /* Extensions */ = { isa = PBXGroup; children = ( + 31CC9BA02CB5F93100E84A38 /* Button+Link.swift */, EFDE97D76542848E7821BA43 /* FormElement+Link.swift */, 04C8047FD8994D3FAA3D1A7A /* Intent+Link.swift */, FD0EACE5F259BDE586A4A20C /* STPAnalyticsClient+Link.swift */, @@ -1240,6 +1316,7 @@ isa = PBXGroup; children = ( F8599012936F1A32FC191F06 /* ACH */, + 31CC9B952CB5F74A00E84A38 /* Components */, FD205A472E1B92651A0BB16F /* Controllers */, E46EF43F3DC5F4348B844EE7 /* Elements */, 86FB97D65ED6CB44B3E8B66C /* Extensions */, @@ -1451,6 +1528,14 @@ FCA28FF8CD5BA829A44CDCE7 /* Link */ = { isa = PBXGroup; children = ( + 31CC9B6C2CB5F69600E84A38 /* ButtonLinkSnapshotTests.swift */, + 31CC9B6D2CB5F69600E84A38 /* LinkBadgeViewSnapshotTest.swift */, + 31CC9B702CB5F69600E84A38 /* LinkInstantDebitMandateViewSnapshotTests.swift */, + 31CC9B712CB5F69600E84A38 /* LinkNavigationBarSnapshotTests.swift */, + 31CC9B722CB5F69600E84A38 /* LinkNoticeViewSnapshotTests.swift */, + 31CC9B742CB5F69600E84A38 /* LinkPopupURLParserTests.swift */, + 31CC9B752CB5F69600E84A38 /* LinkToastSnapshotTests.swift */, + 31CC9B762CB5F69600E84A38 /* LinkURLGeneratorTests.swift */, 22E4212F4A865B5AB5D72F99 /* LinkPopupURLParserTests.swift */, 9872CF28C8CA1D2C5499B8C5 /* LinkURLGeneratorTests.swift */, ); @@ -1660,6 +1745,14 @@ B63B2CF12BF8313D003810F3 /* VerticalPaymentMethodListViewControllerTest.swift in Sources */, 61CB0BD02BED985100E24A4C /* VerticalSavedPaymentMethodsViewControllerSnapshotTests.swift in Sources */, 8180BC3615767F896E2F9355 /* AddressViewControllerSnapshotTests.swift in Sources */, + 31CC9B792CB5F69600E84A38 /* LinkNavigationBarSnapshotTests.swift in Sources */, + 31CC9B7D2CB5F69600E84A38 /* ButtonLinkSnapshotTests.swift in Sources */, + 31CC9B7E2CB5F69600E84A38 /* LinkNoticeViewSnapshotTests.swift in Sources */, + 31CC9B7F2CB5F69600E84A38 /* LinkPopupURLParserTests.swift in Sources */, + 31CC9B802CB5F69600E84A38 /* LinkToastSnapshotTests.swift in Sources */, + 31CC9B812CB5F69600E84A38 /* LinkInstantDebitMandateViewSnapshotTests.swift in Sources */, + 31CC9B822CB5F69600E84A38 /* LinkURLGeneratorTests.swift in Sources */, + 31CC9B852CB5F69600E84A38 /* LinkBadgeViewSnapshotTest.swift in Sources */, B65FE7092BED33EA009A73FC /* VerticalPaymentMethodListViewControllerSnapshotTest.swift in Sources */, 37F750E1C99D6257E845A66E /* BacsDDMandateViewSnapshotTests.swift in Sources */, 694A3B36AC19FC1F87EF0CB1 /* CustomerSheetPaymentMethodAvailabilityTests.swift in Sources */, @@ -1732,6 +1825,10 @@ 6A529F76ECB33C9154314C1F /* STPAnalyticsClient+LUXE.swift in Sources */, 06976DDC67A61176FC54AA76 /* Data+SHA256.swift in Sources */, B63B2CF52BFBEEAD003810F3 /* PaymentMethodFormViewController.swift in Sources */, + 31CC9B972CB5F74A00E84A38 /* LinkNavigationBar.swift in Sources */, + 31CC9B982CB5F74A00E84A38 /* LinkNoticeView.swift in Sources */, + 31CC9B9A2CB5F74A00E84A38 /* LinkToast.swift in Sources */, + 31CC9B9C2CB5F74A00E84A38 /* LinkBadgeView.swift in Sources */, 108846A3D8EFD1D4DCC0DDBC /* NSAttributedString+Stripe.swift in Sources */, B55EFA2557B5BE39CC12E357 /* STPPaymentMethod+PaymentSheet.swift in Sources */, 3CB64564D5B6F092A2A3A5BE /* STPPaymentMethodParams+PaymentSheet.swift in Sources */, @@ -1811,6 +1908,8 @@ 9E77F1E9F801AE970F1A5BE1 /* CustomerSheetConfiguration.swift in Sources */, AB8E1556F008083257A99E91 /* CustomerSheetError.swift in Sources */, B67D01B62C46FE9900ED8172 /* CVCReconfirmationVerticalViewController.swift in Sources */, + 31CC9BA42CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift in Sources */, + 31CC9BA52CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift in Sources */, 47B19F96CCEA290541E3B988 /* CardSectionElement.swift in Sources */, 04FEA90F2D0CB9D1C2029D21 /* CardSectionWithScannerView.swift in Sources */, 6BA8D3342B0C1F79008C51FF /* CVCRecollectionElement.swift in Sources */, @@ -1869,6 +1968,7 @@ F4EA474D60D0889E7D48E1CF /* BankAccountInfoView.swift in Sources */, 057A899F4123F3716F2AC0FA /* USBankAccountPaymentMethodElement.swift in Sources */, 985DAA770BC0289D24A5999C /* AddressSearchResult.swift in Sources */, + 31CC9BA12CB5F93100E84A38 /* Button+Link.swift in Sources */, 9DEDA3E0FFF73F9275F5F8F0 /* AutoCompleteViewController.swift in Sources */, A4CD99B2032CBFA7F957B1B8 /* String+AutoComplete.swift in Sources */, 190A1A5A871A82E5B6C09F41 /* BottomSheet3DS2ViewController.swift in Sources */, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Helpers/Images.swift b/StripePaymentSheet/StripePaymentSheet/Source/Helpers/Images.swift index 064e76c144d..6febbdc2516 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Helpers/Images.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Helpers/Images.swift @@ -49,6 +49,8 @@ enum Image: String, CaseIterable, ImageMaker { case icon_chevron_left = "icon_chevron_left" case icon_chevron_right = "icon_chevron_right" case icon_lock = "icon_lock" + case icon_menu = "icon_menu" + case icon_menu_horizontal = "icon_menu_horizontal" case icon_plus = "icon_plus" case icon_x = "icon_x" case icon_x_standalone = "icon_x_standalone" @@ -56,6 +58,11 @@ enum Image: String, CaseIterable, ImageMaker { case icon_edit = "icon_edit" // Link + case back_button = "back_button" + case icon_cancel = "icon_cancel" + case icon_add_bordered = "icon_add_bordered" + case icon_link_success = "icon_link_success" + case icon_link_error = "icon_link_error" case link_logo = "link_logo" case link_logo_bw = "link_logo_bw" case link_logo_knockout = "link_logo_knockout" diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Badge/LinkBadgeView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Badge/LinkBadgeView.swift new file mode 100644 index 00000000000..a2c5bc0e10e --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Badge/LinkBadgeView.swift @@ -0,0 +1,133 @@ +// +// LinkBadgeView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 4/29/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeUICore + +/// For internal SDK use only +@objc(STP_Internal_LinkBadgeView) +final class LinkBadgeView: UIView { + struct Constants { + static let spacing: CGFloat = 4 + static let margins: NSDirectionalEdgeInsets = .insets(top: 2, leading: 4, bottom: 2, trailing: 4) + static let iconSize: CGSize = .init(width: 12, height: 12) + static let maxFontSize: CGFloat = 16 + } + + enum BadgeType { + case neutral + case error + } + + let type: BadgeType + + var text: String? { + get { + return textLabel.text + } + set { + textLabel.text = newValue + } + } + + private lazy var iconView: UIImageView? = { + guard let icon = type.icon else { + return nil + } + + let imageView = UIImageView(image: icon) + imageView.tintColor = type.foregroundColor + imageView.setContentHuggingPriority(.required, for: .horizontal) + imageView.setContentCompressionResistancePriority(.required, for: .horizontal) + imageView.isHidden = imageView.image == nil + + NSLayoutConstraint.activate([ + imageView.widthAnchor.constraint(equalToConstant: Constants.iconSize.width), + imageView.heightAnchor.constraint(equalToConstant: Constants.iconSize.height), + ]) + + return imageView + }() + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.textColor = type.foregroundColor + label.font = LinkUI.font(forTextStyle: .captionEmphasized, maximumPointSize: Constants.maxFontSize) + label.adjustsFontForContentSizeCategory = true + return label + }() + + override var intrinsicContentSize: CGSize { + return CGSize(width: UIView.noIntrinsicMetric, height: 20) + } + + convenience init(type: BadgeType, text: String) { + self.init(type: type) + self.text = text + } + + init(type: BadgeType) { + self.type = type + super.init(frame: .zero) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + setContentHuggingPriority(.required, for: .vertical) + setContentHuggingPriority(.required, for: .horizontal) + + let stackView = UIStackView(arrangedSubviews: [iconView, textLabel].compactMap({ $0 })) + + stackView.axis = .horizontal + stackView.spacing = Constants.spacing + stackView.alignment = .center + stackView.isLayoutMarginsRelativeArrangement = true + stackView.directionalLayoutMargins = Constants.margins + addAndPinSubview(stackView) + + backgroundColor = type.backgroundColor + layer.cornerRadius = LinkUI.smallCornerRadius + } + +} + +private extension LinkBadgeView.BadgeType { + + var icon: UIImage? { + switch self { + case .neutral: + return nil + case .error: + return Image.icon_link_error.makeImage(template: true) + } + } + + var backgroundColor: UIColor { + switch self { + case .neutral: + return .linkNeutralBackground + case .error: + return .linkDangerBackground + } + } + + var foregroundColor: UIColor { + switch self { + case .neutral: + return .linkNeutralForeground + case .error: + return .linkDangerForeground + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift new file mode 100644 index 00000000000..5f3881fbf92 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift @@ -0,0 +1,189 @@ +// +// LinkNavigationBar.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 3/10/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeCore +@_spi(STP) import StripePayments +@_spi(STP) import StripePaymentsUI +@_spi(STP) import StripeUICore + +/// For internal SDK use only +@objc(STP_Internal_LinkNavigationBar) +final class LinkNavigationBar: UIView { + struct Constants { + static let buttonSize: CGSize = .init(width: 60, height: 44) + static let labelMargin: CGFloat = 20 + static let maxFontSize: CGFloat = 18 + static let logoVerticalOffset: CGFloat = 14 + static let defaultHeight: CGFloat = 44 + static let largeHeight: CGFloat = 66 + } + + var linkAccount: PaymentSheetLinkAccountInfoProtocol? { + didSet { + update() + } + } + + var showBackButton: Bool = false { + didSet { + if showBackButton != oldValue { + update() + } + } + } + + var isLarge: Bool { + // The nav bar is considered large as long as we need to display the email label. + return showEmailLabel + } + + private var showEmailLabel: Bool = false { + didSet { + emailLabel.isHidden = !showEmailLabel + invalidateIntrinsicContentSize() + } + } + + let backButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(Image.back_button.makeImage(), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.accessibilityLabel = String.Localized.back + button.isHidden = true + return button + }() + + let closeButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(Image.icon_cancel.makeImage(), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.accessibilityLabel = String.Localized.close + return button + }() + + let menuButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(Image.icon_menu_horizontal.makeImage(), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.accessibilityLabel = String.Localized.show_menu + return button + }() + + private let logoView: UIImageView = { + let imageView = UIImageView(image: Image.link_logo.makeImage(template: true)) + imageView.tintColor = .linkNavLogo + imageView.isAccessibilityElement = true + imageView.accessibilityTraits = .header + imageView.accessibilityLabel = STPPaymentMethodType.link.displayName + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + private let emailLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .body, maximumPointSize: Constants.maxFontSize) + label.textColor = .linkTertiaryText + label.textAlignment = .center + label.lineBreakMode = .byTruncatingMiddle + label.adjustsFontForContentSizeCategory = true + label.translatesAutoresizingMaskIntoConstraints = false + label.isHidden = true + return label + }() + + override var intrinsicContentSize: CGSize { + let baseHeight: CGFloat = isLarge + ? Constants.largeHeight + : Constants.defaultHeight + return CGSize( + width: UIView.noIntrinsicMetric, + height: baseHeight + safeAreaInsets.top + safeAreaInsets.bottom + ) + } + + init() { + super.init(frame: .zero) + + setContentHuggingPriority(.defaultHigh, for: .vertical) + setContentHuggingPriority(.defaultLow, for: .horizontal) + + tintColor = .linkNavTint + backgroundColor = .linkBackground + + addSubview(logoView) + addSubview(emailLabel) + addSubview(backButton) + addSubview(closeButton) + addSubview(menuButton) + + NSLayoutConstraint.activate([ + // Back button + backButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + backButton.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), + backButton.widthAnchor.constraint(equalToConstant: Constants.buttonSize.width), + backButton.heightAnchor.constraint(equalToConstant: Constants.buttonSize.height), + // Close button + closeButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + closeButton.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), + closeButton.widthAnchor.constraint(equalToConstant: Constants.buttonSize.width), + closeButton.heightAnchor.constraint(equalToConstant: Constants.buttonSize.height), + // Logo + logoView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: Constants.logoVerticalOffset), + logoView.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor), + logoView.bottomAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.bottomAnchor), + // Email label + emailLabel.centerXAnchor.constraint(equalTo: safeAreaLayoutGuide.centerXAnchor), + emailLabel.bottomAnchor.constraint(equalTo: bottomAnchor), + emailLabel.leadingAnchor.constraint( + greaterThanOrEqualTo: safeAreaLayoutGuide.leadingAnchor, + constant: Constants.labelMargin + ), + emailLabel.trailingAnchor.constraint( + lessThanOrEqualTo: safeAreaLayoutGuide.trailingAnchor, + constant: Constants.labelMargin + ), + // Menu button + menuButton.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + menuButton.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), + menuButton.widthAnchor.constraint(equalToConstant: Constants.buttonSize.width), + menuButton.heightAnchor.constraint(equalToConstant: Constants.buttonSize.height), + ]) + + update() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func safeAreaInsetsDidChange() { + super.safeAreaInsetsDidChange() + invalidateIntrinsicContentSize() + } + + private func update() { +// TODO(link): Set isLoggedIn once the SDK supports logging in again +// let isLoggedIn = linkAccount?.isLoggedIn ?? false + let isLoggedIn = false + + emailLabel.text = linkAccount?.email + showEmailLabel = isLoggedIn && !showBackButton + + // Back and close button are mutually exclusive. + backButton.isHidden = !showBackButton + closeButton.isHidden = showBackButton + + // Hide the logo if showing the back button. + logoView.isHidden = showBackButton + + // Menu should be hidden if not logged in or we are currently showing the back button. + menuButton.isHidden = !isLoggedIn || showBackButton + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Notice/LinkNoticeView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Notice/LinkNoticeView.swift new file mode 100644 index 00000000000..f73659ec946 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Notice/LinkNoticeView.swift @@ -0,0 +1,113 @@ +// +// LinkNoticeView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 3/30/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeUICore + +/// A view for displaying text notices. +/// +/// For internal SDK use only +@objc(STP_Internal_LinkNoticeView) +final class LinkNoticeView: UIView { + struct Constants { + static let spacing: CGFloat = 10 + static let margins: NSDirectionalEdgeInsets = .insets(amount: 12) + } + + enum NoticeType { + case error + } + + let type: NoticeType + + var text: String? { + get { + return textLabel.text + } + set { + textLabel.text = newValue + } + } + + private lazy var iconView: UIImageView = { + let imageView = UIImageView(image: type.icon) + imageView.tintColor = type.foregroundColor + imageView.adjustsImageSizeForAccessibilityContentSizeCategory = true + imageView.setContentHuggingPriority(.required, for: .horizontal) + imageView.setContentCompressionResistancePriority(.required, for: .horizontal) + return imageView + }() + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.textColor = type.foregroundColor + label.numberOfLines = 0 + label.font = LinkUI.font(forTextStyle: .detail) + label.adjustsFontForContentSizeCategory = true + return label + }() + + convenience init(type: NoticeType, text: String) { + self.init(type: type) + self.text = text + } + + init(type: NoticeType) { + self.type = type + super.init(frame: .zero) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + let stackView = UIStackView(arrangedSubviews: [ + iconView, + textLabel, + ]) + + stackView.axis = .horizontal + stackView.spacing = Constants.spacing + stackView.alignment = .top + stackView.isLayoutMarginsRelativeArrangement = true + stackView.directionalLayoutMargins = Constants.margins + addAndPinSubview(stackView) + + backgroundColor = type.backgroundColor + layer.cornerRadius = LinkUI.mediumCornerRadius + } + +} + +private extension LinkNoticeView.NoticeType { + + var icon: UIImage { + switch self { + case .error: + return Image.icon_link_error.makeImage(template: true) + } + } + + var backgroundColor: UIColor { + switch self { + case .error: + return .linkDangerBackground + } + } + + var foregroundColor: UIColor { + switch self { + case .error: + return .linkDangerForeground + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift new file mode 100644 index 00000000000..3bb072a6432 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift @@ -0,0 +1,99 @@ +// +// LinkPaymentMethodPicker-AddButton.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/20/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore +import UIKit + +extension LinkPaymentMethodPicker { + + final class AddButton: UIControl { + struct Constants { + static let iconSize: CGSize = .init(width: 24, height: 24) + } + + private let iconView: UIImageView = UIImageView(image: Image.icon_add_bordered.makeImage(template: true)) + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.text = String.Localized.add_a_payment_method + label.numberOfLines = 0 + label.textColor = tintColor + label.font = LinkUI.font(forTextStyle: .bodyEmphasized) + label.adjustsFontForContentSizeCategory = true + return label + }() + + override var isHighlighted: Bool { + didSet { + update() + } + } + + init() { + super.init(frame: .zero) + + isAccessibilityElement = true + accessibilityTraits = .button + accessibilityLabel = textLabel.text + directionalLayoutMargins = Cell.Constants.margins + + setupUI() + update() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.point(inside: point, with: event) { + return self + } + + return nil + } + + override func tintColorDidChange() { + super.tintColorDidChange() + self.textLabel.textColor = tintColor + } + + private func setupUI() { + let stackView = UIStackView(arrangedSubviews: [iconView, textLabel]) + stackView.spacing = Cell.Constants.contentSpacing + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + + addSubview(stackView) + + NSLayoutConstraint.activate([ + iconView.widthAnchor.constraint(equalToConstant: Constants.iconSize.width), + iconView.heightAnchor.constraint(equalToConstant: Constants.iconSize.height), + stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), + stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), + stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + ]) + } + + private func update() { + if isHighlighted { + iconView.alpha = 0.7 + textLabel.alpha = 0.7 + backgroundColor = .linkControlHighlight + } else { + iconView.alpha = 1 + textLabel.alpha = 1 + backgroundColor = .clear + } + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift new file mode 100644 index 00000000000..6a2a47fa3bc --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift @@ -0,0 +1,280 @@ +// +// LinkPaymentMethodPicker-Cell.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/19/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore +import UIKit + +protocol LinkPaymentMethodPickerCellDelegate: AnyObject { + func savedPaymentPickerCellDidSelect(_ cell: LinkPaymentMethodPicker.Cell) + func savedPaymentPickerCell(_ cell: LinkPaymentMethodPicker.Cell, didTapMenuButton button: UIButton) +} + +extension LinkPaymentMethodPicker { + + final class Cell: UIControl { + struct Constants { + static let margins = NSDirectionalEdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20) + static let contentSpacing: CGFloat = 12 + static let contentIndentation: CGFloat = 34 + static let menuSpacing: CGFloat = 8 + static let menuButtonSize: CGSize = .init(width: 24, height: 24) + static let separatorHeight: CGFloat = 1 + static let iconViewSize: CGSize = .init(width: 14, height: 20) + static let disabledContentAlpha: CGFloat = 0.5 + } + + override var isHighlighted: Bool { + didSet { + setNeedsLayout() + } + } + + override var isSelected: Bool { + didSet { + setNeedsLayout() + } + } + + var paymentMethod: ConsumerPaymentDetails? { + didSet { + update() + } + } + + var isLoading: Bool = false { + didSet { + if isLoading != oldValue { + update() + } + } + } + + var isSupported: Bool = true { + didSet { + if isSupported != oldValue { + update() + } + } + } + + weak var delegate: LinkPaymentMethodPickerCellDelegate? + + private let radioButton = RadioButton() + + private let contentView = CellContentView() + + private let activityIndicator = ActivityIndicator() + + private let defaultBadge = LinkBadgeView( + type: .neutral, + text: STPLocalizedString("Default", "Label for identifying the default payment method.") + ) + + private let alertIconView: UIImageView = { + let iconView = UIImageView() + iconView.contentMode = .scaleAspectFit + iconView.image = Image.icon_link_error.makeImage(template: true) + iconView.tintColor = .linkDangerForeground + return iconView + }() + + private let unavailableBadge = LinkBadgeView(type: .error, text: STPLocalizedString( + "Unavailable for this purchase", + "Label shown when a payment method cannot be used for the current transaction." + )) + + private lazy var menuButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(Image.icon_menu.makeImage(), for: .normal) + button.addTarget(self, action: #selector(onMenuButtonTapped(_:)), for: .touchUpInside) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + /// The menu button frame for hit-testing purposes. + private var menuButtonFrame: CGRect { + let originalFrame = menuButton.convert(menuButton.bounds, to: self) + + let targetSize = CGSize(width: 44, height: 44) + + return CGRect( + x: originalFrame.midX - (targetSize.width / 2), + y: originalFrame.midY - (targetSize.height / 2), + width: targetSize.width, + height: targetSize.height + ) + } + + private let separator: UIView = { + let separator = UIView() + separator.backgroundColor = .linkControlBorder + separator.translatesAutoresizingMaskIntoConstraints = false + return separator + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + isAccessibilityElement = true + directionalLayoutMargins = Constants.margins + + setupUI() + addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(onCellLongPressed))) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + let rightStackView = UIStackView(arrangedSubviews: [defaultBadge, alertIconView, activityIndicator, menuButton]) + rightStackView.spacing = LinkUI.smallContentSpacing + rightStackView.distribution = .equalSpacing + rightStackView.alignment = .center + + let stackView = UIStackView(arrangedSubviews: [contentView, rightStackView]) + stackView.spacing = Constants.contentSpacing + stackView.distribution = .equalSpacing + stackView.alignment = .center + + let container = UIStackView(arrangedSubviews: [stackView, unavailableBadge]) + container.axis = .vertical + container.spacing = Constants.contentSpacing + container.distribution = .equalSpacing + container.alignment = .leading + container.translatesAutoresizingMaskIntoConstraints = false + addSubview(container) + + radioButton.translatesAutoresizingMaskIntoConstraints = false + addSubview(radioButton) + + addSubview(separator) + + NSLayoutConstraint.activate([ + // Radio button + radioButton.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + radioButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + + // Menu button + menuButton.widthAnchor.constraint(equalToConstant: Constants.menuButtonSize.width), + menuButton.heightAnchor.constraint(equalToConstant: Constants.menuButtonSize.height), + + // Loader + activityIndicator.widthAnchor.constraint(equalToConstant: Constants.menuButtonSize.width), + activityIndicator.heightAnchor.constraint(equalToConstant: Constants.menuButtonSize.height), + + // Icon + alertIconView.widthAnchor.constraint(equalToConstant: Constants.iconViewSize.width), + alertIconView.heightAnchor.constraint(equalToConstant: Constants.iconViewSize.height), + + // Container + container.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), + container.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), + container.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: Constants.contentIndentation), + container.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + // Make stackView fill the container + stackView.trailingAnchor.constraint(equalTo: container.trailingAnchor), + + // Separator + separator.heightAnchor.constraint(equalToConstant: Constants.separatorHeight), + separator.bottomAnchor.constraint(equalTo: bottomAnchor), + separator.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + separator.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + ]) + } + + private func update() { + contentView.paymentMethod = paymentMethod + updateAccessibilityContent() + + guard let paymentMethod = paymentMethod else { + return + } + + var hasExpired: Bool { + switch paymentMethod.details { + case .card(let card): + return card.hasExpired + case .bankAccount: + return false + case .unparsable: + return false + } + } + + defaultBadge.isHidden = isLoading || !paymentMethod.isDefault + alertIconView.isHidden = isLoading || !hasExpired + menuButton.isHidden = isLoading + contentView.alpha = isSupported ? 1 : Constants.disabledContentAlpha + unavailableBadge.isHidden = isSupported + + if isLoading { + activityIndicator.startAnimating() + } else { + activityIndicator.stopAnimating() + } + } + + override func layoutSubviews() { + super.layoutSubviews() + radioButton.isOn = isSelected + backgroundColor = isHighlighted ? .linkControlHighlight : .clear + } + + private func updateAccessibilityContent() { + guard let paymentMethod = paymentMethod else { + return + } + + accessibilityIdentifier = "Stripe.Link.PaymentMethodPickerCell" + accessibilityLabel = paymentMethod.accessibilityDescription + accessibilityCustomActions = [ + UIAccessibilityCustomAction( + name: String.Localized.show_menu, + target: self, + selector: #selector(onShowMenuAction(_:)) + ), + ] + } + + @objc func onShowMenuAction(_ sender: UIAccessibilityCustomAction) { + onMenuButtonTapped(menuButton) + } + + @objc func onMenuButtonTapped(_ sender: UIButton) { + delegate?.savedPaymentPickerCell(self, didTapMenuButton: sender) + } + + @objc func onCellLongPressed() { + delegate?.savedPaymentPickerCell(self, didTapMenuButton: menuButton) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if menuButtonFrame.contains(point) { + return menuButton + } + + return bounds.contains(point) ? self : nil + } + + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + + guard let touchLocation = touches.first?.location(in: self) else { + return + } + + if bounds.contains(touchLocation) { + delegate?.savedPaymentPickerCellDidSelect(self) + } + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift new file mode 100644 index 00000000000..93a36183721 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift @@ -0,0 +1,138 @@ +// +// LinkPaymentMethodPicker-CellContentView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 11/19/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripePaymentsUI +@_spi(STP) import StripeUICore +import UIKit + +extension LinkPaymentMethodPicker { + + final class CellContentView: UIView { + struct Constants { + static let contentSpacing: CGFloat = 12 + static let iconSize: CGSize = CardBrandView.targetIconSize + static let maxFontSize: CGFloat = 20 + } + + var paymentMethod: ConsumerPaymentDetails? { + didSet { + switch paymentMethod?.details { + case .card(_): +// TODO(link): Needs refactor +// case .card(let card): +// cardBrandView.cardBrand = card.stpBrand + bankIconView.isHidden = true + cardBrandView.isHidden = false + primaryLabel.text = paymentMethod?.paymentSheetLabel + secondaryLabel.text = nil + secondaryLabel.isHidden = true + case .bankAccount(let bankAccount): + bankIconView.image = PaymentSheetImageLibrary.bankIcon(for: bankAccount.iconCode) + cardBrandView.isHidden = true + bankIconView.isHidden = false + primaryLabel.text = bankAccount.name + secondaryLabel.text = paymentMethod?.paymentSheetLabel + secondaryLabel.isHidden = false + case .none, .unparsable: + cardBrandView.isHidden = true + bankIconView.isHidden = true + primaryLabel.text = nil + secondaryLabel.text = nil + secondaryLabel.isHidden = true + } + } + } + + private lazy var bankIconView: UIImageView = { + let iconView = UIImageView() + iconView.contentMode = .scaleAspectFit + return iconView + }() + + private lazy var cardBrandView: CardBrandView = CardBrandView(centerHorizontally: true) + + private let primaryLabel: UILabel = { + let label = UILabel() + label.adjustsFontForContentSizeCategory = true + label.font = LinkUI.font(forTextStyle: .bodyEmphasized, maximumPointSize: Constants.maxFontSize) + label.textColor = .linkPrimaryText + return label + }() + + private let secondaryLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .caption, maximumPointSize: Constants.maxFontSize) + label.textColor = .linkSecondaryText + return label + }() + + private lazy var iconContainerView: UIView = { + let view = UIView() + bankIconView.translatesAutoresizingMaskIntoConstraints = false + cardBrandView.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(bankIconView) + view.addSubview(cardBrandView) + + let cardBrandSize = cardBrandView.size(for: Constants.iconSize) + NSLayoutConstraint.activate([ + view.widthAnchor.constraint(equalToConstant: max(Constants.iconSize.width, cardBrandSize.width)), + view.heightAnchor.constraint(equalToConstant: max(Constants.iconSize.height, cardBrandSize.height)), + + bankIconView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor), + bankIconView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor), + bankIconView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor), + bankIconView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor), + bankIconView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + bankIconView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + + cardBrandView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor), + cardBrandView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor), + cardBrandView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor), + cardBrandView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor), + cardBrandView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + cardBrandView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + + cardBrandView.widthAnchor.constraint(equalToConstant: cardBrandSize.width), + cardBrandView.heightAnchor.constraint(equalToConstant: cardBrandSize.height), + ]) + + return view + }() + + private lazy var stackView: UIStackView = { + let labelStackView = UIStackView(arrangedSubviews: [ + primaryLabel, + secondaryLabel, + ]) + labelStackView.axis = .vertical + labelStackView.alignment = .leading + labelStackView.spacing = 0 + + let stackView = UIStackView(arrangedSubviews: [ + iconContainerView, + labelStackView, + ]) + + stackView.spacing = Constants.contentSpacing + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + addAndPinSubview(stackView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift new file mode 100644 index 00000000000..3064dd16451 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift @@ -0,0 +1,194 @@ +// +// LinkPaymentMethodPicker-Header.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/22/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeUICore +import UIKit + +extension LinkPaymentMethodPicker { + + final class Header: UIControl { + struct Constants { + static let contentSpacing: CGFloat = 16 + static let chevronSize: CGSize = .init(width: 24, height: 24) + static let collapsedInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) + static let expandedInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 4, trailing: 20) + } + + /// The selected payment method. + var selectedPaymentMethod: ConsumerPaymentDetails? { + didSet { + contentView.paymentMethod = selectedPaymentMethod + updateAccessibilityContent() + } + } + + var isExpanded: Bool = false { + didSet { + setNeedsLayout() + updateChevron() + updateAccessibilityContent() + } + } + + override var isHighlighted: Bool { + didSet { + if isHighlighted && !isExpanded { + backgroundColor = .linkControlHighlight + } else { + backgroundColor = .clear + } + } + } + + private let payWithLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .body) + label.textColor = .linkSecondaryText + label.text = STPLocalizedString("Payment", "Label for a section displaying payment details.") + label.adjustsFontForContentSizeCategory = true + return label + }() + + private let headingLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .bodyEmphasized) + label.textColor = .linkPrimaryText + label.text = STPLocalizedString( + "Payment methods", + "Title for a section listing one or more payment methods." + ) + label.adjustsFontForContentSizeCategory = true + return label + }() + + private let contentView = CellContentView() + + private let cardNumberLabel: UILabel = { + let label = UILabel() + label.font = UIFont.monospacedDigitSystemFont(ofSize: 14, weight: .medium) + .scaled(withTextStyle: .body, maximumPointSize: 20) + return label + }() + + private lazy var chevron: UIImageView = { + let chevron = UIImageView(image: StripeUICore.Image.icon_chevron_down.makeImage(template: true)) + chevron.contentMode = .center + + NSLayoutConstraint.activate([ + chevron.widthAnchor.constraint(equalToConstant: Constants.chevronSize.width), + chevron.heightAnchor.constraint(equalToConstant: Constants.chevronSize.height), + ]) + + return chevron + }() + + private lazy var paymentInfoStackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + payWithLabel, + contentView, + ]) + + stackView.alignment = .center + stackView.setCustomSpacing(Constants.contentSpacing, after: payWithLabel) + stackView.translatesAutoresizingMaskIntoConstraints = false + + return stackView + }() + + private lazy var stackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + paymentInfoStackView, + headingLabel, + chevron, + ]) + + stackView.axis = .horizontal + stackView.spacing = Constants.contentSpacing + stackView.distribution = .equalSpacing + stackView.alignment = .center + stackView.isLayoutMarginsRelativeArrangement = true + stackView.translatesAutoresizingMaskIntoConstraints = false + + return stackView + }() + + override init(frame: CGRect) { + super.init(frame: .zero) + + addSubview(stackView) + + NSLayoutConstraint.activate([ + // Stack view + stackView.topAnchor.constraint(equalTo: topAnchor), + stackView.bottomAnchor.constraint(equalTo: bottomAnchor), + stackView.leadingAnchor.constraint(equalTo: leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: trailingAnchor), + ]) + + isAccessibilityElement = true + accessibilityTraits = .button + + updateChevron() + updateAccessibilityContent() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func updateChevron() { + if isExpanded { + chevron.transform = CGAffineTransform(rotationAngle: .pi) + chevron.tintColor = .linkPrimaryText + } else { + chevron.transform = .identity + chevron.tintColor = .linkSecondaryText + } + } + + private func updateAccessibilityContent() { + if isExpanded { + accessibilityLabel = headingLabel.text + accessibilityHint = STPLocalizedString( + "Tap to close", + "Accessibility hint to tell the user that they can tap to hide additional content." + ) + } else { + accessibilityLabel = selectedPaymentMethod?.accessibilityDescription + accessibilityHint = STPLocalizedString( + "Tap to expand", + "Accessibility hint to tell the user that they can tap to reveal additional content." + ) + } + } + + override func layoutSubviews() { + super.layoutSubviews() + + if isExpanded { + paymentInfoStackView.isHidden = true + headingLabel.isHidden = false + stackView.directionalLayoutMargins = Constants.expandedInsets + } else { + paymentInfoStackView.isHidden = false + headingLabel.isHidden = true + stackView.directionalLayoutMargins = Constants.collapsedInsets + } + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.point(inside: point, with: event) { + return self + } + + return nil + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift new file mode 100644 index 00000000000..6ba74090c09 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift @@ -0,0 +1,114 @@ +// +// LinkPaymentMethodPicker-RadioButton.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 11/15/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +extension LinkPaymentMethodPicker { + + final class RadioButton: UIView { + struct Constants { + static let diameter: CGFloat = 20 + static let innerDiameter: CGFloat = 8 + static let borderWidth: CGFloat = 1 + } + + public var isOn: Bool = false { + didSet { + update() + } + } + + public var borderColor: UIColor = .linkControlBorder { + didSet { + applyStyling() + } + } + + /// Layer for the "off" state. + private let offLayer: CALayer = { + let layer = CALayer() + layer.bounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter) + layer.cornerRadius = Constants.diameter / 2 + layer.borderWidth = Constants.borderWidth + layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + return layer + }() + + /// Layer for the "on" state. + private let onLayer: CALayer = { + let layer = CALayer() + layer.bounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter) + layer.cornerRadius = Constants.diameter / 2 + layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + + let innerCircle = CALayer() + innerCircle.backgroundColor = UIColor.white.cgColor + innerCircle.cornerRadius = Constants.innerDiameter / 2 + innerCircle.bounds = CGRect(x: 0, y: 0, width: Constants.innerDiameter, height: Constants.innerDiameter) + innerCircle.anchorPoint = CGPoint(x: 0.5, y: 0.5) + + // Add and center inner circle + layer.addSublayer(innerCircle) + innerCircle.position = CGPoint(x: layer.bounds.midX, y: layer.bounds.midY) + + return layer + }() + + override var intrinsicContentSize: CGSize { + return CGSize(width: Constants.diameter, height: Constants.diameter) + } + + init() { + super.init(frame: .zero) + layer.addSublayer(offLayer) + layer.addSublayer(onLayer) + update() + applyStyling() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + applyStyling() + } + + override func layoutSubviews() { + offLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) + onLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) + } + + override func tintColorDidChange() { + super.tintColorDidChange() + applyStyling() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + applyStyling() + } + + // MARK: - Private methods + + private func update() { + CATransaction.begin() + CATransaction.setDisableActions(true) + offLayer.isHidden = isOn + onLayer.isHidden = !isOn + CATransaction.commit() + } + + private func applyStyling() { + CATransaction.begin() + CATransaction.setDisableActions(true) + offLayer.borderColor = borderColor.cgColor + onLayer.backgroundColor = tintColor.cgColor + CATransaction.commit() + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift new file mode 100644 index 00000000000..1ae6860ba1b --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift @@ -0,0 +1,312 @@ +// +// LinkPaymentMethodPicker.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/25/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeUICore + +protocol LinkPaymentMethodPickerDelegate: AnyObject { + func paymentMethodPickerDidChange(_ picker: LinkPaymentMethodPicker) + + func paymentMethodPicker( + _ picker: LinkPaymentMethodPicker, + showMenuForItemAt index: Int, + sourceRect: CGRect + ) + + func paymentDetailsPickerDidTapOnAddPayment(_ picker: LinkPaymentMethodPicker) +} + +protocol LinkPaymentMethodPickerDataSource: AnyObject { + + /// Returns the total number of payment methods. + /// - Returns: Payment method count + func numberOfPaymentMethods(in picker: LinkPaymentMethodPicker) -> Int + + /// Returns the payment method at the specific index. + /// - Returns: Payment method. + func paymentPicker( + _ picker: LinkPaymentMethodPicker, + paymentMethodAt index: Int + ) -> ConsumerPaymentDetails + +} + +/// For internal SDK use only +@objc(STP_Internal_LinkPaymentMethodPicker) +final class LinkPaymentMethodPicker: UIView { + weak var delegate: LinkPaymentMethodPickerDelegate? + weak var dataSource: LinkPaymentMethodPickerDataSource? + + var selectedIndex: Int = 0 { + didSet { + updateHeaderView() + } + } + + var supportedPaymentMethodTypes = Set(ConsumerPaymentDetails.DetailsType.allCases) + + var selectedPaymentMethod: ConsumerPaymentDetails? { + let count = dataSource?.numberOfPaymentMethods(in: self) ?? 0 + + guard selectedIndex >= 0 && selectedIndex < count else { + return nil + } + + return dataSource?.paymentPicker(self, paymentMethodAt: selectedIndex) + } + + private var needsDataReload: Bool = true + + private lazy var stackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + headerView, + listView, + ]) + + stackView.axis = .vertical + stackView.clipsToBounds = true + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private let headerView = Header() + + private lazy var listView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + addPaymentMethodButton + ]) + + stackView.axis = .vertical + stackView.distribution = .equalSpacing + stackView.clipsToBounds = true + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .medium) + private let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + + private let addPaymentMethodButton = AddButton() + + override init(frame: CGRect) { + super.init(frame: .zero) + addAndPinSubview(stackView) + setup() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup() { + clipsToBounds = true + accessibilityIdentifier = "Stripe.Link.PaymentMethodPicker" + + layer.cornerRadius = 16 + layer.borderWidth = 1 + layer.borderColor = UIColor.linkControlBorder.cgColor + tintColor = .linkBrandDark + backgroundColor = .linkControlBackground + + headerView.addTarget(self, action: #selector(onHeaderTapped(_:)), for: .touchUpInside) + headerView.layer.zPosition = 1 + + listView.isHidden = true + listView.layer.zPosition = 0 + + addPaymentMethodButton.addTarget(self, action: #selector(onAddPaymentButtonTapped(_:)), for: .touchUpInside) + } + + override func layoutSubviews() { + super.layoutSubviews() + reloadDataIfNeeded() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + layer.borderColor = UIColor.linkControlBorder.cgColor + } + + func setExpanded(_ expanded: Bool, animated: Bool) { + headerView.isExpanded = expanded + + // Prevent double header animation + if headerView.isExpanded { + // TODO(ramont): revise layout margin placement and remove conditional + setNeedsLayout() + layoutIfNeeded() + } else { + headerView.layoutIfNeeded() + } + + if headerView.isExpanded { + stackView.showArrangedSubview(at: 1, animated: animated) + } else { + stackView.hideArrangedSubview(at: 1, animated: animated) + } + } + + private func updateHeaderView() { + headerView.selectedPaymentMethod = selectedPaymentMethod + } + +} + +private extension LinkPaymentMethodPicker { + + @objc func onHeaderTapped(_ sender: Header) { + setExpanded(!sender.isExpanded, animated: true) + impactFeedbackGenerator.impactOccurred() + } + + @objc func onAddPaymentButtonTapped(_ sender: AddButton) { + delegate?.paymentDetailsPickerDidTapOnAddPayment(self) + } + +} + +// MARK: - Data Loading + +extension LinkPaymentMethodPicker { + + func reloadData() { + needsDataReload = false + + addMissingPaymentMethodCells() + + let count = dataSource?.numberOfPaymentMethods(in: self) ?? 0 + if count == 0 { + headerView.isHidden = true + listView.isHidden = false + } + + for index in 0.. listView.arrangedSubviews.count - 1 { + let cell = Cell() + cell.delegate = self + + let index = listView.arrangedSubviews.count - 1 + listView.insertArrangedSubview(cell, at: index) + } + + for (index, subview) in listView.arrangedSubviews.enumerated() { + subview.layer.zPosition = CGFloat(-index) + } + + headerView.selectedPaymentMethod = selectedPaymentMethod + } + +} + +extension LinkPaymentMethodPicker { + + func index(for cell: Cell) -> Int? { + return listView.arrangedSubviews.firstIndex(of: cell) + } + + func removePaymentMethod(at index: Int, animated: Bool) { + isUserInteractionEnabled = false + + listView.removeArrangedSubview(at: index, animated: true) { + let count = self.dataSource?.numberOfPaymentMethods(in: self) ?? 0 + + if index < self.selectedIndex { + self.selectedIndex = max(self.selectedIndex - 1, 0) + } + + self.selectedIndex = max(min(self.selectedIndex, count - 1), 0) + + self.reloadData() + self.delegate?.paymentMethodPickerDidChange(self) + self.isUserInteractionEnabled = true + } + } + +} + +// MARK: - Cell delegate + +extension LinkPaymentMethodPicker: LinkPaymentMethodPickerCellDelegate { + + func savedPaymentPickerCellDidSelect(_ savedCardView: Cell) { + if let newIndex = index(for: savedCardView) { + let oldIndex = selectedIndex + selectedIndex = newIndex + + reloadCell(at: oldIndex) + reloadCell(at: newIndex) + + selectionFeedbackGenerator.selectionChanged() + + delegate?.paymentMethodPickerDidChange(self) + } + } + + func savedPaymentPickerCell(_ cell: Cell, didTapMenuButton button: UIButton) { + guard let index = index(for: cell) else { + assertionFailure("Index not found") + return + } + + let sourceRect = button.convert(button.bounds, to: self) + + delegate?.paymentMethodPicker(self, showMenuForItemAt: index, sourceRect: sourceRect) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift new file mode 100644 index 00000000000..791d9c07ea8 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift @@ -0,0 +1,182 @@ +// +// LinkToast.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 11/23/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore + +/// A view for displaying a brief message to the user. +/// For internal SDK use only +@objc(STP_Internal_LinkToast) +final class LinkToast: UIView { + struct Constants { + static let padding: CGFloat = 12 + /// Space between the icon and label. + static let spacing: CGFloat = 8 + static let animationDuration: TimeInterval = 0.2 + static let animationTravelDistance: CGFloat = 40 + static let defaultDuration: TimeInterval = 2 + } + + enum ToastType { + case success + } + + let toastType: ToastType + + let text: String + + private let iconView = UIImageView() + + private let label: UILabel = { + let label = UILabel() + label.textColor = .linkToastForeground + label.font = LinkUI.font(forTextStyle: .detail, maximumPointSize: 20) + return label + }() + + private let feedbackGenerator = UINotificationFeedbackGenerator() + + /// Creates a new toast. + /// - Parameters: + /// - type: Toast type. + /// - text: Text to show. + init(type: ToastType, text: String) { + self.toastType = type + self.text = text + super.init(frame: .zero) + setup() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup() { + backgroundColor = .linkToastBackground + directionalLayoutMargins = .insets(amount: Constants.padding) + + insetsLayoutMarginsFromSafeArea = false + + label.text = text + iconView.image = toastType.icon + iconView.tintColor = toastType.iconColor + + let stackView = UIStackView(arrangedSubviews: [iconView, label]) + stackView.spacing = Constants.spacing + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + + addSubview(stackView) + + NSLayoutConstraint.activate([ + stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), + stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), + stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + ]) + } + + override func layoutSubviews() { + super.layoutSubviews() + layer.cornerRadius = bounds.height / 2 + } + +} + +// MARK: - Show/Hide + +extension LinkToast { + + /// Show the toast from the given view as context. + /// - Parameters: + /// - view: View to show the toast from. + /// - duration: How long to show the toast for. + func show(from view: UIView, duration: TimeInterval = Constants.defaultDuration) { + let presentingView = view.window ?? view + + translatesAutoresizingMaskIntoConstraints = false + presentingView.addSubview(self) + + NSLayoutConstraint.activate([ + // Horizontally center + centerXAnchor.constraint(equalTo: presentingView.safeAreaLayoutGuide.centerXAnchor), + + // Pin edges + topAnchor.constraint(equalTo: presentingView.safeAreaLayoutGuide.topAnchor), + leadingAnchor.constraint(greaterThanOrEqualTo: presentingView.layoutMarginsGuide.leadingAnchor), + trailingAnchor.constraint(lessThanOrEqualTo: presentingView.layoutMarginsGuide.trailingAnchor), + ]) + + alpha = 0 + transform = CGAffineTransform(translationX: 0, y: -Constants.animationTravelDistance) + + UIView.animate( + withDuration: Constants.animationDuration, + delay: 0, + options: .curveEaseOut + ) { + self.alpha = 1 + self.transform = .identity + } + + UIAccessibility.post(notification: .announcement, argument: text) + generateHapticFeedback() + + DispatchQueue.main.asyncAfter(deadline: .now() + duration) { + self.hide() + } + } + + /// Hides toast. + /// + /// You normally don't need to call this, as the toast will hide on its own after an specific duration. + func hide() { + guard superview != nil else { + return + } + + UIView.animate( + withDuration: Constants.animationDuration, + delay: 0, + options: .curveEaseOut + ) { + self.alpha = 0 + self.transform = CGAffineTransform(translationX: 0, y: -Constants.animationTravelDistance) + } completion: { _ in + self.removeFromSuperview() + } + } + + private func generateHapticFeedback() { + switch toastType { + case .success: + feedbackGenerator.notificationOccurred(.success) + } + } + +} + +extension LinkToast.ToastType { + + var icon: UIImage { + switch self { + case .success: + return Image.icon_link_success.makeImage(template: true) + } + } + + var iconColor: UIColor { + switch self { + case .success: + return .linkBrand + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift index 8c8a3b55dd6..23afcd1f6e5 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift @@ -20,6 +20,17 @@ extension UIColor { static var linkBrand: UIColor { UIColor(red: 0, green: 0.84, blue: 0.44, alpha: 1.0) } + + /// Darker version of the brand color. + /// + /// Use it as accent color on small UI elements or text links. + static let linkBrandDark: UIColor = UIColor(red: 0.020, green: 0.659, blue: 0.498, alpha: 1.0) + + /// Main background color. + static let linkBackground: UIColor = .dynamic( + light: .white, + dark: UIColor(red: 0.11, green: 0.11, blue: 0.118, alpha: 1) + ) /// Level 400 variant of Link brand color. /// @@ -34,11 +45,88 @@ extension UIColor { dark: .white ) + /// Tint color of the nav. Affects the color of nav buttons. + static let linkNavTint: UIColor = .dynamic( + light: UIColor(red: 0.188, green: 0.192, blue: 0.239, alpha: 1.0), + dark: UIColor(red: 0.922, green: 0.922, blue: 0.961, alpha: 0.6) + ) + + /// Color for borders and dividers. + static let linkSeparator: UIColor = .dynamic( + light: UIColor(red: 0.878, green: 0.902, blue: 0.922, alpha: 1), + dark: UIColor(red: 0.471, green: 0.471, blue: 0.502, alpha: 0.36) + ) + + /// Border color for custom controls. Currently an alias of `linkSeparator`. + static let linkControlBorder: UIColor = .linkSeparator + + /// Background color for custom controls. + static let linkControlBackground: UIColor = .dynamic( + light: .white, + dark: UIColor(red: 0.17, green: 0.17, blue: 0.19, alpha: 1) + ) + + /// Background color to be used when a custom control is highlighted. + static let linkControlHighlight: UIColor = .dynamic( + light: UIColor(red: 0.95, green: 0.95, blue: 0.96, alpha: 1), + dark: UIColor(white: 1, alpha: 0.07) + ) + + /// A very subtle color to be used on placeholder content of a control. + /// + /// - Note: Only recommended for shapes/non-text content due to very low contrast ratio with `linkControlBackground`. + static let linkControlLightPlaceholder: UIColor = .dynamic( + light: UIColor(red: 0.922, green: 0.933, blue: 0.945, alpha: 1.0), + dark: UIColor(red: 0.471, green: 0.471, blue: 0.502, alpha: 0.36) + ) + + /// Background color of the toast component. + static let linkToastBackground: UIColor = UIColor(red: 0.19, green: 0.19, blue: 0.24, alpha: 1.0) + + /// Foreground color of the toast component. + static let linkToastForeground: UIColor = .white + /// Foreground color of the primary button. static var linkPrimaryButtonForeground: UIColor { UIColor(red: 0, green: 0.12, blue: 0.06, alpha: 1.0) } + + + /// Foreground color of the secondary button. + static let linkSecondaryButtonForeground: UIColor = .dynamic( + light: UIColor(red: 0.114, green: 0.224, blue: 0.267, alpha: 1.0), + dark: UIColor(red: 0.020, green: 0.659, blue: 0.498, alpha: 1.0) + ) + + /// Background color of the secondary button/ + static let linkSecondaryButtonBackground: UIColor = .dynamic( + light: UIColor(red: 0.965, green: 0.973, blue: 0.980, alpha: 1.0), + dark: UIColor(red: 0.455, green: 0.455, blue: 0.502, alpha: 0.18) + ) + /// Background color of a neutral badge or notice. + static let linkNeutralBackground: UIColor = .dynamic( + light: UIColor(red: 0.96, green: 0.97, blue: 0.98, alpha: 1.0), + dark: UIColor(white: 1, alpha: 0.1) + ) + + /// Foreground color of a neutral badge or notice. + static let linkNeutralForeground: UIColor = .dynamic( + light: UIColor(red: 0.416, green: 0.451, blue: 0.514, alpha: 1), + dark: UIColor(red: 0.922, green: 0.922, blue: 0.961, alpha: 0.6) + ) + + /// Background color of an error badge or notice. + static let linkDangerBackground: UIColor = .dynamic( + light: UIColor(red: 1.0, green: 0.906, blue: 0.949, alpha: 1.0), + dark: UIColor(red: 0.996, green: 0.529, blue: 0.631, alpha: 0.1) + ) + + /// Foreground color of an error badge or notice. + static let linkDangerForeground: UIColor = .dynamic( + light: UIColor(red: 1.0, green: 0.184, blue: 0.298, alpha: 1.0), + dark: UIColor(red: 1.0, green: 0.184, blue: 0.298, alpha: 1.0) + ) } // MARK: - Text color diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift new file mode 100644 index 00000000000..3d8c5f91f08 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift @@ -0,0 +1,119 @@ +// +// LinkInstantDebitMandateView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 2/17/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripePaymentsUI +@_spi(STP) import StripeUICore +import UIKit + +protocol LinkInstantDebitMandateViewDelegate: AnyObject { + /// Called when the user taps on a link. + /// + /// - Parameters: + /// - mandateView: The view that the user interacted with. + /// - url: URL of the link. + func instantDebitMandateView(_ mandateView: LinkInstantDebitMandateView, didTapOnLinkWithURL url: URL) +} + +// TODO(ramont): extract common code with `LinkLegalTermsView`. + +/// For internal SDK use only +@objc(STP_Internal_LinkInstantDebitMandateViewDelegate) +final class LinkInstantDebitMandateView: UIView { + struct Constants { + static let lineHeight: CGFloat = 1.5 + } + + // TODO(ramont): Update with final URLs + private let links: [String: URL] = [ + "terms": URL(string: "https://stripe.com/ach-payments/authorization")! + ] + + weak var delegate: LinkInstantDebitMandateViewDelegate? + + private lazy var textView: UITextView = { + let textView = UITextView() + textView.isScrollEnabled = false + textView.isEditable = false + textView.backgroundColor = .clear + textView.attributedText = formattedLegalText() + textView.textColor = .linkSecondaryText + textView.textAlignment = .center + textView.textContainerInset = .zero + textView.textContainer.lineFragmentPadding = 0 + textView.delegate = self + textView.clipsToBounds = false + textView.adjustsFontForContentSizeCategory = true + textView.linkTextAttributes = [ + .foregroundColor: UIColor.linkBrandDark + ] + textView.font = LinkUI.font(forTextStyle: .caption) + return textView + }() + + init(delegate: LinkInstantDebitMandateViewDelegate? = nil) { + super.init(frame: .zero) + self.delegate = delegate + addAndPinSubview(textView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func formattedLegalText() -> NSAttributedString { + let string = STPLocalizedString( + "By continuing, you agree to authorize payments pursuant to these terms.", + "Mandate text displayed when paying via Link instant debit." + ) + + let formattedString = NSMutableAttributedString() + + STPStringUtils.parseRanges(from: string, withTags: Set(links.keys)) { string, matches in + formattedString.append(NSAttributedString(string: string)) + + for (tag, range) in matches { + guard range.rangeValue.location != NSNotFound else { + assertionFailure("Tag '<\(tag)>' not found") + continue + } + + if let url = links[tag] { + formattedString.addAttributes([.link: url], range: range.rangeValue) + } + } + } + + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineSpacing = LinkUI.lineSpacing( + fromRelativeHeight: Constants.lineHeight, + textStyle: .caption + ) + + formattedString.addAttributes([.paragraphStyle: paragraphStyle], range: formattedString.extent) + + return formattedString + } + +} + +extension LinkInstantDebitMandateView: UITextViewDelegate { + + func textView( + _ textView: UITextView, + shouldInteractWith URL: URL, + in characterRange: NSRange, + interaction: UITextItemInteraction + ) -> Bool { + if interaction == .invokeDefaultAction { + delegate?.instantDebitMandateView(self, didTapOnLinkWithURL: URL) + } + + return false + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkKeyboardAvoidingScrollView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkKeyboardAvoidingScrollView.swift new file mode 100644 index 00000000000..ba793bacfd3 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkKeyboardAvoidingScrollView.swift @@ -0,0 +1,75 @@ +// +// LinkKeyboardAvoidingScrollView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 1/11/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeUICore +import UIKit + +/// A UIScrollView subclass that actively prevents its content from being covered by the software keyboard. +/// For internal SDK use only +@objc(STP_Internal_LinkKeyboardAvoidingScrollView) +final class LinkKeyboardAvoidingScrollView: UIScrollView { + + init() { + super.init(frame: .zero) + + NotificationCenter.default.addObserver(self, + selector: #selector(keyboardFrameChanged(_:)), + name: UIResponder.keyboardWillChangeFrameNotification, + object: nil) + } + + /// Creates a new keyboard-avoiding scrollview with the given view configured as content view. + /// + /// This initializer adds the content view as a subview and installs the appropriate set of constraints. + /// + /// - Parameter contentView: The view to be used as content view. + convenience init(contentView: UIView) { + self.init() + + contentView.translatesAutoresizingMaskIntoConstraints = false + addSubview(contentView) + + NSLayoutConstraint.activate([ + contentView.topAnchor.constraint(equalTo: topAnchor), + contentView.bottomAnchor.constraint(equalTo: bottomAnchor), + contentView.leadingAnchor.constraint(equalTo: leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: trailingAnchor), + contentView.widthAnchor.constraint(equalTo: widthAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + NotificationCenter.default.removeObserver(self) + } +} + +// MARK: - Event Handling + +private extension LinkKeyboardAvoidingScrollView { + + @objc func keyboardFrameChanged(_ notification: Notification) { + let userInfo = notification.userInfo + + guard let keyboardFrame = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { + return + } + + let absoluteFrame = convert(bounds, to: window) + let intersection = absoluteFrame.intersection(keyboardFrame) + + UIView.animateAlongsideKeyboard(notification) { + self.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: intersection.height, right: 0) + self.scrollIndicatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: intersection.height, right: 0) + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift index 0b59fe4e1b1..5c12a600039 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift @@ -15,7 +15,7 @@ import UIKit @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripeUICore -class ButtonLinkSnapshotTests: FBSnapshotTestCase { +class ButtonLinkSnapshotTests: STPSnapshotTestCase { override func setUp() { super.setUp() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift index d5f9d717492..27fd83a3fcf 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift @@ -8,6 +8,7 @@ import iOSSnapshotTestCase import UIKit +import StripeCoreTestUtils @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -15,7 +16,7 @@ import UIKit @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripePaymentsUI -class LinkBadgeViewSnapshotTest: FBSnapshotTestCase { +class LinkBadgeViewSnapshotTest: STPSnapshotTestCase { override func setUp() { super.setUp() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift deleted file mode 100644 index c80772cf42f..00000000000 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// LinkCardEditElementSnapshotTests.swift -// StripeiOS Tests -// -// Created by Ramon Torres on 10/3/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import UIKit - -@testable import Stripe -@testable@_spi(STP) import StripeCoreTestUtils -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripeUICore - -final class LinkCardEditElementSnapshotTests: FBSnapshotTestCase { - - override func setUp() { - super.setUp() - // self.recordMode = true - - // `LinkCardEditElement` depends on `AddressSectionElement`, which requires - // address specs to be loaded in memory. - let expectation = expectation(description: "Load address specs") - AddressSpecProvider.shared.loadAddressSpecs { - expectation.fulfill() - } - - wait(for: [expectation], timeout: STPTestingNetworkRequestTimeout) - } - - func testDefault() { - let sut = makeSUT(isDefault: true) - verify(sut) - } - - func testNonDefault() { - let sut = makeSUT(isDefault: false) - verify(sut) - } - - func verify( - _ element: LinkCardEditElement, - identifier: String? = nil, - file: StaticString = #filePath, - line: UInt = #line - ) { - element.view.autosizeHeight(width: 340) - STPSnapshotVerifyView(element.view, identifier: identifier, file: file, line: line) - } - -} - -extension LinkCardEditElementSnapshotTests { - - func makeSUT(isDefault: Bool) -> LinkCardEditElement { - let paymentMethod = ConsumerPaymentDetails( - stripeID: "1", - details: .card( - card: .init( - expiryYear: 2032, - expiryMonth: 1, - brand: "visa", - last4: "4242", - checks: nil - ) - ), - isDefault: isDefault - ) - - return LinkCardEditElement(paymentMethod: paymentMethod, configuration: .init()) - } - -} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift deleted file mode 100644 index 0d9e04bcd01..00000000000 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInlineSignupElementSnapshotTests.swift +++ /dev/null @@ -1,123 +0,0 @@ -// -// LinkInlineSignupElementSnapshotTests.swift -// StripeiOS Tests -// -// Created by Ramon Torres on 1/21/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -@_spi(STP) import StripeCoreTestUtils -@_spi(STP) import StripeUICore -import UIKit - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class LinkInlineSignupElementSnapshotTests: FBSnapshotTestCase { - - override func setUp() { - super.setUp() - // recordMode = true - } - - func testDefaultState() { - let sut = makeSUT() - verify(sut) - } - - func testExpandedState() { - let sut = makeSUT(saveCheckboxChecked: true, emailAddress: "user@example.com") - verify(sut) - } - - func testExpandedState_nonUS() { - let sut = makeSUT( - saveCheckboxChecked: true, - emailAddress: "user@example.com", - country: "CA" - ) - verify(sut) - } - - func testExpandedState_nonUS_preFilled() { - let sut = makeSUT( - saveCheckboxChecked: true, - emailAddress: "user@example.com", - country: "CA", - preFillName: "Jane Diaz", - preFillPhone: "+13105551234" - ) - verify(sut) - } - - func verify( - _ element: LinkInlineSignupElement, - identifier: String? = nil, - file: StaticString = #filePath, - line: UInt = #line - ) { - element.view.autosizeHeight(width: 340) - STPSnapshotVerifyView(element.view, identifier: identifier, file: file, line: line) - } - -} - -extension LinkInlineSignupElementSnapshotTests { - - struct MockAccountService: LinkAccountServiceProtocol { - func lookupAccount( - withEmail email: String?, - completion: @escaping (Result) -> Void - ) { - completion( - .success( - PaymentSheetLinkAccount( - email: "user@example.com", - session: nil, - publishableKey: nil - ) - ) - ) - } - - func hasEmailLoggedOut(email: String) -> Bool { - // TODO(porter): Determine if we want to implement this in tests - return false - } - } - - func makeSUT( - saveCheckboxChecked: Bool = false, - emailAddress: String? = nil, - country: String = "US", - preFillName: String? = nil, - preFillPhone: String? = nil - ) -> LinkInlineSignupElement { - var configuration = PaymentSheet.Configuration() - configuration.merchantDisplayName = "[Merchant]" - configuration.defaultBillingDetails.name = preFillName - configuration.defaultBillingDetails.phone = preFillPhone - - let viewModel = LinkInlineSignupViewModel( - configuration: configuration, - accountService: MockAccountService(), - country: country - ) - - viewModel.saveCheckboxChecked = saveCheckboxChecked - viewModel.emailAddress = emailAddress - - if emailAddress != nil { - // Wait for account to load - let expectation = notNullExpectation(for: viewModel, keyPath: \.linkAccount) - wait(for: [expectation], timeout: 10) - } - - return .init(viewModel: viewModel) - } - -} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift index b0646cce80b..ec7803a6190 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift @@ -8,6 +8,7 @@ import iOSSnapshotTestCase import UIKit +import StripeCoreTestUtils @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -16,7 +17,7 @@ import UIKit @testable@_spi(STP) import StripePaymentsUI @testable@_spi(STP) import StripeUICore -class LinkInstantDebitMandateViewSnapshotTests: FBSnapshotTestCase { +class LinkInstantDebitMandateViewSnapshotTests: STPSnapshotTestCase { override func setUp() { super.setUp() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift index b5900c44145..766407fd15e 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift @@ -8,6 +8,7 @@ import iOSSnapshotTestCase import UIKit +import StripeCoreTestUtils @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -15,7 +16,7 @@ import UIKit @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripePaymentsUI -class LinkNavigationBarSnapshotTests: FBSnapshotTestCase { +class LinkNavigationBarSnapshotTests: STPSnapshotTestCase { override func setUp() { super.setUp() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift index e62a1a1e6d3..0e97f930f6f 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift @@ -8,6 +8,7 @@ import iOSSnapshotTestCase import UIKit +import StripeCoreTestUtils @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -15,7 +16,7 @@ import UIKit @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripePaymentsUI -class LinkNoticeViewSnapshotTests: FBSnapshotTestCase { +class LinkNoticeViewSnapshotTests: STPSnapshotTestCase { override func setUp() { super.setUp() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift deleted file mode 100644 index 686715d582f..00000000000 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// LinkPaymentMethodPickerSnapshotTests.swift -// StripeiOS Tests -// -// Created by Ramon Torres on 11/8/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import StripeCoreTestUtils -import UIKit - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class LinkPaymentMethodPickerSnapshotTests: FBSnapshotTestCase { - - override func setUp() { - super.setUp() - // recordMode = true - } - - func testNormal() { - let mockDataSource = MockDataSource() - - let picker = LinkPaymentMethodPicker() - picker.dataSource = mockDataSource - picker.layoutSubviews() - - verify(picker, identifier: "First Option") - - picker.selectedIndex = 1 - verify(picker, identifier: "Second Option") - } - - func testExpanded() { - let mockDataSource = MockDataSource() - - let picker = LinkPaymentMethodPicker() - picker.dataSource = mockDataSource - picker.layoutSubviews() - picker.setExpanded(true, animated: false) - - verify(picker) - } - - func testUnsupportedBankAccount() { - let mockDataSource = MockDataSource() - - let picker = LinkPaymentMethodPicker() - picker.dataSource = mockDataSource - picker.supportedPaymentMethodTypes = [.card] - picker.layoutSubviews() - picker.setExpanded(true, animated: false) - - verify(picker) - } - - func testEmpty() { - let mockDataSource = MockDataSource(empty: true) - - let picker = LinkPaymentMethodPicker() - picker.dataSource = mockDataSource - picker.layoutSubviews() - - verify(picker) - } - - func verify( - _ view: UIView, - identifier: String? = nil, - file: StaticString = #filePath, - line: UInt = #line - ) { - view.autosizeHeight(width: 335) - view.backgroundColor = .white - STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) - } - -} - -extension LinkPaymentMethodPickerSnapshotTests { - - fileprivate final class MockDataSource: LinkPaymentMethodPickerDataSource { - let paymentMethods: [ConsumerPaymentDetails] - - init( - empty: Bool = false - ) { - self.paymentMethods = empty ? [] : LinkStubs.paymentMethods() - } - - func numberOfPaymentMethods(in picker: LinkPaymentMethodPicker) -> Int { - return paymentMethods.count - } - - func paymentPicker( - _ picker: LinkPaymentMethodPicker, - paymentMethodAt index: Int - ) -> ConsumerPaymentDetails { - return paymentMethods[index] - } - } - -} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift index 7f6d910e09a..328b1530ca7 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift @@ -8,6 +8,7 @@ import iOSSnapshotTestCase import UIKit +import StripeCoreTestUtils @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -15,7 +16,7 @@ import UIKit @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripePaymentsUI -class LinkToastSnapshotTests: FBSnapshotTestCase { +class LinkToastSnapshotTests: STPSnapshotTestCase { override func setUp() { super.setUp() diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift deleted file mode 100644 index 752ddeccf45..00000000000 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// LinkVerificationViewSnapshotTests.swift -// StripeiOS Tests -// -// Created by Ramon Torres on 12/7/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import StripeCoreTestUtils -import UIKit - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class LinkVerificationViewSnapshotTests: FBSnapshotTestCase { - - override func setUp() { - super.setUp() - // recordMode = true - } - - func testModal() { - let sut = makeSUT(mode: .modal) - verify(sut) - } - - func testModalWithErrorMessage() { - let sut = makeSUT(mode: .modal) - sut.errorMessage = "The provided verification code has expired." - verify(sut) - } - - func testInlineLogin() { - let sut = makeSUT(mode: .inlineLogin) - verify(sut) - } - - func testEmbedded() { - let sut = makeSUT(mode: .embedded) - verify(sut) - } - - func verify( - _ view: LinkVerificationView, - identifier: String? = nil, - file: StaticString = #filePath, - line: UInt = #line - ) { - view.autosizeHeight(width: 340) - STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) - } - -} - -extension LinkVerificationViewSnapshotTests { - - struct LinkAccountStub: PaymentSheetLinkAccountInfoProtocol { - let email: String - let redactedPhoneNumber: String? - let isRegistered: Bool - let isLoggedIn: Bool - } - - func makeSUT(mode: LinkVerificationView.Mode) -> LinkVerificationView { - let sut = LinkVerificationView( - mode: mode, - linkAccount: LinkAccountStub( - email: "user@example.com", - redactedPhoneNumber: "+1********55", - isRegistered: true, - isLoggedIn: false - ) - ) - - sut.tintColor = .linkBrand - - return sut - } - -} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift deleted file mode 100644 index 27bf3bf48d1..00000000000 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/PayWithLinkViewController-WalletViewModelTests.swift +++ /dev/null @@ -1,144 +0,0 @@ -// -// PayWithLinkViewController-WalletViewModelTests.swift -// StripeiOS Tests -// -// Created by Ramon Torres on 3/31/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import StripeCoreTestUtils -import XCTest - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class PayWithLinkViewController_WalletViewModelTests: XCTestCase { - - func test_shouldRecollectCardCVC() throws { - let sut = try makeSUT() - - // Card with passing CVC checks - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card - XCTAssertFalse(sut.shouldRecollectCardCVC) - - // Card with failing CVC checks - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.cardWithFailingChecks - XCTAssertTrue( - sut.shouldRecollectCardCVC, - "Should recollect CVC when CVC checks are failing" - ) - - // Expired card - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.expiredCard - XCTAssertTrue(sut.shouldRecollectCardCVC, "Should recollect CVC when card has expired") - - // Bank account (CVC not supported) - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.bankAccount - XCTAssertFalse(sut.shouldRecollectCardCVC) - } - - func test_shouldRecollectCardExpiry() throws { - let sut = try makeSUT() - - // Non-expired card - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card - XCTAssertFalse(sut.shouldRecollectCardExpiryDate) - - // Expired card - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.expiredCard - XCTAssertTrue( - sut.shouldRecollectCardExpiryDate, - "Should recollect new expiry date when card has expired" - ) - - // Bank account (CVC not supported) - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.bankAccount - XCTAssertFalse(sut.shouldRecollectCardCVC) - } - - func test_shouldShowInstantDebitMandate() throws { - let sut = try makeSUT() - - // Card - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card - XCTAssertFalse(sut.shouldShowInstantDebitMandate) - - // Bank account - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.bankAccount - XCTAssertTrue(sut.shouldShowInstantDebitMandate) - } - - func test_confirmButtonStatus_shouldHandleNoSelection() throws { - let sut = try makeSUT() - - // No selection - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.notExisting - XCTAssertEqual( - sut.confirmButtonStatus, - .disabled, - "Button should be disabled when no payment method is selected" - ) - - // Selection - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.card - XCTAssertEqual(sut.confirmButtonStatus, .enabled) - } - - func test_confirmButtonStatus_shouldHandleCVCRecollectionRequirements() throws { - let sut = try makeSUT() - - sut.selectedPaymentMethodIndex = LinkStubs.PaymentMethodIndices.cardWithFailingChecks - XCTAssertEqual( - sut.confirmButtonStatus, - .disabled, - "Button should be disabled when no CVC is provided and a card with failing CVC checks is selected" - ) - - // Provide a CVC - sut.cvc = "123" - XCTAssertEqual(sut.confirmButtonStatus, .enabled) - } -} - -extension PayWithLinkViewController_WalletViewModelTests { - - func makeSUT() throws -> PayWithLinkViewController.WalletViewModel { - // Link settings don't live in the PaymentIntent object itself, but in the /elements/sessions API response - // So we construct a minimal response (see STPPaymentIntentTest.testDecodedObjectFromAPIResponseMapping) to parse them - let paymentIntentJson = try XCTUnwrap(STPTestUtils.jsonNamed(STPTestJSONPaymentIntent)) - let orderedPaymentJson = ["card", "link"] - let paymentIntentResponse = [ - "payment_intent": paymentIntentJson, - "ordered_payment_method_types": orderedPaymentJson, - ] as [String: Any] - let linkSettingsJson = ["link_funding_sources": ["CARD"]] - let response = [ - "payment_method_preference": paymentIntentResponse, - "link_settings": linkSettingsJson, - ] - let paymentIntent = try XCTUnwrap( - STPPaymentIntent.decodedObject(fromAPIResponse: response) - ) - - return PayWithLinkViewController.WalletViewModel( - // TODO(ramont): Fully mock `PaymentSheetLinkAccount and remove this. - linkAccount: .init( - email: "user@example.com", - session: LinkStubs.consumerSession(), - publishableKey: nil - ), - context: .init( - intent: .paymentIntent(paymentIntent), - configuration: .init(), - shouldOfferApplePay: false, - shouldFinishOnClose: false, - callToAction: nil - ), - paymentMethods: LinkStubs.paymentMethods() - ) - } - -} diff --git a/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift b/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift index 5344b75c956..048bfdfd796 100644 --- a/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift +++ b/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift @@ -47,7 +47,7 @@ import UIKit private var centeringPadding: UIEdgeInsets { return UIEdgeInsets( top: 0, - left: 0, + left: centerHorizontally ? Self.iconPadding.right : 0, bottom: Self.iconPadding.top, right: 0 ) @@ -71,6 +71,9 @@ import UIKit /// If `true`, the view will display the CVC hint icon instead of the card brand image. let showCVC: Bool + /// If `true`, will center the card brand icon horizontally in the containing view + let centerHorizontally: Bool + /// If `true`, show a CBC indicator arrow var isShowingCBCIndicator: Bool = false { didSet { @@ -125,9 +128,11 @@ import UIKit /// Creates and returns an initialized card brand view. /// - Parameter showCVC: Whether or not to show the CVC hint icon instead of the card brand image. @_spi(STP) public init( - showCVC: Bool = false + showCVC: Bool = false, + centerHorizontally: Bool = false ) { self.showCVC = showCVC + self.centerHorizontally = centerHorizontally super.init(frame: .zero) addSubview(imageView) diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2aed510d18f9a1334b5eeeb94870139d2fb36c61 GIT binary patch literal 6259 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Disabled@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Disabled@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..28ff08090a6ec1b821c62ab2518e379aa1829884 GIT binary patch literal 6677 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Highlighted@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testBordered_Highlighted@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e25f96205e856da4e4593eb37ceb277a45ffa648 GIT binary patch literal 5985 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 ZFJ{+Zh_uLmo2HKYxI2ix{z$G2Hh6w;b1w6AK z(EY0!_i4`@Dx`_F8UWkJy?o|)I$PzuxBs+)sFY%Lvbh_gfGrEtfsalhtE4$GI<^n`eijK^I#~=EA9T{LSngCdn8p< z9g8Moq!f3GIu@w}e@6Sidl13YZz-TGmC@1BG>P6N{gh%^-sU0nE-BzGX+ugRwIdlo zKP*@U<2k8=ah#ZCt@jgTN5caJ4~n>$u2!>JD#WEGyW|$5T4r_$<9?HOBDB%D!L+6@Wz7pVCk~x z9bdNf4ZpsoqpS`*ebHyf)xjPH^P2LAG!Y8#S{hh zLGN1mGG-=lOIG->AWPnSBlPDTzGLRm@*gnuQ_ffQ1(LmMRfC$}K1nN0N+TM^zGrxB ztTm)ysQ&k7a@f>IT_5~qNs$&zThP94ud&m?60#P_fB(vmPFFI^?z?I4azh+b1LtW7 zXzpTOqqo27?Ll!;QzKGXRN;#zM>fqPzMm$jg4NW4d!j*$0(3>6m!)~4iyYBj6^3#z zPAIY$tHv#ccMGlk9>2OXQCkoyh=U18>m=MFfE=!9%~yi*H%#+^3Mk_E^A{?D z@d?34%b~6|tGhsf0{p;G5!hbuw){+x zlR-{ny4R3uZc)pSeKk*k>T>Y z+%@sFk_Q3MkZjV{Xun56`|^@)iz#;nHs346r9DlP<4;W%@=i}%&&c)qo^Vxv%9g-+ z2Y~w{F*2-vbL{P%iLKf{oG%Dezq9b~4^%7vAgUnB9lZv)G-)nq<2@BgqLh>B;JBjx zAKM3{k*^OT@Z2KK@`S{D+rnWgKbuwxK2gudAO$Uz^yE?I6Iq%3xm0(;M(*lyNBd3m z7)Pz4t=co6a*kPk3f(b?Pgj~y0A_}2J0}A?O~mmCrwH^r_im8OA=vMQyGw5qQPZ^flJuw@9u4LFTr#l1fs(Or;k`lmOw_2#q(48f4s_ktBB+yE}5oQbv?>ItH zS{oxAG*cu3o{-r;Za>|RzeN|o@G#N3_XhO1b4m#s(=p0-bFg}^ZC7F{ouv#uPfYBK z9FH*;^$6aObZiN_)u zbCn-S7!~r+CX%f@`|!z$cVq9{RzxSUIMMSTel*C<820!6JwFv{t`0Mv)%y#CqBfN) zZ4cC~iTuzvKI$1Hck3O4cGrsS7kt@x)mb{13G)tY@>vV&#+JTctc=}EwIuz4Qegm% zrq#rfWOIi-Y}RPv)eU|hhX_4C`vUbYzJsq37VgLju#POiAyaKO-{WySYhOo_QkghK zQtWhQ*!eJ}EeyMq?bB!Zh0L(C8p7v*Gn E)BTL+^8udBpjH+FBqE{30b+E&!L*6 zxyWd!(ZEbMO$q}7m487rv{X%!pG|~`r6{`ofWl`b{Wf10q4wc!ipe;KFYzChnb8+7 zxtHb&!SLTgsRj17Z&drr7jMBzk2Z7ijf6Itvq&0jNN^`?PxWlfo}RJ_>8G8|*p%}bOUbfK zn$&`HSu&^2Tx2PhRr~?Zn&DCWQJS>(K}eNW5^|&az|1#?kBMs2=PpZopwP04%fh#w zp3koff;wE64e!prnL3=DCaUX+e3j`xgZNS**79DFq{epQi4Oe!H#fx?7G8k25MjM#SEnJ%ZH1(0zwr4PU zmo%`*aIwTfOZlXA6P;PW9ZtXXbxhwTDf}W&zDJL9H6LBFv$Xwo_B6TCEeVUhly6uD{3}9_^2zHV7&l;u9~%?KIhu2W(Uh5G z;hc|6H#m^wyMw8=(w;IG+%<-)W;>f{X>hM}HjHmu=T67tH}sA+Sl^Q4I_e_X{9Byp zRwJx9X=a|@+rmf`x6AsUFq%pZ4+2g&YkP^LYwfS@jehzndpNRY-!Phl!CL4@e%~MR zbjpjs!bRDpRzC~|lM9)hAq=Q|b|mOJJ0DbYGga)G-=nK+U^Kdxog>J|Lk6$e#tLo# zJ&tj%x6(Vh=H40W_DXAb$!W!$1)TRh*w)EC!^vcE!S9!~goGonprUvb6-Ia2P{87o z;_;ZSth<%n^I6WOWJI$6O@V6EsDNJU?2?4f->tzX#tymPOuIzrf!2r1(6Mn!WU`vc z>J0AmUEh6aQh%Ob*F8yTBjx-6v*~!CP2aw74MRy4XVyiVRzXhMG-eB%PlT7PI*s_c zkw|KakFReLqGTntcMCBdEogIR;rx&9wBMcFrmGW-1z(8Pu8r+37m}rYDbwd^*EIAh zvq3J;?u8%@x-Z=!S$fnmk#fxbxeW14Vh4-=Hm$96Q-9<*kz8<8-A9P$3rJdUWkAU@ z(9q-qQB~lY%OYCAk}FN^<5=5}Rz90jd({@YOa#N-Ei zrE&hv!~7LB+}&(m@}t}AcyGaNQmcW1`Q^*~HdZXF0qE%+q5L3L@Mwxg=!rjfB~~b| zlg#AC0MsuIkei~{#Xe6#yCFlK5$^m}qo_fkh5X_eXuFp(bj zpwZ00otG8NfPOYY^MjL}_-l}_eEGTd&DTkV_(7(Q__8B_;|-5FCnw)$FXz$@l=m~g zqlfl@U!2Y9QAYcV;QR>dzve?qMXO2LlnS4Z>`#;1++rc&Ww$gppMMP{Q49 zWa&aA3Zot%cRgP)P!Lnn(eG@6Y9nF`k&5tJI}KPHTuFaJrCr_ATg;qV6*-!(p?Nlw z(oFlodRh+k4RZ-E>_b;o*hz42o;|;5+l;8zl;qF*iyljCQ+jrU#t%JQB5R`QAQ@l> z>?&UNTH9ACp5~3ZWvM1Tq>ituS>=+#{n)mwoVEy-c`$uubD6xm>yu9yrL&2Hwfa>;^ zo1M;-fJ?>BVJc2oCv2g2Ig0&%*tH4P`h zB@q=4e=g|cLymr3WRS zGYSH#UcNs)om6ulsD!0w_+*k8(S=>u+FB4Aj-pwup6 zj#njTF@$&IgV7F0qgKcb+Gz39n{>4cunS?m(SkHJc+5z%?7jB1nwOA~Y6tJCna)U6 z#1G}mvp-@Du80l*z&OY;#Ovvr1QSQ`!&5bz0j~t}F-u7c^hmJ|R|e{Tc=P+uR*JYn ae+-Jak0+S|__)rdG(bnwKm)6Wi26TsT3}fK literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Highlighted@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Highlighted@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc2e79e77dc601d543f44cab1e2bdfb127a719e GIT binary patch literal 4217 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 J`l#U;@gIITn9BeF literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Loading@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPlain_Loading@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..392ffa96d28a2f8aad57ed6c1e7907112ef587c8 GIT binary patch literal 3937 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 R^}l~nQzJ{lBSUi3e*g!Wf`|YB literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..bcb28a3fe40e4b1cedec14dcafa9de7577e40bcb GIT binary patch literal 8346 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 C72i?- literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary_Highlighted@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testPrimary_Highlighted@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..836d566c29d94436e86601a1ae3bacf474f85999 GIT binary patch literal 8277 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..bac8586566b4d86d276de2d53ee9da9c01fa4c10 GIT binary patch literal 10529 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 ZAVs$A_}OA#b^ljF1sN4-(ChbK{~txg9aI1S literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary_Disabled@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.ButtonLinkSnapshotTests/testSecondary_Disabled@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a25f6bb41c771a9c95f9c54e1156eb7b3592cb5a GIT binary patch literal 9844 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 g4u`+jWQAPt(L+8+a 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 Dh@>aI literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkBadgeViewSnapshotTest/testError@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkBadgeViewSnapshotTest/testError@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2dfd6ab35cfe57288461f986c71fbc5c3029cfe8 GIT binary patch literal 5681 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkBadgeViewSnapshotTest/testNeutral@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkBadgeViewSnapshotTest/testNeutral@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..261e6537d5d83dc742477ac58fb941af9614c781 GIT binary patch literal 4903 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testDefault@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testDefault@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_de@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_de@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_el_GR@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_el_GR@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_es@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_es@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_it@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_it@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 zcmeIZWl&tt7dA+6fdm!rvyZMeq&rf9v1g(80j{^Bfii zCeQ)~{@-onUgh6w@wNQz^DhaT1^b^Cu;47X|I}g3|2D1pEJN}tQ0yc$9bsT7xc`0ZlU`C3T7ztvtWdzDO*UxihEzB$oFowZg~-CG~7 ztqx3XtNqN#F{9*`Bu1%adJDX^6r0?2ID`6TK4w18#G|?#2tI;xCp~aPlz0h6afEXz zFcqa)a3tXS<5{9Wc*8q5gL6tuvyfBIJ;CGB8i3_l%{^N~>#_vWL zh6?JI#GG}qmwn#!0qYM#b#hA*`AuEMnmWhrR;*HT8d}GmRy;>Ep(Sg%Auo-P?fm@M zb~C@=j-o!z6QH-ZYZ=7*QeP(=Q@`Su)d$UaOCq|BS5PXOu)cJ@pce^6Xf9oO5=*+3 zDRU}W*sy3$E~)v9AEvtSGj1o#Coa&epokw=&vTv%)0H zgB~`db5F#83JI)LXvL(fr#{VzzDhkQiu$acpw?2Mq26r+YpTe!u+wuy^Rmx3)lShioI9UYq_H5DV5~9AFx$90WnV{LP>8cEG`o@RG%Le~W7n8rX3;55-rATFK zdHg9pd}uC!7y8@GokjeGm>DcIJw_jQ{F57u?@43zvTxU9Lc%Yfe&~H`iOH-ma{djt^9=X5_>%mEErxYmf z?GA2UQQJ8q3(VjjSx24j>rEnHJUtTFIq%uAO>k$jAl^R~X`q{EY{j2So9CFQwo29) zxJOFNy$hHPPpl~QIIabyT)T@d_2unGK}elugE!j4D9rfyhH9Gl({yZ;5$8hh?-x7> zJXe%xy$&yboM}4ok53G2d}})B!IwLD_Qw=J7p{@O0C?FfHy>#>gc$q)mZ2By`nb0` z4P3ZqhPa(n=F@p~Ma16?g(p>g4*XP7z-d&4_XJeBeW!!v>7x&?g$NF05O1^mV7Ff_ zNu%Bfv5|4}2=WdK6Yq9s%WkwE;KN>GpN;nw&n&q+Lasbh;*#at=&A?eUbGxAJOd6$J--EydS)hhC|yd0 zm|=+QUEOtQURo{fVzG;_&&^Mu<6h>L^sui@^v^MFv^(m^$fo0_c4m;HPUbR)=t;f> zc=ae1J{E$_??0B*bM7b=ei>KpGvkm_G*jPX!FDhH*|DDD1fTWu-XV&mbeR>L%#ZxJ zsyK`=kFazwrT*@E0SW2(`ReLwgAy{V1Rw8Bcm3t@q1vN-;XXgaC6kuDL}~Cj(y8nA z_Ot~s;h_oyk@;N|<1^RiN$VlH#-V(Jjz4Ju_^$X%RNUP|KwKl;9{qy-DbM056E&+J zFi9(2iW#jdA(`1As02MS5Ocvd+MV`4hS zr&pm8-3wXnA$4$VLvO?MAhKCdl;amalQzTzswO0lQ^`y*mOzLO#=yLGNV9F{1wx~X z-4`xbc*ci`8dn{?<94F^^*$kx>9LKsaz4ng7Zn=e<=5>`qD4vt`HU&AsN*Gry z+W=wBQ^01%wl`yW8v?Hbl--|0L>1s>HZ@t9S}` z7-pR?w~C!TVC9J8s6)?%fC=X~Bw!MChAdkj!c^u2Rr>iG(+%d~MltRRDe9%}BU|7q z#fC{t;>Rn|cFg=2#23^t`(M0k%&A7q&8KWSM z*ewAGtSQZROwX>6C7$sTS?|a1jVa)6o~3QodGMl0WYa!UTsFo%7pdriahdOA>zT3| zV}x}hXfh&X;a_F?f^F=bYrkGqZaOhgQ zDeDPofYdwU?Vr?+RAC0K$dLX*rc#;?c-kxKp-@8>Tl#HB3H-^PKry8I`bAeZw>CHt z%xWFgYrUCh3B7ZB6U7ptz`uw7>_Z&F^|$0Z45fXSO@|waTviMM~TSX3u}iUG7#AUlgI(WuJiqk zcC&;2uS-|?DaVnikMhD;mjI>p$_5DD?oJ(+n<9v>vxhOcED`hG&wGiHpUou7CYq?2Sp;;#A9~kndHs8 z)#80_S1i|QHS78>_T5p*LY5qCT5XoFWXkx%`tN#|BH+2#e~po47_=|&)1Y_Zn4C+@ zU8c&WRfHP7?XnCSHq)v$pzEzb8~$CEBssyr_edB&U7egcfQz~+uxyOnf}Bmj`C_ua zIs#(?NxqK6?=If*L>7q{9Kj+^!ka?NC&;~BTv1<`tZF0_LSf9hKL-phGHxd?&~bT4 ztP^X_D`5GW63L6b;?;!JtktW$#F5#IH~lTe;8S&q6Qk9(AO?D@yYt&NK9v*134!6@ zZ08ItlevD=!9?lw?^pW3@n+J++dxGcOvf!0zKz<`p*`^lGmn!zghq5x47u$*I9)Qd%~1(FK;|+WnF9GqBE@Xw&T!-a*v*Hq zZsB>T-XagxM4h4Dv!#Ps9dwmeA#%#*EqStk0dU%?vd;Ll_SS+*mIZHVw3D=JA24!L z{qBAOuT3P~IVYX@t7csl(dDjE;o{TEer5PLEB|TqYes+|8z|H|ckb>O42Wn1_$pDpD z20PfxQ2az!yqA&2KM)tpj&wFk6rbX0mdngY#J)C)@o8aBMKgTeHgk}noC}LH{SMm> zUL+9f1bxX(vaifC?s*lC(FkpD_lut841IVFM=x2P_DobXd&_4i!ZTjtbFR2T1S0As zKP}xVf^7n7qiK>t!b~^EO$c_~G(%ik>!d0~;#7%KDWFVFQpstp7*<|L(AxdC4r>Z? zgFM#m#WA91W8|u@d-dcdra(N(@bsB9S5)yGf}s*HixT`L|IV0~ZOC1sa!zKbX-zyM37+mR1**AA59Aw=H6Bd`IEQg(+DiuoT@$HJstULNf z!;85`4zkr4$ajYp9K-u?`tXSv(N`Z{kNkGeBmM^Z&C9Q2YMwNzbtWWS&vNGy5M#t9 zn^8>T(L7muXrGIlxSxa+uPc}^q4!W6PBqmjFv<&d+SLqjFYd@$kywh+6OV*w3JVKe z;x9=efp?aT=~|G9;u_;nU0TFk^$j1e5{>xmFpCIeJp*;sm@XGxe+^B-L$TO(hX+P? z-WxBsK3s0mFf$Fb1L^a^8^8Y;MqN9{Z~P}dr@E{|U$uZDFGHpxeof?ZzX)V&#w|On z-0nNrte8)^UoRtyWLa;@A)i~dGkv60f7dmwpTD^-6C4;gVo-Wk^7SM3ATTt;)*)QK z+?;xZHe8j_WKV<(z4B60OGm^Sh<@{#H|kh08hvesneD31{sW7Qwfz~=kR6bUo}iI? z39GT^<34e;>WzQWZU+{%5LI&*aN6gwk&|ecNd%Fa=0$AaTu9>rmJbW!gf@WL)1ezN zf6KPDqBjy>Kl#=h*o@1j4Z8BUGoUBgA^Y}Mw`%jBr{V-lA-qfonvne?@fb71vPVlA zQwsBxYuyN4zfpzeqwZYLMbW=h935IT(J7#!$x%lXJ&`XL-D(&ghZo3>;Ng9)pmD99y&7oZj7d70)$FUcZ5tUT(aztYtA%Kf#kmwQs?= zWVm7LhT(Rfbl*1zR%DuRbmiRg`3T2x)x;TL42J~HWU2bdH{L?(v(JD4rrWT*s_tJ$ zFnLN{*jjV}O?=6C)$u=z*^od@VOxw@X0;@OLcUoTe*|Gsr)uY}O}=c{_Q*(alT3v?QWFvwCPv2LK45pROA-+B`cBR#){h7+r21?5#;qSeCgN!HbgWECDvF z3jW!yV_>PYqE6COccSW5;|g-);Vz^4@+^m8b;0c#Wt7!$j(EkcG_m!R#n%vElY|gX zn%Pab>BtMMb+^sJwX|2h+^s*uLyxc#X*!g%9nQole=u;}uT8bOX&qH~=4Nel;lm(W zc1d~b!+cp3=QO->^oIMUAk_`yuI2ki=93U_yygV34hDnmjtGpevM%p`r>jt@#t7DI zP;=1MqnHJvP;lRoTy1+k)|jz&)d37@q~{43%u%$ln}04at~8u^d5~H=n^BxmqeYye z)b6Rx4LXv-Rq(n+-JEud-p&a;eN7#1klk!=OnJIIPYs;VAyG!w8|w@dmF-mBT}8Z| z2K^KC0>2l*$m zq05whrsK}rrEGgn8jaxI-Unq!zXIT}rFb=p1zpUy3r?g z(r8#}eSD)ox)Bk)$pI(~ov#~qa?&MHrqjdT#7J1`t=8oH)_;#*Q<9uCuCys9sK|M* zP+5C|ou-V5PE;)gBk-jaGrc!0vee}FzB20SK;;mYbM*H^P3F)m9DM$G6GXcq~eqXq@xz2FmFNm{o=uU*_j@a>I{( z$~bY~99fzOm{v_K%(=p9-d%BdyCKUGZE3L zw*+G2HVgouI&brh$EX0N!|q5?0s{E%oHwj_0h+0mC(UUpJ3de+d1-R6yyz^vE<97B z*SJ|_t^K4?!>?fDt?lnLPxq_(>wOBex>Laa6+`jwF!z^wUk*UIns%(bFP!LUES%~f zQCA)H--gI3CTG(~p-sox1>34upyjp$Nt>sgu7KoxTXv|MO z+mHOQ!J}s?Gd~=kD%ZD9Asr}z)&T9tNJK6j2PDuo8Ho=q&I5^$UKBFZXnY;u&%Gly zKjjj<=4%2ag(lv(?@&kAgj2Crm1woWmk77A?nl4*@EdgtDhTXLuYcFaj765z%w3?+ z>X83-Fs@;~(?THV3S!5l=bT9S)2*TwCcAX}OY&~4zZs()Z35bK=e`)tE!Dt*RJ?2o zxvll4&CL(p5y;(3vK#eN^KzbTOO{ppO*dXebfo7=*juY{vE=cc4KY_;-a9&RTcbGs z4?p7(z#a{@ZRSRiAS&$~ru)|O(RY`tm>cJYgAU)l8#ex!MzF`ci)LLNQR2hYNtL`cYFlw-KG)oH za9#Ke`|CkP?De4H6WzIn=6oDcHFM+u99Gs515Ji+g-|uM{4p7c*HdjTZAt8^#coX` zf%6+7AlRW*os#BKW!1_lKIl$f8=r@KcC#i4CNfY(0Bh3gJBVX@6XpQ(hGJh2Z$tFy zWFRS*1p4g;?^CUMEs71@7&Cl0m##V?;X^p&-!{fr{?N4|uWW)r5?`Ok8z1*L9lFmg za$)#_Iy3gx(}lXo6M{D)=FNGFeLUE$BQsVtJcxBMg`eyaArG%!{g#eDuVpVK79#yb zu{(V2d?%`ZkYw>1l|5JQ(0Iw2`%kK7>n6VXcP!3nMCH5P){8#%O*sb7e^NQcfY-cm zA11qOD9}{vR;4#oFVzrU2M)rHEd1rIXj@1b+f_@9zSSrEh9$CEEyF>{!pHgo_LSYo zh62kz?UJ9@=qE77O|Tdo&dGMekV`7KpU)^-zE|<4GDdxEE5BxjoN9(%4fQ+)qNaiX z2C+GEr}=f-XZc;+qfP(R_mYdSP(LGT3d?Yoi-)l7;-n&fw;kVLMW$iNgYU8_yyD*T zdpf4Hqpe^P8cb_gOi=wfS*Q(9fM&?u9bhxVFK9KLsGHRKIE@-xFv5CD%;~}LqEB#= zECRI=PbOu=jZ8%ZGo6`c@V1%n@Qu36ENoHPX)l-XR&p2}UWR~z^2-h5W zI!w$>NO~1e0O#`boldkHL>48KWef>~VO=s!=H^Y)j>IQ?_;xcA1XK^p*H?OxuhaLu zim-U*U6kzd^s6;sF^>s5C@rf8s!q# zIs!(bT)w9+MwWT^=77WZOgL&SyhLw87dWj1U z-Yt77{~BKb{ypU{6rIOWNgcGWSgjs-xFY(iQE{f~@TT~0y!^L&uGetP`SOzvLhVy0 z7;xV@`|YwQyEm0F$fq9vh_zO*gvcPbnGXaD=KqH*<0k)wC;K~r`YZi*`c=ur6)D*q zLr7<{s6i2K$GfiEvUndp&hH}9Cqx6z+q5bu$lCWnDYGzifslg|S^R9A+Z6dW0zG{h0Jg=t555p;c{vX0pwE zfTa%ol9&QK9H zg0iminr@r2KugKlDP&B|WuZj<>{)kUV@`E0!1oCS*7p}VIWqG9Fa95dpq7$_`-GX4 zPF;PnqEO|bPYtDs^8W@oTLcX9<9OHB(Zr$4bPk?vs=Z$?jPMsMEO_`g{}bk7UxM7} zX&l7<^E}B384XPxKtgy6$kw+Vg05+rWf6Wr)}V|s(;QcB$ahcftzM?@6~Jwk^KY@- z!E|2ee@*&t4J%r>r)PbV`e*FL5o|)bN9HT~%dWl`0C*Q1;_l80>zc63@3e0({ZIGE zmZ;JiZjKiR$n4#O-$s1y^es&fb=AKYkN=l>3_S&0cvJd+_wq4Qa}Q|TwHA(7!^1g3O??c{-zhi%G=b z9++8uSL*U1NJ}i;t~+L7rZ!Yr`sLBh&8@i<$4TOk+2l&3$0^`4QiBE5#>%MOo$Ipr zn1!n2=HBLs68l1N_NSe#7>TsTe2O`5HxqwjW~U82TMbEtqlQi(;;V1C&noJ%GKRm; ztn*W!xwQB0fH-%XZyl~zT-M12l#kfxIYVxl+(pl#Tn@er@wwUkdC<1FAN^2ZQLpGh z=H$T{x68euJBzz)8h!L>4(ijlezsIAWPh8dJMqJo-yX7;>F_YvGSyDPqi`!|H%xh! zZsA(k*J6XDJCCTM!M{%u*nP|dnxn$ErOTT#*(p2qJ(D{umJ`J`vw z1xDq0*zl!TR-46am6}iu&yFq!@z>_|tPxwG#@)yDvS>q3Xt`Mc;jiPP*3PSDH!;jTx z;9^rcysRz@70&l^*`9&FgpG)~rZLm`E*_nyJ)BOKS_ABrt$i7p0~Zw49;9DrowV;f zDnXuv)eFK4rm9FwexIF*??Rn~9VX|$0L z6FN{1e*pCfX`6-Iw0La^X81jnPOSlnHo6L!{kaG$&T7)EP5ZD}c+Q;qd5dJCY%s=nn#L=FK`g2I019T%sn z`p;EDC}^-#`%jhJ_2VcsuixtSW3nyQNt9+;EqPkE*&wsLsH%eeOr2X7YrdZgpLT%K zlU_jQUE#Mx(c7h3s_mv z8a6=TZ<#cYNF#U~i_vz0I8k4qUhl^wE?mff%)i&^DAcamuWkXSy6g^F<;;WuR)e{@ zi_0r3D`g`G`{eP^UN;LQ1deqO^L4qAt1`DjafT%CpBWL_N2*vfebIrsAyat4pBjX> z3y#gbl{yzHfLWthp~?$s$p<^z3k3z;?4vEC&71E^S`o*9a*_#)I6E>j!u~Hfx0O0N zK~D>{kE{eWXQzp4?b%1Pi#D6~q1*Z=6i==(Gn?o=UCjn1W$PZZp~O7sfs?qWXu>2q z1}TB^=zx{-oiJ7UZ?pJg8k(jxVTP$Ud6jls)6Y|CtDO*mk6-m7ms*2a-!C^VMzqnz zZuwEy`Bb)W4e5nYC4X?|9#`dCoZQbV2N@HWgrf^<=&J;quG%m3YFMtI`l2Z{3o?bf zk;2c1a`;lthqor~Qal2?uJ%MB;U3{V_}k@$exI^5DvZqtosqduV~yD$@WR}m3QrBayK^)nAHdT0^!0qeOsUO>HHL}oPe$61n}ZS zO{es(fZ&nH3aZG8n(-GUr=$wyKM$efyF_<&VaA8qFdZnAlE@X};tlCe@T3F?? za7#XNN8BgEfM)`Vj4)y%MsSIK08N^86(^=bnO3yME`Y9As3s`^CI> z8aGJw{HWUM@Q1(Xty-xj)yvaJ@7}q(Z=d;$Lu$w{?4c8W5zI4~jb}fWH($wH;WWcU zA`rGKO!xiV9l8(D%Wpd}i3!U+5~}j65v|%$ ztlEFug@+&*_By=V_Rvb&+rnKsEQnYTP-9IwtS()Lo3ZD+@n2uw5?rrXSD$?jzbh+l zsEePVvz9&IqUvp%T;@z+VAHo8(2E<2YFrRsK4fGd8y}fF>yDgIcE?EmxOk^DL+kdl zg2b%8z-!KgPvX7q9NzTqGUs&iEfS798S-x8A(B#S=nyToL%W<|L;FaWiwgE-Lk)kx zWF2YVnOMSHl z6A$|EBrb`Yn>?ynajLuXKr1w3OCvrkZ`|pK@3qhza8cE(2B^YLwQmC951N|Y9e{r< ze}H!ShAtcrghl(}K{MdsUR2l`oHunfUw1+m>Ry=qTMqHcZCJ)6k+4hIiOnc+;wKIq zfa`>kt|2DbSKnh-4P19yCN~3f7tKAG7j}cLtH=iRat2EFyV#Tak%jK73??5+^hJE$&?3TLub_N*5`?5bVIsOIKrW*4!c9e8;A@W2{2=!dM|??686-b|}je@*M- z`PSadHEMOh4+$}>ec-`BD)5klv0jJu68uHq=$aVb-GwR>>1|R>?r~sQi3nd*0ZUzu z$tTLC{?C&Ttp!j}74#L=9T6UW_IFGIY~7gGt-Cr{N%6=@ywdEmBQarOJ>J%f+_{Qp zq`b%K!25QGn~EZAOfSN4$&_thMCgPj0QnrXnaNFd^kR_DzF7vC5(YhMW?IufSowmw z0p#JO%^AI)7xiW<5N@6O5Ndh#MGatlpH%b#Aw|zWy4dar>%6G?!BEE6jZ(8zF;=TZeZrpq0368#8= z{lgtU?(F1hKwD<~J2Uls(BoA>kwF>?c*$_JoqWx*_B>^0cGBsuJ{s#~Z&q#>QyOQs zrA=PAza(F zdKhG}v_SW1xuogW-}tok5(4Hs2P!#VkvBD$(E(@+D7JB4Lk+1K{qTn3og+75{?$3T=#IA+mKV=SY!f{T_?+N$=cnS;^0uC)5IiLL~O$?)QBk)_ht&AIbTB zrg7ar&FZ-wsI#Vl&Xh0VK)}o9Lb%K9-S0st4l-2J=+&(Q+-5pdo4UBUMb@fW+Vbke zj~b^{xJM3K_f#-xLK# zRk(z@^3ENh*Lu#N%DtOX5PM{Rg;ad3isoA8dQ9ent5sBgcy@dCu(+z{k$nP&m%$$g zwBxUhaF&FEc}K%L8jv;Br7=HH{i2rEy`@D`V=p^q=Jd(Jj`DHiw^g%ZhGXZ#bh9E_ z@^$FY4g8^CVnOP*pRUq@aKXzri$aU{Y2joEL*JS66@&RCPK9bR8nG_bt0K)U6Ouq_ z4SpCafQ9l?iF4GS9ei6r>MCmIMT|ZkP{MD~d zQ8Z@#!FoCdEu4MofOQOEp)fBg=rOpk>?i8r`NUCrqH8nS;I@!MpfDyrjkbz+_8C!Z zm>W9jX+Y{W*dQBq|W6qrp`2 z3(|29oML3LyukQ$*Nip}@aKvK^V2GVM@4o(Q2`g-55XA$HP1p1-S{T9M659uuve^cEkZTrL@7?M%2%Rx`9s_C)TzO> zCT3cClhA-ky%Pn~7?(AS=2H4{YqtALXGS=C?+_GAmH_`-TlsrKEvZIPGzpvIXT>1C zZ+&IU#hm~SU2Fb2+W=BX^=aP__D(8Me-ZK3ttLJuS(zvOZDJtviU#7{sqc%Wx#16= z+l)jZVFO!{FQ*K_R!gnT)X>M__>RqfBLCAqZW&+K<-0FP;jLeUtiA7q$aBWhjo(vA zmWGPp+S5KyVuSIGQkeWOc7DwJMQ2mVa*91!TX|c=>{uR{_h7qRCRe0(57Mjk1o2^G z1AWKt%Mdq~UK+7(OI5GNk1+EC&=#m`r)~2m#{$k*Uc)}8mKx@=%=V>lI&T7qF7!w?>p=A$wCh0tFGYaH=&`g zWFZ&n@GC$X9&LA?GO1NpfJ+2hK&_vw1_ZrVAksPN#7IQark6jkrtbuuVT{<2ec<|DBG#mQVdrB(CKw&gbbJS7Ns;c=t$-G+70o`Dla-t* zEOUnb;GMaU!F3@G%)4b`lCwoxns7dr%BZgj=gh{lAMkKW&odPQguYJMnh53RfqXx3 zJeZHjm(y_NT2-B;53BydeR*BT;}z2QKP41E7L_%Ui^vq;3A<4ox(WiRHN<>oDz z`VdxWYcV{@8T&#?Xx)KKHDg3b$^%DrK#Qo4k&o>fu-b1U#!h-LtaIVZlse)@3y zWgTygOi=wffUzhSX!zJDoG{e^N}0>tTn9<45}CO< ziW+0z=>|PM!NryJ!>&9?c-vK++mj9w11dG-mHs?{t55cX9aOcghtr47oLR>DXa}4; zcnP=K_b+b;{k>N?v?*o$h<^xVVQ+J%KRC@M?l*b%yld&0-l<7jSsvjnvaw%h`nGyy zjA3^iB&K^1#H}C8A7ONM5qj6^E0e7IQ~T3c5?ENQ_bZi<@{qunEhB z6H(vrv^d-&r-ajs;@gUMC#r)gPGn>K17KWAL^x{)`75t9WpBb2E!_4RiLj>*7YXP? z8gayLDAW7w1(R9Fut^#wITOu;=3ji+b#Rt4Jt+8ghJ3w{%2u*(Pp2&QwA!;6N%(-H zTN8naBg{jj-=wsBUFv34JLupmQ4c6x9#TxHV2wwwOQ4B5Ra1k5mt?k<7wZp~N+#l} zxt!I*L)m>zma!h%g}<1*#(DE+V)&G3qZzxGwk=61_2|3o?{4FtMS;ZCX=YW4*RV!~ zz3IU2$aCRdF+K_2*q7?rc)1nR>Xnd2DvH5}E17Q=J_VBMdzP;V{1Gy0)(LhuSJ{El zH|>*n8tOcv=%+`vm~g+xh2MMsY8Wwt@=MUTaLj{WOxxrByz(6A;Yp4p0fh{g>qY&? z0}tCJjo2VP5Juw~AIkx6zUaG1e}ZnM`7|8@m}j|0!Pob%?J9h-hcTe5E|D+P{e zbAVwZnjtxs2?Bi`G}cbo`NKQXyX;eu?VOVsJuRW^MTlLB=fm-h9JWjS2%_?W;I87p zzLuuxQ`0HRaM)I8H-k9E5!Bm$se5yv>4(nh#cL`lWrqB@+?l}rb^cbvfsHNJNIR7? z6)UrN3)ZzZeq*kP+g@C_Q{Sy?PhUP%GE%+4d>%?F&+SbQ?^QSTS#U{B3YTwz8ph+i zg(VdypVq{&Zy;Af&slvcKCp9&{_%6;`CQg-H$Sq;JAzey(kji ztg@ShiFh)(Oio|o3m3#7cW7ltnl&}7bvM;WUFk~{_z(;7LIDk8aHbxbu1|T3DF0!I zrccbnMaB7}(2Xz-)nV;9uRSkj+r6PT-3hxrZR!k*)2T9<6TgEH;}Olhz>GXdGJP~G zv)s>F+}rkZ*W7AFJMF!0dDLY6V=Or|3_i_zoVU;PTM%DZei^OkXhDC$8r0uw#D{#+ z0-iFRS^~-G6FWN15Jp(NJSSh~kzae}-JSMUlGT&E_Apsnf1k1l3Dh0P( z#>-L49%vjrA{sTMAc(FLt3E&2zj{cAO}E}Qm#IM?!YLFXPO)@c`NdJhTHidmVMUJmH8BuBnX-w=seSCuxl>R!F)Fc!~8(tC+E9<_Qpz0FN_ba#f z1>Z2xoMpR6Tw-V`ZKnzJv;`UgptCN&F6FL?YXz2t*WG%GHSk&P4$AU8U4S;#tpKq}?wWB3)=1#1fk!+BvbUPDG(UTQBfK0qEPX#0yFjVuVBfYFm*@^J5-ETeQwkT0J0on_WY-d>I zjz?Onh*H*_LlqPHx>p=$?-&NKH%Q}k#{n7}y`0lM$ZMz(J5gl3TO;`l1KFtCa;}a2 zv-$F_vloNUwSQ9m70FDJuTAfJJR8bs^9UeYS2}8RVeZlr8`N1`g4qlONy*Do4D~Tq z&hBftkWP$US&^30tmEeG>hN(lZwa!z2WOf@pibxa5pDtU?UIygqlzgVux|EmQ3Ev)nx~d9ai*;qEvKn$`fc$0SJ&56zVq-rd)9EsA6acROna#H8g{xJgpSk6cL6&p zy?o;QI-&G+b#&77iWBAgUBSOcF;>FiVyyBTOK*#BI)8Wm`kJ|LJ@WL1rn=|#WZzug zSR3v!_Mi@*ZR|kgUw1Kpt+&p>(cb(THAdGr*!9IM`1#u^?FP5{p6iFYo=MwzI6wb< zQcdVWzPSZ24=22OPe%+KNO$w@nUDNd#w`fo#bvONwzb_mICae;+A_FFLED=}oP^Ir z`nf$@Jb9tM>Ne4|Es&BK8T9*CQO(zEU0lxA@MxK55@VB@ziE~jw4Q|M_KfnIReem- ztDpn>wAc7%7CoU5>z3b$?Y+q**AUWyli;@8J%YY3<0G*OU^`-nE1j-p>{ScEdSkP# z?)*nTek;zUfR9oGHRvQ532i<0007%igWlD`fWUQCd+j8srKDQg)$bPxl4se9#<$~M zIQ9p$CfX%&^F4kB7QM|HW9+3*B-HpCZRM(UnR*oFelBW|8sPt_Ow4G@@NfNoc zQ(mcnJ+4n4uUQU#>Os;->`k|FoWqD=S~!iAUKwnc@lIq|1AK5~!?or>YmX|XZ}I5U z{xZq+$H9JJ@=*r$Uj1fFY#ZY-v@Sl-=xD^q-m7H6r|Th)xfs#UT#7I9;}2AoAdm)D zk|O*z?})HRI%YtF$$Qjtfxzf`MeS*XdwHLqUPv98Md>(B-wqn(7~UOKTvy{j*7a=l z^HB7ucIM^@tbc`FaWPrz^`>9u23X9JA2{Zva{I6w!Do1c*D>$R0;Y|moh3LIzcD5u zie9ayIy$m`HcxYrbi6dY`t-y}nQ8ahvio`Y_l7m0CVxDz;gP_FSvOv{IucrnsEOF($K2! z1{qC8mE(F<1>ZLQms`CARZ*P{8LIPuy0)rkNrM#*UsShoQZv$4{ z#R|(q#xgW(o%DD6TQ;=G{rKl&bG!bB_TVh?C@xrwbZXDFNc^wUl#_o+tfdoQgX-ix zaR}2bG-)rGt3FU>wWudgv~B+2y52z?3D)YF6<2k_il-nVuAmzpkSCIB_-HUI`FOZK zqm8dkiR}T8;4U`<3-EkXgWAHU>O7?OKuHz9)=4nBQ7E6=a!yf#k(ktcJLE(<5h9C! zUuwc*yY^H1N{td#1zOZr)-lFDsyzNZDBmhWLn8$%r0I1ln#cP*nQxulQ;$Tx8}NSJ z&d7M}6N-e8Y`|d(317YY_v^~MDHD26N5!Cdgi>OGJZ_%L=x)3bN@DZHX1|Xbw)OFN zJi=K<$a&G35kxVpR35cExiZVFpYd8g^XF<|XNn?^&QOcij@VHt-1&Eo$;0RNW` dR>HdT_O6e;1|FAz{{B5%QcUh^xrl-9{{g47yZrzF literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_ja@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_ja@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_ko@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_ko@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_zh_Hans@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkInstantDebitMandateViewSnapshotTests/testLocalization_zh_Hans@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2874298e2f68177cbcca609a8f02178c6cf83106 GIT binary patch literal 15988 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testDefault@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testDefault@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..66dcc162102eb7a0ae22184c363b3c96a0abb295 GIT binary patch literal 8480 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 Xht!2LMgzbPOdv%$)qBOVj|2V>0xNoU literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testDefault_BackButton@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testDefault_BackButton@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..374006515a678142a4ee3d1d193c4be206bb6d93 GIT binary patch literal 3933 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 Xht!2LMgzbPOdv%$)qBOVj|2V>0xNoU literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithEmailAddress_BackButton@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithEmailAddress_BackButton@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..374006515a678142a4ee3d1d193c4be206bb6d93 GIT binary patch literal 3933 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 Xht!2LMgzbPOdv%$)qBOVj|2V>0xNoU literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithLongEmailAddress_BackButton@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithLongEmailAddress_BackButton@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..374006515a678142a4ee3d1d193c4be206bb6d93 GIT binary patch literal 3933 zcmeHJk2h3#6n}4e#!zZP`7tqLiHX{&u}P(R9Qjd`jMDU*gCSNCLMX#J2ccEX#GU`&8>f|%XQoJO9C^=wws0`kKfWUDSPE(o z!L~~oy0D+~jN8w^1qe#QDAWnYbX&)cfo!tj#Dtcy;no`dt2RDM!rVnjoV6Y-IFW0i zT{j`ZC|PW@)8iA%?q*9r@q$97@=15{Y+ykaJ05nJL1i%NF$v8Z7Et*wq1YHW1ILAW z_@cwGfKlHHt zvxo&$ct*f_fR$u-twU0(L&bT}THl}z!B#Y?0aHrHm!Sd#?OZ}?KA-c+rdCBa_ zGgDW156}|KUQ<^^hWF-+8j6+Fbz)^sLD%qb!YI~I@IFafiP|#Gv}V*#Nqn#~zhX}& zM~~g0im7O9e%EH$Oa`6RYH?s3GJfNWpAkUo$eH^2yE; zr@Du+nVh`}gkCcn>Zobile5^%=)QXM682@vdzOaOcPClCiXrYNsJ5O?g1(liD(zk(YqwxqP^-QpcG+3r;8oS%TsmhjQ}y?UMU3)F zz+n!A48Gc1u~nJMO1SG1oqK)ySdX08IN6?2ALrcC5PD?0Z13BE{7oPS)Wf`+FXAhE zqW45WNMeJVI#}SMeE+`KpsXF-k}jHCvPaRd%AadW?)cJs-T7?eh39tv5uEqJBQ7xi zh=iQxMh=SeREGW9TIT+Rl}mE*&{f&#Y&Ws`;;X%3EQjPfZ(^g;S|cA+rKqLtt;=2x z4i>8ec#n(4Vs%)fQnjmM>!Y_Rboiz^<J)c+E8dTP)yLG?p#o)C4ChTcL;z!1g zc6Rh(S-`uZpwNeNi+qUbIO>U($j#4|2R(oKwEt9L#k-*AuU}tXp~w*}%-<&@0?JvB z&$$wM`AX}J6;DP++5>XTSfLNF!QI4Tna>3lk(z5kwK*bmz6F&22PjNFSzkKCal3p9 z_QDiex*IGNpw~Yv!k zztA5UTNbETKrBrUhSPoCOyBxkQy+)W-lPSwZ)Lw*{%wBHmRK~{HD7#=V+`|RVMX_C zxmw*cO3t|*^yl}^Vj@b^7F!Sn`RY>qJb5zVok3euWXBQ@xWKnC zB*Io-%Eh=%RfUTa2X3%JHk8Pftbn&Pxl(1IxCMcP2hu>OG|mq*SUlbe>7uB|3G}Ar zJENuCi5wm;KPNpV->JyMA+)XKub9@GYN$S_OdE+%FQaO>z^cTktvSmZr8FL8WGemT)MKHWG6Hms}J0 zor)j5W(UFVMp`AJ-YA2D#CHNCJtI5U64RQJ0Wh*k{N$Y5fRVO0?eLLN08(y!weYWE zxsH%suDZSqiic|GTc6R92e*QV$xMEPGAbF0hoM2ahPE1V@E*vxdyS6=;dnj+{uyvW fhxp%Qc;Dpmc;4Xx-(Tq9LPfk+`nZ?61*ZQ4dw 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 Date: Tue, 8 Oct 2024 17:12:31 -0700 Subject: [PATCH 03/12] Fix lint --- .../en.lproj/Localizable.strings | 21 +++++++++++++++++++ .../NavigationBar/LinkNavigationBar.swift | 2 +- ...kPaymentMethodPicker-CellContentView.swift | 2 +- .../Link/Extensions/UIColor+Link.swift | 7 +++---- .../Link/ButtonLinkSnapshotTests.swift | 5 ----- .../Link/LinkBadgeViewSnapshotTest.swift | 7 +------ ...InstantDebitMandateViewSnapshotTests.swift | 7 +------ .../Link/LinkNavigationBarSnapshotTests.swift | 7 +------ .../Link/LinkNoticeViewSnapshotTests.swift | 7 +------ .../Link/LinkToastSnapshotTests.swift | 7 +------ .../Internal/UI/Views/CardBrandView.swift | 2 +- 11 files changed, 32 insertions(+), 42 deletions(-) diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings index cd3d2f695a1..0ca50f16450 100644 --- a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings +++ b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings @@ -70,6 +70,9 @@ /* Text providing link to terms for ACH payments */ "By continuing, you agree to authorize payments pursuant to these terms." = "By continuing, you agree to authorize payments pursuant to these terms."; +/* Mandate text displayed when paying via Link instant debit. */ +"By continuing, you agree to authorize payments pursuant to these terms." = "By continuing, you agree to authorize payments pursuant to these terms."; + /* Cash App mandate text */ "By continuing, you authorize %@ to debit your Cash App account for this payment and future payments in accordance with %@'s terms, until this authorization is revoked. You can change this anytime in your Cash App Settings." = "By continuing, you authorize %1$@ to debit your Cash App account for this payment and future payments in accordance with %2$@'s terms, until this authorization is revoked. You can change this anytime in your Cash App Settings."; @@ -124,6 +127,9 @@ /* Label for CPF/CPNJ (Brazil tax ID) field */ "CPF/CPNJ" = "CPF/CPNJ"; +/* Label for identifying the default payment method. */ +"Default" = "Default"; + /* Text for a button that allows manual entry of an address */ "Enter address manually" = "Enter address manually"; @@ -201,9 +207,15 @@ e.g, 'Pay faster at Example, Inc. and thousands of businesses.' */ /* US Bank Account copy title for Mobile payment element form */ "Pay with your bank account in just a few steps." = "Pay with your bank account in just a few steps."; +/* Label for a section displaying payment details. */ +"Payment" = "Payment"; + /* Text on a screen that indicates a payment has failed */ "Payment failed" = "Payment failed"; +/* Title for a section listing one or more payment methods. */ +"Payment methods" = "Payment methods"; + /* Text on a screen that indicates a payment has failed informing the user we are asking the user to try a different payment method */ "Please go back and select another payment method" = "Please go back and select another payment method"; @@ -281,12 +293,21 @@ is not supported by the merchant */ /* Prompt for microdeposit verification before completing purchase with merchant. %@ will be replaced by merchant business name */ "Stripe will deposit $0.01 to your account in 1-2 business days. Then you’ll get an email with instructions to complete payment to %@." = "Stripe will deposit $0.01 to your account in 1-2 business days. Then you’ll get an email with instructions to complete payment to %@."; +/* Accessibility hint to tell the user that they can tap to hide additional content. */ +"Tap to close" = "Tap to close"; + +/* Accessibility hint to tell the user that they can tap to reveal additional content. */ +"Tap to expand" = "Tap to expand"; + /* An error message. */ "The IBAN you entered is incomplete." = "The IBAN you entered is incomplete."; /* An error message. */ "The IBAN you entered is invalid, \"%@\" is not a supported country code." = "The IBAN you entered is invalid, \"%@\" is not a supported country code."; +/* Label shown when a payment method cannot be used for the current transaction. */ +"Unavailable for this purchase" = "Unavailable for this purchase"; + /* Title for a button that when tapped, updates a card brand. */ "Update" = "Update"; diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift index 5f3881fbf92..3ba0892a03f 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift @@ -172,7 +172,7 @@ final class LinkNavigationBar: UIView { // TODO(link): Set isLoggedIn once the SDK supports logging in again // let isLoggedIn = linkAccount?.isLoggedIn ?? false let isLoggedIn = false - + emailLabel.text = linkAccount?.email showEmailLabel = isLoggedIn && !showBackButton diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift index 93a36183721..5fe2fe5bcc5 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift @@ -22,7 +22,7 @@ extension LinkPaymentMethodPicker { var paymentMethod: ConsumerPaymentDetails? { didSet { switch paymentMethod?.details { - case .card(_): + case .card: // TODO(link): Needs refactor // case .card(let card): // cardBrandView.cardBrand = card.stpBrand diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift index 23afcd1f6e5..be519121811 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/UIColor+Link.swift @@ -20,12 +20,12 @@ extension UIColor { static var linkBrand: UIColor { UIColor(red: 0, green: 0.84, blue: 0.44, alpha: 1.0) } - + /// Darker version of the brand color. /// /// Use it as accent color on small UI elements or text links. static let linkBrandDark: UIColor = UIColor(red: 0.020, green: 0.659, blue: 0.498, alpha: 1.0) - + /// Main background color. static let linkBackground: UIColor = .dynamic( light: .white, @@ -90,8 +90,7 @@ extension UIColor { static var linkPrimaryButtonForeground: UIColor { UIColor(red: 0, green: 0.12, blue: 0.06, alpha: 1.0) } - - + /// Foreground color of the secondary button. static let linkSecondaryButtonForeground: UIColor = .dynamic( light: UIColor(red: 0.114, green: 0.224, blue: 0.267, alpha: 1.0), diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift index 5c12a600039..da3811b5c9b 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift @@ -17,11 +17,6 @@ import UIKit class ButtonLinkSnapshotTests: STPSnapshotTestCase { - override func setUp() { - super.setUp() - // recordMode = true - } - func testPrimary() { let sut = makeSUT(configuration: .linkPrimary(), title: "Primary Button") verify(sut) diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift index 27fd83a3fcf..5de42b388a2 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift @@ -7,8 +7,8 @@ // import iOSSnapshotTestCase -import UIKit import StripeCoreTestUtils +import UIKit @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -18,11 +18,6 @@ import StripeCoreTestUtils class LinkBadgeViewSnapshotTest: STPSnapshotTestCase { - override func setUp() { - super.setUp() - // recordMode = true - } - func testNeutral() { verify( LinkBadgeView( diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift index ec7803a6190..d528416d7a8 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift @@ -7,8 +7,8 @@ // import iOSSnapshotTestCase -import UIKit import StripeCoreTestUtils +import UIKit @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -19,11 +19,6 @@ import StripeCoreTestUtils class LinkInstantDebitMandateViewSnapshotTests: STPSnapshotTestCase { - override func setUp() { - super.setUp() - // recordMode = true - } - func testDefault() { let sut = makeSUT() verify(sut) diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift index 766407fd15e..5da577d7d35 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift @@ -7,8 +7,8 @@ // import iOSSnapshotTestCase -import UIKit import StripeCoreTestUtils +import UIKit @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -18,11 +18,6 @@ import StripeCoreTestUtils class LinkNavigationBarSnapshotTests: STPSnapshotTestCase { - override func setUp() { - super.setUp() - // recordMode = true - } - func testDefault() { let sut = makeSUT() verify(sut) diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift index 0e97f930f6f..f02bd0bd573 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift @@ -7,8 +7,8 @@ // import iOSSnapshotTestCase -import UIKit import StripeCoreTestUtils +import UIKit @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -18,11 +18,6 @@ import StripeCoreTestUtils class LinkNoticeViewSnapshotTests: STPSnapshotTestCase { - override func setUp() { - super.setUp() - // recordMode = true - } - func testError() { verify( LinkNoticeView( diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift index 328b1530ca7..670ba43c5b5 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift @@ -7,8 +7,8 @@ // import iOSSnapshotTestCase -import UIKit import StripeCoreTestUtils +import UIKit @testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @@ -18,11 +18,6 @@ import StripeCoreTestUtils class LinkToastSnapshotTests: STPSnapshotTestCase { - override func setUp() { - super.setUp() - // recordMode = true - } - func testSuccess() { let toast = LinkToast(type: .success, text: "Success message!") verify(toast) diff --git a/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift b/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift index 048bfdfd796..d94c880aaba 100644 --- a/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift +++ b/StripePaymentsUI/StripePaymentsUI/Source/Internal/UI/Views/CardBrandView.swift @@ -73,7 +73,7 @@ import UIKit /// If `true`, will center the card brand icon horizontally in the containing view let centerHorizontally: Bool - + /// If `true`, show a CBC indicator arrow var isShowingCBCIndicator: Bool = false { didSet { From 47756c0aafe5c0138e47a0b30e020efcc7deac7c Mon Sep 17 00:00:00 2001 From: David Estes Date: Tue, 8 Oct 2024 17:26:25 -0700 Subject: [PATCH 04/12] Fix accidentally added files --- .../Source/Categories/Dictionary+Stripe.swift | 4 +- .../LinkPaymentMethodPicker-AddButton.swift | 99 ------ .../LinkPaymentMethodPicker-Cell.swift | 280 ---------------- ...kPaymentMethodPicker-CellContentView.swift | 138 -------- .../LinkPaymentMethodPicker-Header.swift | 194 ----------- .../LinkPaymentMethodPicker-RadioButton.swift | 114 ------- .../LinkPaymentMethodPicker.swift | 312 ------------------ 7 files changed, 2 insertions(+), 1139 deletions(-) delete mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift delete mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift delete mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift delete mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift delete mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift delete mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift diff --git a/StripeCore/StripeCore/Source/Categories/Dictionary+Stripe.swift b/StripeCore/StripeCore/Source/Categories/Dictionary+Stripe.swift index 7d6e876bdec..7e20329eb4e 100644 --- a/StripeCore/StripeCore/Source/Categories/Dictionary+Stripe.swift +++ b/StripeCore/StripeCore/Source/Categories/Dictionary+Stripe.swift @@ -45,14 +45,14 @@ extension Dictionary { return newDict } - public mutating func mergeAssertingOnOverwrites(_ other: [Key: Value]) { + @_spi(STP) public mutating func mergeAssertingOnOverwrites(_ other: [Key: Value]) { merge(other) { a, b in stpAssertionFailure("Dictionary merge is overwriting a key with values: \(a) and \(b)!") return a } } - public func mergingAssertingOnOverwrites(_ other: S) -> [Key: Value] where S: Sequence, S.Element == (Key, Value) { + @_spi(STP) public func mergingAssertingOnOverwrites(_ other: S) -> [Key: Value] where S: Sequence, S.Element == (Key, Value) { merging(other) { a, b in stpAssertionFailure("Dictionary merge is overwriting a key with values: \(a) and \(b)!") return a diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift deleted file mode 100644 index 3bb072a6432..00000000000 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// LinkPaymentMethodPicker-AddButton.swift -// StripePaymentSheet -// -// Created by Ramon Torres on 10/20/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -@_spi(STP) import StripeUICore -import UIKit - -extension LinkPaymentMethodPicker { - - final class AddButton: UIControl { - struct Constants { - static let iconSize: CGSize = .init(width: 24, height: 24) - } - - private let iconView: UIImageView = UIImageView(image: Image.icon_add_bordered.makeImage(template: true)) - - private lazy var textLabel: UILabel = { - let label = UILabel() - label.text = String.Localized.add_a_payment_method - label.numberOfLines = 0 - label.textColor = tintColor - label.font = LinkUI.font(forTextStyle: .bodyEmphasized) - label.adjustsFontForContentSizeCategory = true - return label - }() - - override var isHighlighted: Bool { - didSet { - update() - } - } - - init() { - super.init(frame: .zero) - - isAccessibilityElement = true - accessibilityTraits = .button - accessibilityLabel = textLabel.text - directionalLayoutMargins = Cell.Constants.margins - - setupUI() - update() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if self.point(inside: point, with: event) { - return self - } - - return nil - } - - override func tintColorDidChange() { - super.tintColorDidChange() - self.textLabel.textColor = tintColor - } - - private func setupUI() { - let stackView = UIStackView(arrangedSubviews: [iconView, textLabel]) - stackView.spacing = Cell.Constants.contentSpacing - stackView.alignment = .center - stackView.translatesAutoresizingMaskIntoConstraints = false - - addSubview(stackView) - - NSLayoutConstraint.activate([ - iconView.widthAnchor.constraint(equalToConstant: Constants.iconSize.width), - iconView.heightAnchor.constraint(equalToConstant: Constants.iconSize.height), - stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), - stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), - stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), - ]) - } - - private func update() { - if isHighlighted { - iconView.alpha = 0.7 - textLabel.alpha = 0.7 - backgroundColor = .linkControlHighlight - } else { - iconView.alpha = 1 - textLabel.alpha = 1 - backgroundColor = .clear - } - } - - } - -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift deleted file mode 100644 index 6a2a47fa3bc..00000000000 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift +++ /dev/null @@ -1,280 +0,0 @@ -// -// LinkPaymentMethodPicker-Cell.swift -// StripePaymentSheet -// -// Created by Ramon Torres on 10/19/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -@_spi(STP) import StripeUICore -import UIKit - -protocol LinkPaymentMethodPickerCellDelegate: AnyObject { - func savedPaymentPickerCellDidSelect(_ cell: LinkPaymentMethodPicker.Cell) - func savedPaymentPickerCell(_ cell: LinkPaymentMethodPicker.Cell, didTapMenuButton button: UIButton) -} - -extension LinkPaymentMethodPicker { - - final class Cell: UIControl { - struct Constants { - static let margins = NSDirectionalEdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20) - static let contentSpacing: CGFloat = 12 - static let contentIndentation: CGFloat = 34 - static let menuSpacing: CGFloat = 8 - static let menuButtonSize: CGSize = .init(width: 24, height: 24) - static let separatorHeight: CGFloat = 1 - static let iconViewSize: CGSize = .init(width: 14, height: 20) - static let disabledContentAlpha: CGFloat = 0.5 - } - - override var isHighlighted: Bool { - didSet { - setNeedsLayout() - } - } - - override var isSelected: Bool { - didSet { - setNeedsLayout() - } - } - - var paymentMethod: ConsumerPaymentDetails? { - didSet { - update() - } - } - - var isLoading: Bool = false { - didSet { - if isLoading != oldValue { - update() - } - } - } - - var isSupported: Bool = true { - didSet { - if isSupported != oldValue { - update() - } - } - } - - weak var delegate: LinkPaymentMethodPickerCellDelegate? - - private let radioButton = RadioButton() - - private let contentView = CellContentView() - - private let activityIndicator = ActivityIndicator() - - private let defaultBadge = LinkBadgeView( - type: .neutral, - text: STPLocalizedString("Default", "Label for identifying the default payment method.") - ) - - private let alertIconView: UIImageView = { - let iconView = UIImageView() - iconView.contentMode = .scaleAspectFit - iconView.image = Image.icon_link_error.makeImage(template: true) - iconView.tintColor = .linkDangerForeground - return iconView - }() - - private let unavailableBadge = LinkBadgeView(type: .error, text: STPLocalizedString( - "Unavailable for this purchase", - "Label shown when a payment method cannot be used for the current transaction." - )) - - private lazy var menuButton: UIButton = { - let button = UIButton(type: .system) - button.setImage(Image.icon_menu.makeImage(), for: .normal) - button.addTarget(self, action: #selector(onMenuButtonTapped(_:)), for: .touchUpInside) - button.translatesAutoresizingMaskIntoConstraints = false - return button - }() - - /// The menu button frame for hit-testing purposes. - private var menuButtonFrame: CGRect { - let originalFrame = menuButton.convert(menuButton.bounds, to: self) - - let targetSize = CGSize(width: 44, height: 44) - - return CGRect( - x: originalFrame.midX - (targetSize.width / 2), - y: originalFrame.midY - (targetSize.height / 2), - width: targetSize.width, - height: targetSize.height - ) - } - - private let separator: UIView = { - let separator = UIView() - separator.backgroundColor = .linkControlBorder - separator.translatesAutoresizingMaskIntoConstraints = false - return separator - }() - - override init(frame: CGRect) { - super.init(frame: frame) - - isAccessibilityElement = true - directionalLayoutMargins = Constants.margins - - setupUI() - addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(onCellLongPressed))) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func setupUI() { - let rightStackView = UIStackView(arrangedSubviews: [defaultBadge, alertIconView, activityIndicator, menuButton]) - rightStackView.spacing = LinkUI.smallContentSpacing - rightStackView.distribution = .equalSpacing - rightStackView.alignment = .center - - let stackView = UIStackView(arrangedSubviews: [contentView, rightStackView]) - stackView.spacing = Constants.contentSpacing - stackView.distribution = .equalSpacing - stackView.alignment = .center - - let container = UIStackView(arrangedSubviews: [stackView, unavailableBadge]) - container.axis = .vertical - container.spacing = Constants.contentSpacing - container.distribution = .equalSpacing - container.alignment = .leading - container.translatesAutoresizingMaskIntoConstraints = false - addSubview(container) - - radioButton.translatesAutoresizingMaskIntoConstraints = false - addSubview(radioButton) - - addSubview(separator) - - NSLayoutConstraint.activate([ - // Radio button - radioButton.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), - radioButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - - // Menu button - menuButton.widthAnchor.constraint(equalToConstant: Constants.menuButtonSize.width), - menuButton.heightAnchor.constraint(equalToConstant: Constants.menuButtonSize.height), - - // Loader - activityIndicator.widthAnchor.constraint(equalToConstant: Constants.menuButtonSize.width), - activityIndicator.heightAnchor.constraint(equalToConstant: Constants.menuButtonSize.height), - - // Icon - alertIconView.widthAnchor.constraint(equalToConstant: Constants.iconViewSize.width), - alertIconView.heightAnchor.constraint(equalToConstant: Constants.iconViewSize.height), - - // Container - container.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), - container.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), - container.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: Constants.contentIndentation), - container.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), - // Make stackView fill the container - stackView.trailingAnchor.constraint(equalTo: container.trailingAnchor), - - // Separator - separator.heightAnchor.constraint(equalToConstant: Constants.separatorHeight), - separator.bottomAnchor.constraint(equalTo: bottomAnchor), - separator.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), - separator.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), - ]) - } - - private func update() { - contentView.paymentMethod = paymentMethod - updateAccessibilityContent() - - guard let paymentMethod = paymentMethod else { - return - } - - var hasExpired: Bool { - switch paymentMethod.details { - case .card(let card): - return card.hasExpired - case .bankAccount: - return false - case .unparsable: - return false - } - } - - defaultBadge.isHidden = isLoading || !paymentMethod.isDefault - alertIconView.isHidden = isLoading || !hasExpired - menuButton.isHidden = isLoading - contentView.alpha = isSupported ? 1 : Constants.disabledContentAlpha - unavailableBadge.isHidden = isSupported - - if isLoading { - activityIndicator.startAnimating() - } else { - activityIndicator.stopAnimating() - } - } - - override func layoutSubviews() { - super.layoutSubviews() - radioButton.isOn = isSelected - backgroundColor = isHighlighted ? .linkControlHighlight : .clear - } - - private func updateAccessibilityContent() { - guard let paymentMethod = paymentMethod else { - return - } - - accessibilityIdentifier = "Stripe.Link.PaymentMethodPickerCell" - accessibilityLabel = paymentMethod.accessibilityDescription - accessibilityCustomActions = [ - UIAccessibilityCustomAction( - name: String.Localized.show_menu, - target: self, - selector: #selector(onShowMenuAction(_:)) - ), - ] - } - - @objc func onShowMenuAction(_ sender: UIAccessibilityCustomAction) { - onMenuButtonTapped(menuButton) - } - - @objc func onMenuButtonTapped(_ sender: UIButton) { - delegate?.savedPaymentPickerCell(self, didTapMenuButton: sender) - } - - @objc func onCellLongPressed() { - delegate?.savedPaymentPickerCell(self, didTapMenuButton: menuButton) - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if menuButtonFrame.contains(point) { - return menuButton - } - - return bounds.contains(point) ? self : nil - } - - override func touchesEnded(_ touches: Set, with event: UIEvent?) { - super.touchesEnded(touches, with: event) - - guard let touchLocation = touches.first?.location(in: self) else { - return - } - - if bounds.contains(touchLocation) { - delegate?.savedPaymentPickerCellDidSelect(self) - } - } - - } - -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift deleted file mode 100644 index 5fe2fe5bcc5..00000000000 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift +++ /dev/null @@ -1,138 +0,0 @@ -// -// LinkPaymentMethodPicker-CellContentView.swift -// StripePaymentSheet -// -// Created by Ramon Torres on 11/19/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore -import UIKit - -extension LinkPaymentMethodPicker { - - final class CellContentView: UIView { - struct Constants { - static let contentSpacing: CGFloat = 12 - static let iconSize: CGSize = CardBrandView.targetIconSize - static let maxFontSize: CGFloat = 20 - } - - var paymentMethod: ConsumerPaymentDetails? { - didSet { - switch paymentMethod?.details { - case .card: -// TODO(link): Needs refactor -// case .card(let card): -// cardBrandView.cardBrand = card.stpBrand - bankIconView.isHidden = true - cardBrandView.isHidden = false - primaryLabel.text = paymentMethod?.paymentSheetLabel - secondaryLabel.text = nil - secondaryLabel.isHidden = true - case .bankAccount(let bankAccount): - bankIconView.image = PaymentSheetImageLibrary.bankIcon(for: bankAccount.iconCode) - cardBrandView.isHidden = true - bankIconView.isHidden = false - primaryLabel.text = bankAccount.name - secondaryLabel.text = paymentMethod?.paymentSheetLabel - secondaryLabel.isHidden = false - case .none, .unparsable: - cardBrandView.isHidden = true - bankIconView.isHidden = true - primaryLabel.text = nil - secondaryLabel.text = nil - secondaryLabel.isHidden = true - } - } - } - - private lazy var bankIconView: UIImageView = { - let iconView = UIImageView() - iconView.contentMode = .scaleAspectFit - return iconView - }() - - private lazy var cardBrandView: CardBrandView = CardBrandView(centerHorizontally: true) - - private let primaryLabel: UILabel = { - let label = UILabel() - label.adjustsFontForContentSizeCategory = true - label.font = LinkUI.font(forTextStyle: .bodyEmphasized, maximumPointSize: Constants.maxFontSize) - label.textColor = .linkPrimaryText - return label - }() - - private let secondaryLabel: UILabel = { - let label = UILabel() - label.font = LinkUI.font(forTextStyle: .caption, maximumPointSize: Constants.maxFontSize) - label.textColor = .linkSecondaryText - return label - }() - - private lazy var iconContainerView: UIView = { - let view = UIView() - bankIconView.translatesAutoresizingMaskIntoConstraints = false - cardBrandView.translatesAutoresizingMaskIntoConstraints = false - - view.addSubview(bankIconView) - view.addSubview(cardBrandView) - - let cardBrandSize = cardBrandView.size(for: Constants.iconSize) - NSLayoutConstraint.activate([ - view.widthAnchor.constraint(equalToConstant: max(Constants.iconSize.width, cardBrandSize.width)), - view.heightAnchor.constraint(equalToConstant: max(Constants.iconSize.height, cardBrandSize.height)), - - bankIconView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor), - bankIconView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor), - bankIconView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor), - bankIconView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor), - bankIconView.centerXAnchor.constraint(equalTo: view.centerXAnchor), - bankIconView.centerYAnchor.constraint(equalTo: view.centerYAnchor), - - cardBrandView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor), - cardBrandView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor), - cardBrandView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor), - cardBrandView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor), - cardBrandView.centerXAnchor.constraint(equalTo: view.centerXAnchor), - cardBrandView.centerYAnchor.constraint(equalTo: view.centerYAnchor), - - cardBrandView.widthAnchor.constraint(equalToConstant: cardBrandSize.width), - cardBrandView.heightAnchor.constraint(equalToConstant: cardBrandSize.height), - ]) - - return view - }() - - private lazy var stackView: UIStackView = { - let labelStackView = UIStackView(arrangedSubviews: [ - primaryLabel, - secondaryLabel, - ]) - labelStackView.axis = .vertical - labelStackView.alignment = .leading - labelStackView.spacing = 0 - - let stackView = UIStackView(arrangedSubviews: [ - iconContainerView, - labelStackView, - ]) - - stackView.spacing = Constants.contentSpacing - stackView.alignment = .center - stackView.translatesAutoresizingMaskIntoConstraints = false - return stackView - }() - - override init(frame: CGRect) { - super.init(frame: frame) - addAndPinSubview(stackView) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - } - -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift deleted file mode 100644 index 3064dd16451..00000000000 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift +++ /dev/null @@ -1,194 +0,0 @@ -// -// LinkPaymentMethodPicker-Header.swift -// StripePaymentSheet -// -// Created by Ramon Torres on 10/22/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeUICore -import UIKit - -extension LinkPaymentMethodPicker { - - final class Header: UIControl { - struct Constants { - static let contentSpacing: CGFloat = 16 - static let chevronSize: CGSize = .init(width: 24, height: 24) - static let collapsedInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) - static let expandedInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 4, trailing: 20) - } - - /// The selected payment method. - var selectedPaymentMethod: ConsumerPaymentDetails? { - didSet { - contentView.paymentMethod = selectedPaymentMethod - updateAccessibilityContent() - } - } - - var isExpanded: Bool = false { - didSet { - setNeedsLayout() - updateChevron() - updateAccessibilityContent() - } - } - - override var isHighlighted: Bool { - didSet { - if isHighlighted && !isExpanded { - backgroundColor = .linkControlHighlight - } else { - backgroundColor = .clear - } - } - } - - private let payWithLabel: UILabel = { - let label = UILabel() - label.font = LinkUI.font(forTextStyle: .body) - label.textColor = .linkSecondaryText - label.text = STPLocalizedString("Payment", "Label for a section displaying payment details.") - label.adjustsFontForContentSizeCategory = true - return label - }() - - private let headingLabel: UILabel = { - let label = UILabel() - label.font = LinkUI.font(forTextStyle: .bodyEmphasized) - label.textColor = .linkPrimaryText - label.text = STPLocalizedString( - "Payment methods", - "Title for a section listing one or more payment methods." - ) - label.adjustsFontForContentSizeCategory = true - return label - }() - - private let contentView = CellContentView() - - private let cardNumberLabel: UILabel = { - let label = UILabel() - label.font = UIFont.monospacedDigitSystemFont(ofSize: 14, weight: .medium) - .scaled(withTextStyle: .body, maximumPointSize: 20) - return label - }() - - private lazy var chevron: UIImageView = { - let chevron = UIImageView(image: StripeUICore.Image.icon_chevron_down.makeImage(template: true)) - chevron.contentMode = .center - - NSLayoutConstraint.activate([ - chevron.widthAnchor.constraint(equalToConstant: Constants.chevronSize.width), - chevron.heightAnchor.constraint(equalToConstant: Constants.chevronSize.height), - ]) - - return chevron - }() - - private lazy var paymentInfoStackView: UIStackView = { - let stackView = UIStackView(arrangedSubviews: [ - payWithLabel, - contentView, - ]) - - stackView.alignment = .center - stackView.setCustomSpacing(Constants.contentSpacing, after: payWithLabel) - stackView.translatesAutoresizingMaskIntoConstraints = false - - return stackView - }() - - private lazy var stackView: UIStackView = { - let stackView = UIStackView(arrangedSubviews: [ - paymentInfoStackView, - headingLabel, - chevron, - ]) - - stackView.axis = .horizontal - stackView.spacing = Constants.contentSpacing - stackView.distribution = .equalSpacing - stackView.alignment = .center - stackView.isLayoutMarginsRelativeArrangement = true - stackView.translatesAutoresizingMaskIntoConstraints = false - - return stackView - }() - - override init(frame: CGRect) { - super.init(frame: .zero) - - addSubview(stackView) - - NSLayoutConstraint.activate([ - // Stack view - stackView.topAnchor.constraint(equalTo: topAnchor), - stackView.bottomAnchor.constraint(equalTo: bottomAnchor), - stackView.leadingAnchor.constraint(equalTo: leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: trailingAnchor), - ]) - - isAccessibilityElement = true - accessibilityTraits = .button - - updateChevron() - updateAccessibilityContent() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func updateChevron() { - if isExpanded { - chevron.transform = CGAffineTransform(rotationAngle: .pi) - chevron.tintColor = .linkPrimaryText - } else { - chevron.transform = .identity - chevron.tintColor = .linkSecondaryText - } - } - - private func updateAccessibilityContent() { - if isExpanded { - accessibilityLabel = headingLabel.text - accessibilityHint = STPLocalizedString( - "Tap to close", - "Accessibility hint to tell the user that they can tap to hide additional content." - ) - } else { - accessibilityLabel = selectedPaymentMethod?.accessibilityDescription - accessibilityHint = STPLocalizedString( - "Tap to expand", - "Accessibility hint to tell the user that they can tap to reveal additional content." - ) - } - } - - override func layoutSubviews() { - super.layoutSubviews() - - if isExpanded { - paymentInfoStackView.isHidden = true - headingLabel.isHidden = false - stackView.directionalLayoutMargins = Constants.expandedInsets - } else { - paymentInfoStackView.isHidden = false - headingLabel.isHidden = true - stackView.directionalLayoutMargins = Constants.collapsedInsets - } - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if self.point(inside: point, with: event) { - return self - } - - return nil - } - - } - -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift deleted file mode 100644 index 6ba74090c09..00000000000 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift +++ /dev/null @@ -1,114 +0,0 @@ -// -// LinkPaymentMethodPicker-RadioButton.swift -// StripePaymentSheet -// -// Created by Ramon Torres on 11/15/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import UIKit - -extension LinkPaymentMethodPicker { - - final class RadioButton: UIView { - struct Constants { - static let diameter: CGFloat = 20 - static let innerDiameter: CGFloat = 8 - static let borderWidth: CGFloat = 1 - } - - public var isOn: Bool = false { - didSet { - update() - } - } - - public var borderColor: UIColor = .linkControlBorder { - didSet { - applyStyling() - } - } - - /// Layer for the "off" state. - private let offLayer: CALayer = { - let layer = CALayer() - layer.bounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter) - layer.cornerRadius = Constants.diameter / 2 - layer.borderWidth = Constants.borderWidth - layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) - return layer - }() - - /// Layer for the "on" state. - private let onLayer: CALayer = { - let layer = CALayer() - layer.bounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter) - layer.cornerRadius = Constants.diameter / 2 - layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) - - let innerCircle = CALayer() - innerCircle.backgroundColor = UIColor.white.cgColor - innerCircle.cornerRadius = Constants.innerDiameter / 2 - innerCircle.bounds = CGRect(x: 0, y: 0, width: Constants.innerDiameter, height: Constants.innerDiameter) - innerCircle.anchorPoint = CGPoint(x: 0.5, y: 0.5) - - // Add and center inner circle - layer.addSublayer(innerCircle) - innerCircle.position = CGPoint(x: layer.bounds.midX, y: layer.bounds.midY) - - return layer - }() - - override var intrinsicContentSize: CGSize { - return CGSize(width: Constants.diameter, height: Constants.diameter) - } - - init() { - super.init(frame: .zero) - layer.addSublayer(offLayer) - layer.addSublayer(onLayer) - update() - applyStyling() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - applyStyling() - } - - override func layoutSubviews() { - offLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) - onLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) - } - - override func tintColorDidChange() { - super.tintColorDidChange() - applyStyling() - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - applyStyling() - } - - // MARK: - Private methods - - private func update() { - CATransaction.begin() - CATransaction.setDisableActions(true) - offLayer.isHidden = isOn - onLayer.isHidden = !isOn - CATransaction.commit() - } - - private func applyStyling() { - CATransaction.begin() - CATransaction.setDisableActions(true) - offLayer.borderColor = borderColor.cgColor - onLayer.backgroundColor = tintColor.cgColor - CATransaction.commit() - } - - } - -} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift deleted file mode 100644 index 1ae6860ba1b..00000000000 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift +++ /dev/null @@ -1,312 +0,0 @@ -// -// LinkPaymentMethodPicker.swift -// StripePaymentSheet -// -// Created by Ramon Torres on 10/25/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import UIKit - -@_spi(STP) import StripeUICore - -protocol LinkPaymentMethodPickerDelegate: AnyObject { - func paymentMethodPickerDidChange(_ picker: LinkPaymentMethodPicker) - - func paymentMethodPicker( - _ picker: LinkPaymentMethodPicker, - showMenuForItemAt index: Int, - sourceRect: CGRect - ) - - func paymentDetailsPickerDidTapOnAddPayment(_ picker: LinkPaymentMethodPicker) -} - -protocol LinkPaymentMethodPickerDataSource: AnyObject { - - /// Returns the total number of payment methods. - /// - Returns: Payment method count - func numberOfPaymentMethods(in picker: LinkPaymentMethodPicker) -> Int - - /// Returns the payment method at the specific index. - /// - Returns: Payment method. - func paymentPicker( - _ picker: LinkPaymentMethodPicker, - paymentMethodAt index: Int - ) -> ConsumerPaymentDetails - -} - -/// For internal SDK use only -@objc(STP_Internal_LinkPaymentMethodPicker) -final class LinkPaymentMethodPicker: UIView { - weak var delegate: LinkPaymentMethodPickerDelegate? - weak var dataSource: LinkPaymentMethodPickerDataSource? - - var selectedIndex: Int = 0 { - didSet { - updateHeaderView() - } - } - - var supportedPaymentMethodTypes = Set(ConsumerPaymentDetails.DetailsType.allCases) - - var selectedPaymentMethod: ConsumerPaymentDetails? { - let count = dataSource?.numberOfPaymentMethods(in: self) ?? 0 - - guard selectedIndex >= 0 && selectedIndex < count else { - return nil - } - - return dataSource?.paymentPicker(self, paymentMethodAt: selectedIndex) - } - - private var needsDataReload: Bool = true - - private lazy var stackView: UIStackView = { - let stackView = UIStackView(arrangedSubviews: [ - headerView, - listView, - ]) - - stackView.axis = .vertical - stackView.clipsToBounds = true - stackView.translatesAutoresizingMaskIntoConstraints = false - return stackView - }() - - private let headerView = Header() - - private lazy var listView: UIStackView = { - let stackView = UIStackView(arrangedSubviews: [ - addPaymentMethodButton - ]) - - stackView.axis = .vertical - stackView.distribution = .equalSpacing - stackView.clipsToBounds = true - stackView.translatesAutoresizingMaskIntoConstraints = false - return stackView - }() - - private let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .medium) - private let selectionFeedbackGenerator = UISelectionFeedbackGenerator() - - private let addPaymentMethodButton = AddButton() - - override init(frame: CGRect) { - super.init(frame: .zero) - addAndPinSubview(stackView) - setup() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func setup() { - clipsToBounds = true - accessibilityIdentifier = "Stripe.Link.PaymentMethodPicker" - - layer.cornerRadius = 16 - layer.borderWidth = 1 - layer.borderColor = UIColor.linkControlBorder.cgColor - tintColor = .linkBrandDark - backgroundColor = .linkControlBackground - - headerView.addTarget(self, action: #selector(onHeaderTapped(_:)), for: .touchUpInside) - headerView.layer.zPosition = 1 - - listView.isHidden = true - listView.layer.zPosition = 0 - - addPaymentMethodButton.addTarget(self, action: #selector(onAddPaymentButtonTapped(_:)), for: .touchUpInside) - } - - override func layoutSubviews() { - super.layoutSubviews() - reloadDataIfNeeded() - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - layer.borderColor = UIColor.linkControlBorder.cgColor - } - - func setExpanded(_ expanded: Bool, animated: Bool) { - headerView.isExpanded = expanded - - // Prevent double header animation - if headerView.isExpanded { - // TODO(ramont): revise layout margin placement and remove conditional - setNeedsLayout() - layoutIfNeeded() - } else { - headerView.layoutIfNeeded() - } - - if headerView.isExpanded { - stackView.showArrangedSubview(at: 1, animated: animated) - } else { - stackView.hideArrangedSubview(at: 1, animated: animated) - } - } - - private func updateHeaderView() { - headerView.selectedPaymentMethod = selectedPaymentMethod - } - -} - -private extension LinkPaymentMethodPicker { - - @objc func onHeaderTapped(_ sender: Header) { - setExpanded(!sender.isExpanded, animated: true) - impactFeedbackGenerator.impactOccurred() - } - - @objc func onAddPaymentButtonTapped(_ sender: AddButton) { - delegate?.paymentDetailsPickerDidTapOnAddPayment(self) - } - -} - -// MARK: - Data Loading - -extension LinkPaymentMethodPicker { - - func reloadData() { - needsDataReload = false - - addMissingPaymentMethodCells() - - let count = dataSource?.numberOfPaymentMethods(in: self) ?? 0 - if count == 0 { - headerView.isHidden = true - listView.isHidden = false - } - - for index in 0.. listView.arrangedSubviews.count - 1 { - let cell = Cell() - cell.delegate = self - - let index = listView.arrangedSubviews.count - 1 - listView.insertArrangedSubview(cell, at: index) - } - - for (index, subview) in listView.arrangedSubviews.enumerated() { - subview.layer.zPosition = CGFloat(-index) - } - - headerView.selectedPaymentMethod = selectedPaymentMethod - } - -} - -extension LinkPaymentMethodPicker { - - func index(for cell: Cell) -> Int? { - return listView.arrangedSubviews.firstIndex(of: cell) - } - - func removePaymentMethod(at index: Int, animated: Bool) { - isUserInteractionEnabled = false - - listView.removeArrangedSubview(at: index, animated: true) { - let count = self.dataSource?.numberOfPaymentMethods(in: self) ?? 0 - - if index < self.selectedIndex { - self.selectedIndex = max(self.selectedIndex - 1, 0) - } - - self.selectedIndex = max(min(self.selectedIndex, count - 1), 0) - - self.reloadData() - self.delegate?.paymentMethodPickerDidChange(self) - self.isUserInteractionEnabled = true - } - } - -} - -// MARK: - Cell delegate - -extension LinkPaymentMethodPicker: LinkPaymentMethodPickerCellDelegate { - - func savedPaymentPickerCellDidSelect(_ savedCardView: Cell) { - if let newIndex = index(for: savedCardView) { - let oldIndex = selectedIndex - selectedIndex = newIndex - - reloadCell(at: oldIndex) - reloadCell(at: newIndex) - - selectionFeedbackGenerator.selectionChanged() - - delegate?.paymentMethodPickerDidChange(self) - } - } - - func savedPaymentPickerCell(_ cell: Cell, didTapMenuButton button: UIButton) { - guard let index = index(for: cell) else { - assertionFailure("Index not found") - return - } - - let sourceRect = button.convert(button.bounds, to: self) - - delegate?.paymentMethodPicker(self, showMenuForItemAt: index, sourceRect: sourceRect) - } - -} From 34552dc3a23becf55bcedb0fdae96a0c91453a6e Mon Sep 17 00:00:00 2001 From: David Estes Date: Tue, 8 Oct 2024 18:13:05 -0700 Subject: [PATCH 05/12] Fix accidentally added files --- .../Localizations/en.lproj/Localizable.strings | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings index 0ca50f16450..ca5c300508a 100644 --- a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings +++ b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings @@ -127,9 +127,6 @@ /* Label for CPF/CPNJ (Brazil tax ID) field */ "CPF/CPNJ" = "CPF/CPNJ"; -/* Label for identifying the default payment method. */ -"Default" = "Default"; - /* Text for a button that allows manual entry of an address */ "Enter address manually" = "Enter address manually"; @@ -207,15 +204,9 @@ e.g, 'Pay faster at Example, Inc. and thousands of businesses.' */ /* US Bank Account copy title for Mobile payment element form */ "Pay with your bank account in just a few steps." = "Pay with your bank account in just a few steps."; -/* Label for a section displaying payment details. */ -"Payment" = "Payment"; - /* Text on a screen that indicates a payment has failed */ "Payment failed" = "Payment failed"; -/* Title for a section listing one or more payment methods. */ -"Payment methods" = "Payment methods"; - /* Text on a screen that indicates a payment has failed informing the user we are asking the user to try a different payment method */ "Please go back and select another payment method" = "Please go back and select another payment method"; @@ -293,21 +284,12 @@ is not supported by the merchant */ /* Prompt for microdeposit verification before completing purchase with merchant. %@ will be replaced by merchant business name */ "Stripe will deposit $0.01 to your account in 1-2 business days. Then you’ll get an email with instructions to complete payment to %@." = "Stripe will deposit $0.01 to your account in 1-2 business days. Then you’ll get an email with instructions to complete payment to %@."; -/* Accessibility hint to tell the user that they can tap to hide additional content. */ -"Tap to close" = "Tap to close"; - -/* Accessibility hint to tell the user that they can tap to reveal additional content. */ -"Tap to expand" = "Tap to expand"; - /* An error message. */ "The IBAN you entered is incomplete." = "The IBAN you entered is incomplete."; /* An error message. */ "The IBAN you entered is invalid, \"%@\" is not a supported country code." = "The IBAN you entered is invalid, \"%@\" is not a supported country code."; -/* Label shown when a payment method cannot be used for the current transaction. */ -"Unavailable for this purchase" = "Unavailable for this purchase"; - /* Title for a button that when tapped, updates a card brand. */ "Update" = "Update"; From 51e80f49bf782a917590d0cdf23f977eea572ce2 Mon Sep 17 00:00:00 2001 From: David Estes Date: Tue, 8 Oct 2024 18:16:35 -0700 Subject: [PATCH 06/12] Fix accidentally added files --- .../project.pbxproj | 4 +++ .../Link/Components/Toast/LinkToast.swift | 7 +++- .../Source/Internal/Link/LinkUI.swift | 33 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj index b430d5bd8d8..048225cdd17 100644 --- a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj +++ b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj @@ -73,6 +73,7 @@ 31CC9BA12CB5F93100E84A38 /* Button+Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA02CB5F93100E84A38 /* Button+Link.swift */; }; 31CC9BA42CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA32CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift */; }; 31CC9BA52CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA22CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift */; }; + 31CC9BA72CB610A300E84A38 /* ConfirmButton+Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31CC9BA62CB610A300E84A38 /* ConfirmButton+Link.swift */; }; 31CDFC362BA8E66200B3DD91 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 31CDFC352BA8E66200B3DD91 /* PrivacyInfo.xcprivacy */; }; 335A19D93A5979557DB4CA4D /* PaymentMethodElementWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5012364ED0F2EEC6EC2AB52 /* PaymentMethodElementWrapper.swift */; }; 34CF08CBC636F596B8BA4C12 /* TextFieldElement+CardTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00C7F5905759525C9BF8BD4 /* TextFieldElement+CardTest.swift */; }; @@ -426,6 +427,7 @@ 31CC9BA02CB5F93100E84A38 /* Button+Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Button+Link.swift"; sourceTree = ""; }; 31CC9BA22CB5F9D400E84A38 /* LinkInstantDebitMandateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkInstantDebitMandateView.swift; sourceTree = ""; }; 31CC9BA32CB5F9D400E84A38 /* LinkKeyboardAvoidingScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkKeyboardAvoidingScrollView.swift; sourceTree = ""; }; + 31CC9BA62CB610A300E84A38 /* ConfirmButton+Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfirmButton+Link.swift"; sourceTree = ""; }; 31CDFC352BA8E66200B3DD91 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 32332E0DB0AE12377EBDDEF1 /* PaymentSheetIntentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentSheetIntentConfiguration.swift; sourceTree = ""; }; 32BDC53A88FB17F378C6B413 /* CardSectionWithScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardSectionWithScannerView.swift; sourceTree = ""; }; @@ -1113,6 +1115,7 @@ isa = PBXGroup; children = ( 31CC9BA02CB5F93100E84A38 /* Button+Link.swift */, + 31CC9BA62CB610A300E84A38 /* ConfirmButton+Link.swift */, EFDE97D76542848E7821BA43 /* FormElement+Link.swift */, 04C8047FD8994D3FAA3D1A7A /* Intent+Link.swift */, FD0EACE5F259BDE586A4A20C /* STPAnalyticsClient+Link.swift */, @@ -1855,6 +1858,7 @@ A4FF52567582E9774AE13348 /* PaymentDetails.swift in Sources */, 3E2279C28944A87EC6472101 /* STPAPIClient+Link.swift in Sources */, B8A7575878C5124CF5482097 /* VerificationSession.swift in Sources */, + 31CC9BA72CB610A300E84A38 /* ConfirmButton+Link.swift in Sources */, 9326393E775D29F8C661624B /* STPAPIClient+PaymentSheet.swift in Sources */, AA3A96D74B1659CB5725E95F /* CardExpiryDate.swift in Sources */, 64DE5688E4FBE92E1F49810C /* ExternalPaymentMethod.swift in Sources */, diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift index 791d9c07ea8..2eac4eac24a 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/Toast/LinkToast.swift @@ -40,8 +40,9 @@ final class LinkToast: UIView { label.font = LinkUI.font(forTextStyle: .detail, maximumPointSize: 20) return label }() - + #if !os(visionOS) private let feedbackGenerator = UINotificationFeedbackGenerator() + #endif /// Creates a new toast. /// - Parameters: @@ -127,7 +128,9 @@ extension LinkToast { } UIAccessibility.post(notification: .announcement, argument: text) + #if !os(visionOS) generateHapticFeedback() + #endif DispatchQueue.main.asyncAfter(deadline: .now() + duration) { self.hide() @@ -154,12 +157,14 @@ extension LinkToast { } } +#if !os(visionOS) private func generateHapticFeedback() { switch toastType { case .success: feedbackGenerator.notificationOccurred(.success) } } +#endif } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/LinkUI.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/LinkUI.swift index 13b9a403aef..671a5704f4f 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/LinkUI.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/LinkUI.swift @@ -143,3 +143,36 @@ extension LinkUI { } } + +// MARK: - Appearance + +extension LinkUI { + + static let appearance: PaymentSheet.Appearance = { + var appearance = PaymentSheet.Appearance.default + appearance.cornerRadius = LinkUI.mediumCornerRadius + appearance.colors.primary = .linkBrandDark + appearance.colors.background = .linkBackground + + // Text + appearance.colors.text = .linkPrimaryText + appearance.colors.textSecondary = .linkSecondaryText + + // Components + appearance.colors.componentText = .linkPrimaryText + appearance.colors.componentPlaceholderText = .linkSecondaryText + appearance.colors.componentBackground = .linkControlBackground + appearance.colors.componentBorder = .linkControlBorder + appearance.colors.componentDivider = .linkSeparator + + // Primary button + appearance.primaryButton.textColor = .linkPrimaryButtonForeground + appearance.primaryButton.backgroundColor = .linkBrand + appearance.primaryButton.borderWidth = 0 + appearance.primaryButton.cornerRadius = LinkUI.cornerRadius + appearance.primaryButton.font = LinkUI.font(forTextStyle: .bodyEmphasized) + + return appearance + }() + +} From d92e0c5449edb2dcccb782b5dbb210a6bb045d05 Mon Sep 17 00:00:00 2001 From: David Estes Date: Wed, 9 Oct 2024 13:51:18 -0700 Subject: [PATCH 07/12] Fix visionOS build --- .../Internal/Link/Views/LinkInstantDebitMandateView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift index 3d8c5f91f08..7ae8ce58ce0 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Views/LinkInstantDebitMandateView.swift @@ -103,6 +103,7 @@ final class LinkInstantDebitMandateView: UIView { extension LinkInstantDebitMandateView: UITextViewDelegate { + #if !os(visionOS) func textView( _ textView: UITextView, shouldInteractWith URL: URL, @@ -115,5 +116,6 @@ extension LinkInstantDebitMandateView: UITextViewDelegate { return false } + #endif } From 3eeced032e157eca9a417c91dba4d1899288538a Mon Sep 17 00:00:00 2001 From: David Estes Date: Wed, 9 Oct 2024 16:20:04 -0700 Subject: [PATCH 08/12] Fix visionOS build --- .../PaymentSheet/Link/ButtonLinkSnapshotTests.swift | 2 -- .../PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift | 2 -- .../Link/LinkInstantDebitMandateViewSnapshotTests.swift | 2 -- .../PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift | 2 -- .../PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift | 2 -- .../PaymentSheet/Link/LinkToastSnapshotTests.swift | 2 -- .../Snapshot/Controls/ButtonSnapshotTest.swift | 1 - 7 files changed, 13 deletions(-) diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift index da3811b5c9b..949626c18e7 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/ButtonLinkSnapshotTests.swift @@ -6,11 +6,9 @@ // Copyright © 2022 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils import UIKit -@testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripeUICore diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift index 5de42b388a2..8aaef64aa83 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkBadgeViewSnapshotTest.swift @@ -6,11 +6,9 @@ // Copyright © 2022 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils import UIKit -@testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePayments @testable@_spi(STP) import StripePaymentSheet diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift index d528416d7a8..88d2bbeb569 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkInstantDebitMandateViewSnapshotTests.swift @@ -6,11 +6,9 @@ // Copyright © 2022 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils import UIKit -@testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePayments @testable@_spi(STP) import StripePaymentSheet diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift index 5da577d7d35..23709ecff5c 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNavigationBarSnapshotTests.swift @@ -6,11 +6,9 @@ // Copyright © 2022 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils import UIKit -@testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePayments @testable@_spi(STP) import StripePaymentSheet diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift index f02bd0bd573..6175c1aa68a 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkNoticeViewSnapshotTests.swift @@ -6,11 +6,9 @@ // Copyright © 2022 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils import UIKit -@testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePayments @testable@_spi(STP) import StripePaymentSheet diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift index 670ba43c5b5..e3163848d86 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkToastSnapshotTests.swift @@ -6,11 +6,9 @@ // Copyright © 2021 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils import UIKit -@testable@_spi(STP) import Stripe @testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePayments @testable@_spi(STP) import StripePaymentSheet diff --git a/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift b/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift index accbce379ab..3e0ec2a7171 100644 --- a/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift +++ b/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift @@ -6,7 +6,6 @@ // Copyright © 2021 Stripe, Inc. All rights reserved. // -import iOSSnapshotTestCase import StripeCoreTestUtils @_spi(STP) import StripeUICore From ff7b4f26077099b15b95d5ce2768dd8d31123889 Mon Sep 17 00:00:00 2001 From: David Estes Date: Wed, 9 Oct 2024 17:05:42 -0700 Subject: [PATCH 09/12] Fix visionOS build --- .../StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift b/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift index 3e0ec2a7171..e0db6c7c2ef 100644 --- a/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift +++ b/StripeUICore/StripeUICoreTests/Snapshot/Controls/ButtonSnapshotTest.swift @@ -8,6 +8,7 @@ import StripeCoreTestUtils @_spi(STP) import StripeUICore +import UIKit final class ButtonSnapshotTest: STPSnapshotTestCase { From e69c8a6c68235a5aad946a999916010b3bcb7bdb Mon Sep 17 00:00:00 2001 From: David Estes Date: Thu, 10 Oct 2024 14:54:02 -0700 Subject: [PATCH 10/12] Re-add link data model --- .../EmbeddedPlaygroundViewController.swift | 32 +- .../PayWithLinkButtonSnapshotTests.swift | 6 +- .../Source/Analytics/STPAnalyticEvent.swift | 7 + .../project.pbxproj | 24 ++ .../en.lproj/Localizable.strings | 16 + .../Source/Categories/String+Localized.swift | 10 + .../Helpers/PaymentSheetLinkAccount.swift | 287 +++++++++++++++++- .../Link/ConsumerSession+PublishableKey.swift | 5 +- .../API Bindings/Link/ConsumerSession.swift | 111 ++++++- .../Link/CookieStore/LinkCookieStore.swift | 43 +++ .../CookieStore/LinkInMemoryCookieStore.swift | 24 ++ .../CookieStore/LinkSecureCookieStore.swift | 103 +++++++ .../API Bindings/Link/PaymentDetails.swift | 216 ++++++++++++- .../API Bindings/Link/STPAPIClient+Link.swift | 177 ++++++++++- .../NavigationBar/LinkNavigationBar.swift | 4 +- .../Link/Extensions/Intent+Link.swift | 4 + .../Extensions/STPAnalyticsClient+Link.swift | 22 ++ .../Link/Services/LinkAccountService.swift | 20 +- .../Link/Verification/LinkCookieKey.swift | 2 +- .../Link/Verification/LinkUtils.swift | 51 ++++ .../Embedded/EmbeddedPaymentElement.swift | 4 +- .../Link/PaymentSheet-LinkConfirmOption.swift | 28 +- .../PaymentSheet/PaymentSheet+API.swift | 6 + ...ymentSheet+PaymentMethodAvailability.swift | 6 + .../PaymentSheetConfiguration.swift | 3 + .../SavedPaymentOptionsViewController.swift | 10 + .../PaymentSheetViewController.swift | 4 + .../PaymentSheet/Views/ConfirmButton.swift | 34 ++- .../Views/PayWithLinkButton.swift | 8 +- .../PaymentSheet/LinkStubs.swift | 44 ++- .../PaymentSheetLinkAccountTests.swift | 4 +- .../testWithEmailAddress@3x.png | Bin 8480 -> 16273 bytes .../testWithLongEmailAddress@3x.png | Bin 8480 -> 19922 bytes 33 files changed, 1269 insertions(+), 46 deletions(-) create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkCookieStore.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkInMemoryCookieStore.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkSecureCookieStore.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkUtils.swift diff --git a/Example/PaymentSheet Example/PaymentSheet Example/EmbeddedPlaygroundViewController.swift b/Example/PaymentSheet Example/PaymentSheet Example/EmbeddedPlaygroundViewController.swift index 378131fcdd3..ffc8e04d3a8 100644 --- a/Example/PaymentSheet Example/PaymentSheet Example/EmbeddedPlaygroundViewController.swift +++ b/Example/PaymentSheet Example/PaymentSheet Example/EmbeddedPlaygroundViewController.swift @@ -33,7 +33,7 @@ class EmbeddedPlaygroundViewController: UIViewController { checkoutButton.translatesAutoresizingMaskIntoConstraints = false return checkoutButton }() - + private let paymentOptionView = EmbeddedPaymentOptionView() init(configuration: EmbeddedPaymentElement.Configuration, intentConfig: PaymentSheet.IntentConfiguration, appearance: PaymentSheet.Appearance) { @@ -94,7 +94,7 @@ class EmbeddedPlaygroundViewController: UIViewController { checkoutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), checkoutButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20), ]) - + paymentOptionView.configure(with: embeddedPaymentElement.paymentOption, showMandate: !configuration.embeddedViewDisplaysMandateText) } @@ -123,15 +123,14 @@ extension EmbeddedPlaygroundViewController: EmbeddedPaymentElementDelegate { self.view.setNeedsLayout() self.view.layoutIfNeeded() } - + func embeddedPaymentElementDidUpdatePaymentOption(embeddedPaymentElement: EmbeddedPaymentElement) { paymentOptionView.configure(with: embeddedPaymentElement.paymentOption, showMandate: !configuration.embeddedViewDisplaysMandateText) } } - private class EmbeddedPaymentOptionView: UIView { - + private let titleLabel: UILabel = { let label = UILabel() label.font = .preferredFont(forTextStyle: .body) @@ -140,14 +139,14 @@ private class EmbeddedPaymentOptionView: UIView { label.text = "Selected payment method" return label }() - + private let imageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit imageView.translatesAutoresizingMaskIntoConstraints = false return imageView }() - + private let label: UILabel = { let label = UILabel() label.font = .preferredFont(forTextStyle: .subheadline) @@ -155,7 +154,7 @@ private class EmbeddedPaymentOptionView: UIView { label.translatesAutoresizingMaskIntoConstraints = false return label }() - + private let mandateTextLabel: UILabel = { let mandateLabel = UILabel() mandateLabel.font = .preferredFont(forTextStyle: .footnote) @@ -165,45 +164,45 @@ private class EmbeddedPaymentOptionView: UIView { mandateLabel.textAlignment = .left return mandateLabel }() - + override init(frame: CGRect) { super.init(frame: frame) setupView() } - + required init?(coder: NSCoder) { super.init(coder: coder) setupView() } - + private func setupView() { addSubview(titleLabel) addSubview(imageView) addSubview(label) addSubview(mandateTextLabel) - + NSLayoutConstraint.activate([ titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 15), titleLabel.topAnchor.constraint(equalTo: self.topAnchor), titleLabel.widthAnchor.constraint(equalTo: self.widthAnchor), titleLabel.heightAnchor.constraint(equalToConstant: 25), - + imageView.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor), imageView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20), imageView.widthAnchor.constraint(equalToConstant: 25), imageView.heightAnchor.constraint(equalToConstant: 25), - + label.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 12), label.trailingAnchor.constraint(equalTo: self.trailingAnchor), label.topAnchor.constraint(equalTo: self.topAnchor), label.centerYAnchor.constraint(equalTo: imageView.centerYAnchor), - + mandateTextLabel.leadingAnchor.constraint(equalTo: imageView.leadingAnchor), mandateTextLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -12), mandateTextLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 12), ]) } - + func configure(with data: EmbeddedPaymentElement.PaymentOptionDisplayData?, showMandate: Bool) { titleLabel.isHidden = data == nil imageView.image = data?.image @@ -212,4 +211,3 @@ private class EmbeddedPaymentOptionView: UIView { mandateTextLabel.isHidden = !showMandate } } - diff --git a/Stripe/StripeiOSTests/PayWithLinkButtonSnapshotTests.swift b/Stripe/StripeiOSTests/PayWithLinkButtonSnapshotTests.swift index 7792c569d3c..2b5cb94c0a8 100644 --- a/Stripe/StripeiOSTests/PayWithLinkButtonSnapshotTests.swift +++ b/Stripe/StripeiOSTests/PayWithLinkButtonSnapshotTests.swift @@ -86,12 +86,16 @@ extension PayWithLinkButtonSnapshotTests { fileprivate struct LinkAccountStub: PaymentSheetLinkAccountInfoProtocol { let email: String let isRegistered: Bool + var redactedPhoneNumber: String? + var isLoggedIn: Bool } fileprivate func makeAccountStub(email: String, isRegistered: Bool) -> LinkAccountStub { return LinkAccountStub( email: email, - isRegistered: isRegistered + isRegistered: isRegistered, + redactedPhoneNumber: "+1********55", + isLoggedIn: true ) } diff --git a/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift b/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift index 6e0d0d4233f..bcc4d84a402 100644 --- a/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift +++ b/StripeCore/StripeCore/Source/Analytics/STPAnalyticEvent.swift @@ -135,6 +135,13 @@ import Foundation case linkPopupError = "link.popup.error" case linkPopupLogout = "link.popup.logout" + // MARK: - Link 2FA + case link2FAStart = "link.2fa.start" + case link2FAStartFailure = "link.2fa.start_failure" + case link2FAComplete = "link.2fa.complete" + case link2FACancel = "link.2fa.cancel" + case link2FAFailure = "link.2fa.failure" + // MARK: - Link Misc case linkAccountLookupComplete = "link.account_lookup.complete" case linkAccountLookupFailure = "link.account_lookup.failure" diff --git a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj index 02ef12cac44..7c4516ab29d 100644 --- a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj +++ b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj @@ -54,6 +54,10 @@ 2EDF4115FDC40A5B0672CCFD /* Locale+Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5DCF73BEC0CC35D4CE30361 /* Locale+Link.swift */; }; 311AC53D6C76953E9B70148A /* ConsumerSession+PublishableKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D61B52BFA201D25E8F6428 /* ConsumerSession+PublishableKey.swift */; }; 313F5F832B0BE5FD00BD98A9 /* Docs.docc in Sources */ = {isa = PBXBuildFile; fileRef = 313F5F822B0BE5FD00BD98A9 /* Docs.docc */; }; + 3147CEBB2CC07E960067B5E4 /* LinkUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBA2CC07E960067B5E4 /* LinkUtils.swift */; }; + 3147CEC02CC080570067B5E4 /* LinkInMemoryCookieStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBD2CC080570067B5E4 /* LinkInMemoryCookieStore.swift */; }; + 3147CEC12CC080570067B5E4 /* LinkCookieStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBC2CC080570067B5E4 /* LinkCookieStore.swift */; }; + 3147CEC22CC080570067B5E4 /* LinkSecureCookieStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBE2CC080570067B5E4 /* LinkSecureCookieStore.swift */; }; 31699A812BE183B30048677F /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31699A802BE183B30048677F /* DownloadManager.swift */; }; 31699A832BE183D40048677F /* DownloadManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31699A822BE183D40048677F /* DownloadManagerTest.swift */; }; 316B33122B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 316B33112B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift */; }; @@ -420,6 +424,10 @@ 2E2B99961C09E31383C9FCE9 /* mt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mt; path = mt.lproj/Localizable.strings; sourceTree = ""; }; 2E42F31D392C0AED757D6239 /* StripePaymentSheet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripePaymentSheet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 313F5F822B0BE5FD00BD98A9 /* Docs.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = Docs.docc; sourceTree = ""; }; + 3147CEBA2CC07E960067B5E4 /* LinkUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkUtils.swift; sourceTree = ""; }; + 3147CEBC2CC080570067B5E4 /* LinkCookieStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkCookieStore.swift; sourceTree = ""; }; + 3147CEBD2CC080570067B5E4 /* LinkInMemoryCookieStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkInMemoryCookieStore.swift; sourceTree = ""; }; + 3147CEBE2CC080570067B5E4 /* LinkSecureCookieStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkSecureCookieStore.swift; sourceTree = ""; }; 3168698F2C61B0F5EC1240FE /* sl-SI */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sl-SI"; path = "sl-SI.lproj/Localizable.strings"; sourceTree = ""; }; 31699A802BE183B30048677F /* DownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManager.swift; sourceTree = ""; }; 31699A822BE183D40048677F /* DownloadManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManagerTest.swift; sourceTree = ""; }; @@ -818,6 +826,16 @@ path = AddressViewController; sourceTree = ""; }; + 3147CEBF2CC080570067B5E4 /* CookieStore */ = { + isa = PBXGroup; + children = ( + 3147CEBC2CC080570067B5E4 /* LinkCookieStore.swift */, + 3147CEBD2CC080570067B5E4 /* LinkInMemoryCookieStore.swift */, + 3147CEBE2CC080570067B5E4 /* LinkSecureCookieStore.swift */, + ); + path = CookieStore; + sourceTree = ""; + }; 319DFD940EAA6EA0A0F4E771 /* Services */ = { isa = PBXGroup; children = ( @@ -1036,6 +1054,7 @@ D0CE026F53D10DA10D7BC4E7 /* ConsumerSession.swift */, 4208AD2E0A737F5E0F00DE48 /* ConsumerSession+LookupResponse.swift */, E2D61B52BFA201D25E8F6428 /* ConsumerSession+PublishableKey.swift */, + 3147CEBF2CC080570067B5E4 /* CookieStore */, 981F958E99945A0318D47BBF /* PaymentDetails.swift */, F1E614E8481658A027599A92 /* STPAPIClient+Link.swift */, B662953D2C63F6C2007B6B14 /* PaymentDetailsShareResponse.swift */, @@ -1203,6 +1222,7 @@ isa = PBXGroup; children = ( B02DD1BA93CC92A187051B2F /* LinkAccountContext.swift */, + 3147CEBA2CC07E960067B5E4 /* LinkUtils.swift */, A1928BE9DFF116368B1A19DC /* LinkCookieKey.swift */, ); path = Verification; @@ -1925,6 +1945,9 @@ F3A34AD1CC2CBB899738C9D7 /* LinkInlineSignupElement.swift in Sources */, 56BB7C81AB3A24D3AD88A904 /* LinkInlineSignupView-CheckboxElement.swift in Sources */, 7479F814D1BC58A6B19F054C /* LinkInlineSignupView.swift in Sources */, + 3147CEC02CC080570067B5E4 /* LinkInMemoryCookieStore.swift in Sources */, + 3147CEC12CC080570067B5E4 /* LinkCookieStore.swift in Sources */, + 3147CEC22CC080570067B5E4 /* LinkSecureCookieStore.swift in Sources */, 258A75AF2E5393186C8850CA /* LinkEmailElement.swift in Sources */, EDE71E0BEDD94FB1101F3C10 /* FormElement+Link.swift in Sources */, C346B534D57A952D4415ADFD /* Intent+Link.swift in Sources */, @@ -2054,6 +2077,7 @@ B8A217F26AAEC592B9B0D2E1 /* CardScanButton.swift in Sources */, 436A212E364FD78C3745DDA3 /* CardScanningView.swift in Sources */, 19A6D9D9951E13377F305263 /* CircularButton.swift in Sources */, + 3147CEBB2CC07E960067B5E4 /* LinkUtils.swift in Sources */, 6BA8D33A2B0C1FBF008C51FF /* CVCPaymentMethodInformationView.swift in Sources */, B662953E2C63F6C2007B6B14 /* PaymentDetailsShareResponse.swift in Sources */, F79DBDF42E5C0ED6B6DDC246 /* ConfirmButton.swift in Sources */, diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings index 9014be8bf2d..2aef5ceb3da 100644 --- a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings +++ b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings @@ -10,6 +10,9 @@ /* Text for a button that, when tapped, displays another screen where the customer can add a new payment method */ "Add a payment method" = "Add a payment method"; +/* Button prompt to add a bank account as a payment method. */ +"Add bank account" = "Add bank account"; + /* Title shown above a view allowing the customer to save their first card. */ "Add card" = "Add card"; @@ -287,9 +290,22 @@ is not supported by the merchant */ /* An error message. */ "The IBAN you entered is invalid, \"%@\" is not a supported country code." = "The IBAN you entered is invalid, \"%@\" is not a supported country code."; +/* Error message shown when the user enters an expired verification code. */ +"The provided verification code has expired." = "The provided verification code has expired."; + +/* Error message shown when the user enters an incorrect verification code. */ +"The provided verification code is incorrect." = "The provided verification code is incorrect."; + +/* Error message shown when the user enters an incorrect verification code too many times. */ +"Too many attempts. Please try again in a few minutes." = "Too many attempts. Please try again in a few minutes."; + /* Title for a button that when tapped, updates a card brand. */ "Update" = "Update"; +/* Title for a button that when tapped, presents a screen for updating a card. Also +the heading the screen itself. */ +"Update card" = "Update card"; + /* Title for a screen for updating a card brand. */ "Update card brand" = "Update card brand"; diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Categories/String+Localized.swift b/StripePaymentSheet/StripePaymentSheet/Source/Categories/String+Localized.swift index 1b992c75128..3aa38c5aee7 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Categories/String+Localized.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Categories/String+Localized.swift @@ -73,6 +73,16 @@ extension String.Localized { STPLocalizedString("Back", "Text for back button") } + static var update_card: String { + STPLocalizedString( + "Update card", + """ + Title for a button that when tapped, presents a screen for updating a card. Also + the heading the screen itself. + """ + ) + } + static var update_card_brand: String { STPLocalizedString( "Update card brand", diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Helpers/PaymentSheetLinkAccount.swift b/StripePaymentSheet/StripePaymentSheet/Source/Helpers/PaymentSheetLinkAccount.swift index 8fb136865da..976fb8091b5 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Helpers/PaymentSheetLinkAccount.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Helpers/PaymentSheetLinkAccount.swift @@ -13,7 +13,9 @@ import UIKit protocol PaymentSheetLinkAccountInfoProtocol { var email: String { get } + var redactedPhoneNumber: String? { get } var isRegistered: Bool { get } + var isLoggedIn: Bool { get } } struct LinkPMDisplayDetails { @@ -49,12 +51,17 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol { // Dependencies let apiClient: STPAPIClient + let cookieStore: LinkCookieStore /// Publishable key of the Consumer Account. private(set) var publishableKey: String? let email: String + var redactedPhoneNumber: String? { + return currentSession?.redactedPhoneNumber + } + var isRegistered: Bool { return currentSession != nil } @@ -83,12 +90,14 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol { email: String, session: ConsumerSession?, publishableKey: String?, - apiClient: STPAPIClient = .shared + apiClient: STPAPIClient = .shared, + cookieStore: LinkCookieStore = LinkSecureCookieStore.shared ) { self.email = email self.currentSession = session self.publishableKey = publishableKey self.apiClient = apiClient + self.cookieStore = cookieStore } func signUp( @@ -144,6 +153,96 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol { } } + func startVerification(completion: @escaping (Result) -> Void) { + guard case .requiresVerification = sessionState else { + DispatchQueue.main.async { + completion(.success(false)) + } + return + } + + guard let session = currentSession else { + assertionFailure() + DispatchQueue.main.async { + completion( + .failure( + PaymentSheetError.unknown(debugDescription: "Don't call verify if not needed") + ) + ) + } + return + } + + session.startVerification( + with: apiClient, + cookieStore: cookieStore, + consumerAccountPublishableKey: publishableKey + ) { [weak self] result in + switch result { + case .success(let newSession): + self?.currentSession = newSession + completion(.success(newSession.hasStartedSMSVerification)) + case .failure(let error): + completion(.failure(error)) + } + } + } + + func verify(with oneTimePasscode: String, completion: @escaping (Result) -> Void) { + guard case .requiresVerification = sessionState, + hasStartedSMSVerification, + let session = currentSession + else { + assertionFailure() + DispatchQueue.main.async { + completion( + .failure( + PaymentSheetError.unknown(debugDescription: "Don't call verify if not needed") + ) + ) + } + return + } + + session.confirmSMSVerification( + with: oneTimePasscode, + with: apiClient, + cookieStore: cookieStore, + consumerAccountPublishableKey: publishableKey + ) { [weak self] result in + switch result { + case .success(let verifiedSession): + self?.currentSession = verifiedSession + completion(.success(())) + case .failure(let error): + completion(.failure(error)) + } + } + } + + func createLinkAccountSession( + completion: @escaping (Result) -> Void + ) { + guard let session = currentSession else { + assertionFailure() + completion( + .failure( + PaymentSheetError.unknown( + debugDescription: "Linking account session without valid consumer session" + ) + ) + ) + return + } + + retryingOnAuthError(completion: completion) { [publishableKey] completionWrapper in + session.createLinkAccountSession( + consumerAccountPublishableKey: publishableKey, + completion: completionWrapper + ) + } + } + func createPaymentDetails( with paymentMethodParams: STPPaymentMethodParams, completion: @escaping (Result) -> Void @@ -166,6 +265,91 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol { } } + func createPaymentDetails( + linkedAccountId: String, + completion: @escaping (Result) -> Void + ) { + guard let session = currentSession else { + assertionFailure() + completion(.failure(PaymentSheetError.unknown(debugDescription: "Saving to Link without valid session"))) + return + } + retryingOnAuthError(completion: completion) { [publishableKey] completionWrapper in + session.createPaymentDetails( + linkedAccountId: linkedAccountId, + consumerAccountPublishableKey: publishableKey, + completion: completionWrapper + ) + } + } + + func listPaymentDetails( + completion: @escaping (Result<[ConsumerPaymentDetails], Error>) -> Void + ) { + guard let session = currentSession else { + assertionFailure() + completion(.failure(PaymentSheetError.unknown(debugDescription: "Paying with Link without valid session"))) + return + } + + retryingOnAuthError(completion: completion) { [apiClient, publishableKey] completionWrapper in + session.listPaymentDetails( + with: apiClient, + consumerAccountPublishableKey: publishableKey, + completion: completionWrapper + ) + } + } + + func deletePaymentDetails(id: String, completion: @escaping (Result) -> Void) { + guard let session = currentSession else { + assertionFailure() + return completion( + .failure( + PaymentSheetError.unknown( + debugDescription: "Deleting Link payment details without valid session" + ) + ) + ) + } + + retryingOnAuthError(completion: completion) { [apiClient, publishableKey] completionWrapper in + session.deletePaymentDetails( + with: apiClient, + id: id, + consumerAccountPublishableKey: publishableKey, + completion: completionWrapper + ) + } + } + + func updatePaymentDetails( + id: String, + updateParams: UpdatePaymentDetailsParams, + completion: @escaping (Result) -> Void + ) { + guard let session = currentSession else { + assertionFailure() + return completion( + .failure( + PaymentSheetError.unknown( + debugDescription: "Updating Link payment details without valid session" + ) + ) + ) + } + + retryingOnAuthError(completion: completion) { [apiClient, publishableKey] completionWrapper in + session.updatePaymentDetails( + with: apiClient, + id: id, + updateParams: updateParams, + consumerAccountPublishableKey: publishableKey, + completion: completionWrapper + ) + } + } + func sharePaymentDetails(id: String, cvc: String?, completion: @escaping (Result) -> Void) { guard let session = currentSession else { assertionFailure() @@ -195,6 +379,14 @@ class PaymentSheetLinkAccount: PaymentSheetLinkAccountInfoProtocol { // We don't need to do anything if this fails, the key will expire automatically. } } + + func markEmailAsLoggedOut() { + guard let hashedEmail = email.lowercased().sha256 else { + return + } + + cookieStore.write(key: .lastLogoutEmail, value: hashedEmail) + } } // MARK: - Equatable @@ -307,3 +499,96 @@ extension PaymentSheetLinkAccount { return params } } + +// MARK: - Payment method availability + +extension PaymentSheetLinkAccount { + + /// Returns a set containing the Payment Details types that the user is able to use for confirming the given `intent`. + /// - Parameter intent: The Intent that the user is trying to confirm. + /// - Returns: A set containing the supported Payment Details types. + func supportedPaymentDetailsTypes(for elementsSession: STPElementsSession) -> Set { + guard let currentSession = currentSession, let fundingSources = elementsSession.linkFundingSources else { + return [] + } + + let fundingSourceDetailsTypes = Set(fundingSources.compactMap { $0.detailsType }) + + // Take the intersection of the consumer session types and the merchant-provided Link funding sources + var supportedPaymentDetailsTypes = fundingSourceDetailsTypes.intersection(currentSession.supportedPaymentDetailsTypes) + + // Special testmode handling + if apiClient.isTestmode && Self.emailSupportsMultipleFundingSourcesOnTestMode(email) { + supportedPaymentDetailsTypes.insert(.bankAccount) + } + + return supportedPaymentDetailsTypes + } + + func supportedPaymentMethodTypes(for elementsSession: STPElementsSession) -> [STPPaymentMethodType] { + var supportedPaymentMethodTypes = [STPPaymentMethodType]() + + for paymentDetailsType in supportedPaymentDetailsTypes(for: elementsSession) { + switch paymentDetailsType { + case .card: + supportedPaymentMethodTypes.append(.card) + case .bankAccount: + break +// TODO(link): Fix instant debits +// supportedPaymentMethodTypes.append(.instantDebits) + case .unparsable: + break + } + } + + if supportedPaymentMethodTypes.isEmpty { + // Card is the default payment method type when no other type is available. + supportedPaymentMethodTypes.append(.card) + } + + return supportedPaymentMethodTypes + } +} + +// MARK: - Helpers + +private extension PaymentSheetLinkAccount { + + /// On *testmode* we use special email addresses for testing multiple funding sources. This method returns `true` + /// if the given `email` is one of such email addresses. + /// + /// - Parameter email: Email. + /// - Returns: Whether or not should enable multiple funding sources on test mode. + static func emailSupportsMultipleFundingSourcesOnTestMode(_ email: String) -> Bool { + return email.contains("+multiple_funding_sources@") + } + +} + +private extension LinkSettings.FundingSource { + var detailsType: ConsumerPaymentDetails.DetailsType? { + switch self { + case .card: + return .card + case .bankAccount: + return .bankAccount + } + } +} + +// MARK: UpdatePaymentDetailsParams + +struct UpdatePaymentDetailsParams { + enum DetailsType { + case card(expiryDate: CardExpiryDate, billingDetails: STPPaymentMethodBillingDetails? = nil) + // updating bank not supported + } + + let isDefault: Bool? + let details: DetailsType? + + init(isDefault: Bool? = nil, details: DetailsType? = nil) { + self.isDefault = isDefault + self.details = details + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession+PublishableKey.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession+PublishableKey.swift index a8d8bf84426..227950a10e2 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession+PublishableKey.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession+PublishableKey.swift @@ -12,13 +12,16 @@ extension ConsumerSession { final class SessionWithPublishableKey: Decodable { let consumerSession: ConsumerSession let publishableKey: String + let authSessionClientSecret: String? init( consumerSession: ConsumerSession, - publishableKey: String + publishableKey: String, + authSessionClientSecret: String? = nil ) { self.consumerSession = consumerSession self.publishableKey = publishableKey + self.authSessionClientSecret = authSessionClientSecret } } } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession.swift index ee6fb7f5a3d..06ec7299803 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/ConsumerSession.swift @@ -15,29 +15,39 @@ import UIKit final class ConsumerSession: Decodable { let clientSecret: String let emailAddress: String + let redactedPhoneNumber: String let verificationSessions: [VerificationSession] + let supportedPaymentDetailsTypes: Set init( clientSecret: String, emailAddress: String, - verificationSessions: [VerificationSession] + redactedPhoneNumber: String, + verificationSessions: [VerificationSession], + supportedPaymentDetailsTypes: Set ) { self.clientSecret = clientSecret self.emailAddress = emailAddress + self.redactedPhoneNumber = redactedPhoneNumber self.verificationSessions = verificationSessions + self.supportedPaymentDetailsTypes = supportedPaymentDetailsTypes } private enum CodingKeys: String, CodingKey { case clientSecret case emailAddress + case redactedPhoneNumber case verificationSessions + case supportedPaymentDetailsTypes = "supportPaymentDetailsTypes" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.clientSecret = try container.decode(String.self, forKey: .clientSecret) self.emailAddress = try container.decode(String.self, forKey: .emailAddress) + self.redactedPhoneNumber = try container.decode(String.self, forKey: .redactedPhoneNumber) self.verificationSessions = try container.decodeIfPresent([ConsumerSession.VerificationSession].self, forKey: .verificationSessions) ?? [] + self.supportedPaymentDetailsTypes = try container.decodeIfPresent(Set.self, forKey: .supportedPaymentDetailsTypes) ?? [] } } @@ -69,9 +79,10 @@ extension ConsumerSession { class func lookupSession( for email: String?, with apiClient: STPAPIClient = STPAPIClient.shared, + cookieStore: LinkCookieStore = LinkSecureCookieStore.shared, completion: @escaping (Result) -> Void ) { - apiClient.lookupConsumerSession(for: email, completion: completion) + apiClient.lookupConsumerSession(for: email, cookieStore: cookieStore, completion: completion) } class func signUp( @@ -124,6 +135,100 @@ extension ConsumerSession { completion: completion) } + func createPaymentDetails( + linkedAccountId: String, + with apiClient: STPAPIClient = STPAPIClient.shared, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + apiClient.createPaymentDetails( + for: clientSecret, + linkedAccountId: linkedAccountId, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + + func startVerification( + type: VerificationSession.SessionType = .sms, + locale: Locale = .autoupdatingCurrent, + with apiClient: STPAPIClient = STPAPIClient.shared, + cookieStore: LinkCookieStore = LinkSecureCookieStore.shared, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + apiClient.startVerification( + for: clientSecret, + type: type, + locale: locale, + cookieStore: cookieStore, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + + func confirmSMSVerification( + with code: String, + with apiClient: STPAPIClient = STPAPIClient.shared, + cookieStore: LinkCookieStore = LinkSecureCookieStore.shared, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + apiClient.confirmSMSVerification( + for: clientSecret, + with: code, + cookieStore: cookieStore, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + + func createLinkAccountSession( + with apiClient: STPAPIClient = STPAPIClient.shared, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + apiClient.createLinkAccountSession( + for: clientSecret, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + + func listPaymentDetails( + with apiClient: STPAPIClient = STPAPIClient.shared, + consumerAccountPublishableKey: String?, + completion: @escaping (Result<[ConsumerPaymentDetails], Error>) -> Void + ) { + apiClient.listPaymentDetails( + for: clientSecret, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + + func deletePaymentDetails( + with apiClient: STPAPIClient = STPAPIClient.shared, + id: String, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + apiClient.deletePaymentDetails( + for: clientSecret, + id: id, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + + func updatePaymentDetails( + with apiClient: STPAPIClient = STPAPIClient.shared, + id: String, + updateParams: UpdatePaymentDetailsParams, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + apiClient.updatePaymentDetails( + for: clientSecret, id: id, + updateParams: updateParams, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion) + } + func sharePaymentDetails( with apiClient: STPAPIClient = STPAPIClient.shared, id: String, @@ -141,11 +246,13 @@ extension ConsumerSession { func logout( with apiClient: STPAPIClient = STPAPIClient.shared, + cookieStore: LinkCookieStore = LinkSecureCookieStore.shared, consumerAccountPublishableKey: String?, completion: @escaping (Result) -> Void ) { apiClient.logout( consumerSessionClientSecret: clientSecret, + cookieStore: cookieStore, consumerAccountPublishableKey: consumerAccountPublishableKey, completion: completion) } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkCookieStore.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkCookieStore.swift new file mode 100644 index 00000000000..c484191d33a --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkCookieStore.swift @@ -0,0 +1,43 @@ +// +// LinkCookieStore.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 12/21/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +/// A protocol that cookie storage objects should conform to. +/// +/// Provides an interface for basic CRUD functionality. +protocol LinkCookieStore { + /// Writes a cookie to the store. + /// - Parameters: + /// - key: Cookie identifier. + /// - value: Cookie value. + /// - allowSync: True if this cookie should be sync'd across devices + func write(key: LinkCookieKey, value: String, allowSync: Bool) + + /// Retrieves a cookie by key. + /// - Parameter key: Cookie identifier. + /// - Returns: The cookie value, or `nil` if it doesn't exist. + func read(key: LinkCookieKey) -> String? + + /// Deletes a stored cookie identified by key. + /// - Parameter key: Cookie identifier. + func delete(key: LinkCookieKey) +} + +extension LinkCookieStore { + func write(key: LinkCookieKey, value: String) { + self.write(key: key, value: value, allowSync: false) + } +} + +// MARK: - Helpers + +extension LinkCookieStore { + func clear() { + delete(key: .lastLogoutEmail) + delete(key: .lastSignupEmail) + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkInMemoryCookieStore.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkInMemoryCookieStore.swift new file mode 100644 index 00000000000..96a81d90834 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkInMemoryCookieStore.swift @@ -0,0 +1,24 @@ +// +// LinkInMemoryCookieStore.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 12/21/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +/// In-memory cookie store. +final class LinkInMemoryCookieStore: LinkCookieStore { + private var data: [LinkCookieKey: String] = [:] + + func write(key: LinkCookieKey, value: String, allowSync: Bool) { + data[key] = value + } + + func read(key: LinkCookieKey) -> String? { + return data[key] + } + + func delete(key: LinkCookieKey) { + data.removeValue(forKey: key) + } +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkSecureCookieStore.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkSecureCookieStore.swift new file mode 100644 index 00000000000..63df889ea6b --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/CookieStore/LinkSecureCookieStore.swift @@ -0,0 +1,103 @@ +// +// LinkSecureCookieStore.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 12/21/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import Foundation +import Security + +/// A secure cookie store backed by Keychain. +final class LinkSecureCookieStore: LinkCookieStore { + + static let shared: LinkSecureCookieStore = .init() + + private init() {} + + func write(key: LinkCookieKey, value: String, allowSync: Bool) { + guard let data = value.data(using: .utf8) else { + return + } + + let query = queryForKey(key, additionalParams: [ + kSecValueData as String: data, + kSecAttrSynchronizable as String: allowSync ? kCFBooleanTrue as Any : kCFBooleanFalse as Any, + ]) + + delete(key: key) + let status = SecItemAdd(query as CFDictionary, nil) + assert( + status == noErr || status == errSecDuplicateItem, + "Unexpected status code \(status)" + ) + + if status == errSecDuplicateItem { + let updateQuery = queryForKey(key) + let updatedValue: [String: Any] = [kSecValueData as String: data] + let status = SecItemUpdate(updateQuery as CFDictionary, updatedValue as CFDictionary) + assert(status == noErr, "Unexpected status code \(status)") + } + } + + func read(key: LinkCookieKey) -> String? { + let query = queryForKey(key, additionalParams: [ + kSecReturnData as String: kCFBooleanTrue as Any, + kSecMatchLimit as String: kSecMatchLimitOne, + kSecAttrSynchronizable as String: kSecAttrSynchronizableAny, + ]) + + var result: AnyObject? + + let status = SecItemCopyMatching(query as CFDictionary, &result) + // Disable this check for UI tests + + assert( + status == noErr || status == errSecItemNotFound, + "Unexpected status code \(status)" + ) + + guard + status == noErr, + let data = result as? Data + else { + return nil + } + + return String(data: data, encoding: .utf8) + } + + func delete(key: LinkCookieKey) { + let query = queryForKey(key, additionalParams: [ + kSecAttrSynchronizable as String: kSecAttrSynchronizableAny + ]) + + let status = SecItemDelete(query as CFDictionary) + assert( + status == noErr || status == errSecItemNotFound, + "Unexpected status code \(status)" + ) + } + + private func queryForKey( + _ key: LinkCookieKey, + additionalParams: [String: Any]? = nil + ) -> [String: Any] { + // This must be unique across apps OR the apps must share + // a keychain access group. To be safe, we'll partition it + // by bundle ID. + let accountId = "STP-\(Bundle.main.bundleIdentifier ?? "")-\(key.rawValue)" + var query = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrAccount as String: accountId, + ] as [String: Any] + + additionalParams?.forEach({ (key, value) in + query[key] = value + }) + + return query + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/PaymentDetails.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/PaymentDetails.swift index 20897763728..052d7681118 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/PaymentDetails.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/PaymentDetails.swift @@ -20,17 +20,231 @@ typealias ConsumerSessionWithPaymentDetails = (session: ConsumerSession, payment */ final class ConsumerPaymentDetails: Decodable { let stripeID: String + let details: Details + var isDefault: Bool - init(stripeID: String) { + // TODO(csabol) : Billing address + + init(stripeID: String, + details: Details, + isDefault: Bool) { self.stripeID = stripeID + self.details = details + self.isDefault = isDefault } private enum CodingKeys: String, CodingKey { case stripeID = "id" + case isDefault } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.stripeID = try container.decode(String.self, forKey: .stripeID) + // The payment details are included in the dictionary, so we pass the whole dict to Details + self.details = try decoder.singleValueContainer().decode(Details.self) + self.isDefault = try container.decode(Bool.self, forKey: .isDefault) + } +} + +// MARK: - Details +/// :nodoc: +extension ConsumerPaymentDetails { + enum DetailsType: String, CaseIterable, SafeEnumCodable { + case card = "CARD" + case bankAccount = "BANK_ACCOUNT" + case unparsable = "" + } + + enum Details: SafeEnumDecodable { + case card(card: Card) + case bankAccount(bankAccount: BankAccount) + case unparsable + + private enum CodingKeys: String, CodingKey { + case type + case card = "cardDetails" + case bankAccount = "bankAccountDetails" + } + + // Our JSON structure doesn't align with Swift's expected structure for enums with associated values, so we do custom decoding. + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let type = try container.decode(DetailsType.self, forKey: CodingKeys.type) + switch type { + case .card: + self = .card(card: try container.decode(Card.self, forKey: CodingKeys.card)) + case .bankAccount: + self = .bankAccount(bankAccount: try container.decode(BankAccount.self, forKey: CodingKeys.bankAccount)) + case .unparsable: + self = .unparsable + } + } + } + + var type: DetailsType { + switch details { + case .card: + return .card + case .bankAccount: + return .bankAccount + case .unparsable: + return .unparsable + } + } +} + +// MARK: - Card checks + +extension ConsumerPaymentDetails.Details { + /// For internal SDK use only + final class CardChecks: Codable { + enum CVCCheck: String, SafeEnumCodable { + case pass = "PASS" + case fail = "FAIL" + case unchecked = "UNCHECKED" + case unavailable = "UNAVAILABLE" + case stateInvalid = "STATE_INVALID" + // Catch all + case unparsable = "" + } + + let cvcCheck: CVCCheck + + init(cvcCheck: CVCCheck) { + self.cvcCheck = cvcCheck + } + } +} + +// MARK: - Details.Card +extension ConsumerPaymentDetails.Details { + final class Card: Codable { + let expiryYear: Int + let expiryMonth: Int + let brand: String + let last4: String + let checks: CardChecks? + + private enum CodingKeys: String, CodingKey { + case expiryYear = "expYear" + case expiryMonth = "expMonth" + case brand + case last4 + case checks + } + + /// A frontend convenience property, i.e. not part of the API Object + /// As such this is deliberately omitted from CodingKeys + var cvc: String? + + init(expiryYear: Int, + expiryMonth: Int, + brand: String, + last4: String, + checks: CardChecks?) { + self.expiryYear = expiryYear + self.expiryMonth = expiryMonth + self.brand = brand + self.last4 = last4 + self.checks = checks + } + } +} + +// MARK: - Details.Card - Helpers +extension ConsumerPaymentDetails.Details.Card { + + var shouldRecollectCardCVC: Bool { + switch checks?.cvcCheck { + case .fail, .unavailable, .unchecked: + return true + default: + return false + } + } + + var expiryDate: CardExpiryDate { + return CardExpiryDate(month: expiryMonth, year: expiryYear) + } + + var hasExpired: Bool { + return expiryDate.expired() + } + + var stpBrand: STPCardBrand { + return STPCard.brand(from: brand) } + +} + +// MARK: - Details.BankAccount +extension ConsumerPaymentDetails.Details { + final class BankAccount: Codable { + let iconCode: String? + let name: String + let last4: String + + private enum CodingKeys: String, CodingKey { + case iconCode = "bankIconCode" + case name = "bankName" + case last4 + } + + init(iconCode: String?, + name: String, + last4: String) { + self.iconCode = iconCode + self.name = name + self.last4 = last4 + } + } +} + +extension ConsumerPaymentDetails { + var paymentSheetLabel: String { + switch details { + case .card(let card): + return "••••\(card.last4)" + case .bankAccount(let bank): + return "••••\(bank.last4)" + case .unparsable: + return "" + } + } + + var cvc: String? { + switch details { + case .card(let card): + return card.cvc + case .bankAccount: + return nil + case .unparsable: + return nil + } + } + + var accessibilityDescription: String { + switch details { + case .card(let card): + // TODO(ramont): investigate why this returns optional + let cardBrandName = STPCardBrandUtilities.stringFrom(card.stpBrand) ?? "" + let digits = card.last4.map({ String($0) }).joined(separator: ", ") + return String( + format: String.Localized.card_brand_ending_in_last_4, + cardBrandName, + digits + ) + case .bankAccount(let bank): + let digits = bank.last4.map({ String($0) }).joined(separator: ", ") + return String( + format: String.Localized.bank_name_account_ending_in_last_4, + bank.name, + digits + ) + case .unparsable: + return "" + } + } + } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/STPAPIClient+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/STPAPIClient+Link.swift index 3aa434462ab..3331fa5eb34 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/STPAPIClient+Link.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/API Bindings/Link/STPAPIClient+Link.swift @@ -15,6 +15,7 @@ import Foundation extension STPAPIClient { func lookupConsumerSession( for email: String?, + cookieStore: LinkCookieStore, completion: @escaping (Result) -> Void ) { let endpoint: String = "consumers/sessions/lookup" @@ -25,7 +26,7 @@ extension STPAPIClient { parameters["email_address"] = email.lowercased() } - guard parameters.keys.contains("email_address") || parameters.keys.contains("cookies") else { + guard parameters.keys.contains("email_address") else { // no request to make if we don't have an email or cookies DispatchQueue.main.async { completion(.success( @@ -130,9 +131,36 @@ extension STPAPIClient { ) } + func createPaymentDetails( + for consumerSessionClientSecret: String, + linkedAccountId: String, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + let endpoint: String = "consumers/payment_details" + + let parameters: [String: Any] = [ + "credentials": ["consumer_session_client_secret": consumerSessionClientSecret], + "request_surface": "ios_payment_element", + "bank_account": [ + "account": linkedAccountId, + ], + "type": "bank_account", + "is_default": true, + ] + + makePaymentDetailsRequest( + endpoint: endpoint, + parameters: parameters, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion + ) + } + private func makeConsumerSessionRequest( endpoint: String, parameters: [String: Any], + cookieStore: LinkCookieStore, consumerAccountPublishableKey: String?, completion: @escaping (Result) -> Void ) { @@ -229,8 +257,93 @@ extension STPAPIClient { } } + func listPaymentDetails( + for consumerSessionClientSecret: String, + consumerAccountPublishableKey: String?, + completion: @escaping (Result<[ConsumerPaymentDetails], Error>) -> Void + ) { + let endpoint: String = "consumers/payment_details/list" + + let parameters: [String: Any] = [ + "credentials": ["consumer_session_client_secret": consumerSessionClientSecret], + "request_surface": "ios_payment_element", + "types": ["card", "bank_account"], + ] + + post( + resource: endpoint, + parameters: parameters, + ephemeralKeySecret: consumerAccountPublishableKey + ) { (result: Result) in + completion(result.map { $0.redactedPaymentDetails }) + } + } + + func deletePaymentDetails( + for consumerSessionClientSecret: String, + id: String, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + let endpoint: String = "consumers/payment_details/\(id)" + + let parameters: [String: Any] = [ + "credentials": ["consumer_session_client_secret": consumerSessionClientSecret], + "request_surface": "ios_payment_element", + ] + + APIRequest.delete( + with: self, + endpoint: endpoint, + additionalHeaders: authorizationHeader(using: consumerAccountPublishableKey), + parameters: parameters + ) { result in + completion(result.map { _ in () } ) + } + } + + func updatePaymentDetails( + for consumerSessionClientSecret: String, + id: String, + updateParams: UpdatePaymentDetailsParams, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + let endpoint: String = "consumers/payment_details/\(id)" + + var parameters: [String: Any] = [ + "credentials": ["consumer_session_client_secret": consumerSessionClientSecret], + "request_surface": "ios_payment_element", + ] + + if let details = updateParams.details, case .card(let expiryDate, let billingDetails) = details { + parameters["exp_month"] = expiryDate.month + parameters["exp_year"] = expiryDate.year + + if let billingDetails = billingDetails { + parameters["billing_address"] = billingDetails.consumersAPIParams + } + + if let billingEmailAddress = billingDetails?.email { + parameters["billing_email_address"] = billingEmailAddress + } + } + + if let isDefault = updateParams.isDefault { + parameters["is_default"] = isDefault + } + + makePaymentDetailsRequest( + endpoint: endpoint, + parameters: parameters, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion + ) + } + func logout( consumerSessionClientSecret: String, + cookieStore: LinkCookieStore, consumerAccountPublishableKey: String?, completion: @escaping (Result) -> Void ) { @@ -246,10 +359,72 @@ extension STPAPIClient { makeConsumerSessionRequest( endpoint: endpoint, parameters: parameters, + cookieStore: cookieStore, consumerAccountPublishableKey: consumerAccountPublishableKey, completion: completion ) } + + func startVerification( + for consumerSessionClientSecret: String, + type: ConsumerSession.VerificationSession.SessionType, + locale: Locale, + cookieStore: LinkCookieStore, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + + let typeString: String = { + switch type { + case .sms: + return "SMS" + case .unparsable, .signup, .email: + assertionFailure("We don't support any verification except sms") + return "" + } + }() + let endpoint: String = "consumers/sessions/start_verification" + + let parameters: [String: Any] = [ + "credentials": ["consumer_session_client_secret": consumerSessionClientSecret], + "type": typeString, + "locale": locale.toLanguageTag(), + ] + + makeConsumerSessionRequest( + endpoint: endpoint, + parameters: parameters, + cookieStore: cookieStore, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion + ) + } + + func confirmSMSVerification( + for consumerSessionClientSecret: String, + with code: String, + cookieStore: LinkCookieStore, + consumerAccountPublishableKey: String?, + completion: @escaping (Result) -> Void + ) { + let endpoint: String = "consumers/sessions/confirm_verification" + + let parameters: [String: Any] = [ + "credentials": ["consumer_session_client_secret": consumerSessionClientSecret], + "type": "SMS", + "code": code, + "request_surface": "ios_payment_element", + ] + + makeConsumerSessionRequest( + endpoint: endpoint, + parameters: parameters, + cookieStore: cookieStore, + consumerAccountPublishableKey: consumerAccountPublishableKey, + completion: completion + ) + } + } // TODO(ramont): Remove this after switching to modern bindings. diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift index 3ba0892a03f..3bad321528c 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/NavigationBar/LinkNavigationBar.swift @@ -169,9 +169,7 @@ final class LinkNavigationBar: UIView { } private func update() { -// TODO(link): Set isLoggedIn once the SDK supports logging in again -// let isLoggedIn = linkAccount?.isLoggedIn ?? false - let isLoggedIn = false + let isLoggedIn = linkAccount?.isLoggedIn ?? false emailLabel.text = linkAccount?.email showEmailLabel = isLoggedIn && !showBackButton diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Intent+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Intent+Link.swift index d3bbf88d194..82e58090ea6 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Intent+Link.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/Intent+Link.swift @@ -22,6 +22,10 @@ extension STPElementsSession { supportsLink && (linkFundingSources?.contains(.card) ?? false) || linkPassthroughModeEnabled } + var onlySupportsLinkBank: Bool { + return supportsLink && (linkFundingSources == [.bankAccount]) + } + var linkFundingSources: Set? { linkSettings?.fundingSources } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/STPAnalyticsClient+Link.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/STPAnalyticsClient+Link.swift index f953a17e4f0..b4176beaec6 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/STPAnalyticsClient+Link.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Extensions/STPAnalyticsClient+Link.swift @@ -67,6 +67,28 @@ extension STPAnalyticsClient { self.logPaymentSheetEvent(event: .linkAccountLookupFailure, error: error) } + // MARK: - 2FA + + func logLink2FAStart() { + self.logPaymentSheetEvent(event: .link2FAStart) + } + + func logLink2FAStartFailure() { + self.logPaymentSheetEvent(event: .link2FAStartFailure) + } + + func logLink2FAComplete() { + self.logPaymentSheetEvent(event: .link2FAComplete) + } + + func logLink2FAFailure() { + self.logPaymentSheetEvent(event: .link2FAFailure) + } + + func logLink2FACancel() { + self.logPaymentSheetEvent(event: .link2FACancel) + } + // MARK: - popup func logLinkPopupShow(sessionType: LinkSettings.PopupWebviewOption) { AnalyticsHelper.shared.startTimeMeasurement(.linkPopup) diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Services/LinkAccountService.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Services/LinkAccountService.swift index fa1a1896767..8f5413d0058 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Services/LinkAccountService.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Services/LinkAccountService.swift @@ -33,11 +33,17 @@ protocol LinkAccountServiceProtocol { final class LinkAccountService: LinkAccountServiceProtocol { let apiClient: STPAPIClient + let cookieStore: LinkCookieStore + + /// The default cookie store used by new instances of the service. + static var defaultCookieStore: LinkCookieStore = LinkSecureCookieStore.shared init( - apiClient: STPAPIClient = .shared + apiClient: STPAPIClient = .shared, + cookieStore: LinkCookieStore = defaultCookieStore ) { self.apiClient = apiClient + self.cookieStore = cookieStore } func lookupAccount( @@ -83,4 +89,16 @@ final class LinkAccountService: LinkAccountServiceProtocol { } } } + + func hasEmailLoggedOut(email: String) -> Bool { + guard let hashedEmail = email.lowercased().sha256 else { + return false + } + + return cookieStore.read(key: .lastLogoutEmail) == hashedEmail + } + + func getLastSignUpEmail() -> String? { + return cookieStore.read(key: .lastSignupEmail) + } } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkCookieKey.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkCookieKey.swift index f93d9b1ac9e..aca7278cf4b 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkCookieKey.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkCookieKey.swift @@ -7,9 +7,9 @@ // enum LinkCookieKey: String { - case session = "com.stripe.pay_sid" case lastLogoutEmail = "com.stripe.link_account" case lastPMLast4 = "com.stripe.link.last_pm_last4" case lastPMBrand = "com.stripe.link.last_pm_brand" case hasUsedLink = "com.stripe.link.has_used_link" + case lastSignupEmail = "com.stripe.link.last_signup_email" } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkUtils.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkUtils.swift new file mode 100644 index 00000000000..657b473fe2b --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkUtils.swift @@ -0,0 +1,51 @@ +// +// LinkUtils.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 6/24/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import Foundation + +@_spi(STP) import StripeCore + +final class LinkUtils { + + /// Error codes for the consumer/Link API. + enum ConsumerErrorCode: String { + case consumerVerificationCodeInvalid = "consumer_verification_code_invalid" + case consumerVerificationExpired = "consumer_verification_expired" + case consumerVerificationMaxAttemptsExceeded = "consumer_verification_max_attempts_exceeded" + + var localizedDescription: String { + switch self { + case .consumerVerificationCodeInvalid: + return STPLocalizedString( + "The provided verification code is incorrect.", + "Error message shown when the user enters an incorrect verification code." + ) + case .consumerVerificationExpired: + return STPLocalizedString( + "The provided verification code has expired.", + "Error message shown when the user enters an expired verification code." + ) + case .consumerVerificationMaxAttemptsExceeded: + return STPLocalizedString( + "Too many attempts. Please try again in a few minutes.", + "Error message shown when the user enters an incorrect verification code too many times." + ) + } + } + } + + static func getLocalizedErrorMessage(from error: Error) -> String { + guard let errorCodeString = (error as NSError).userInfo[STPError.stripeErrorCodeKey] as? String, + let errorCode = ConsumerErrorCode(rawValue: errorCodeString) else { + return error.localizedDescription + } + + return errorCode.localizedDescription + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift index 3a7c8468ca8..db00ceffa0a 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElement.swift @@ -46,7 +46,7 @@ public class EmbeddedPaymentElement { public var paymentOption: PaymentOptionDisplayData? { return embeddedPaymentMethodsView.displayData } - + private let embeddedPaymentMethodsView: EmbeddedPaymentMethodsView /// An asynchronous failable initializer @@ -238,7 +238,7 @@ extension EmbeddedPaymentElement: EmbeddedPaymentMethodsViewDelegate { func heightDidChange() { delegate?.embeddedPaymentElementDidUpdateHeight(embeddedPaymentElement: self) } - + func selectionDidUpdate() { delegate?.embeddedPaymentElementDidUpdatePaymentOption(embeddedPaymentElement: self) } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Link/PaymentSheet-LinkConfirmOption.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Link/PaymentSheet-LinkConfirmOption.swift index c18121c07ff..62ad5969a94 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Link/PaymentSheet-LinkConfirmOption.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Link/PaymentSheet-LinkConfirmOption.swift @@ -25,10 +25,22 @@ extension PaymentSheet { intentConfirmParams: IntentConfirmParams ) - /// Confirm with Payment Method. + /// Confirm with Payment Method. (Web fallback) case withPaymentMethod( paymentMethod: STPPaymentMethod ) + + /// Confirm intent with paymentDetails. + case withPaymentDetails( + account: PaymentSheetLinkAccount, + paymentDetails: ConsumerPaymentDetails + ) + + /// Confirm with Payment Method Params. + case withPaymentMethodParams( + account: PaymentSheetLinkAccount, + paymentMethodParams: STPPaymentMethodParams + ) } } @@ -45,6 +57,10 @@ extension PaymentSheet.LinkConfirmOption { return account case .withPaymentMethod: return nil + case .withPaymentDetails(let account, _): + return account + case .withPaymentMethodParams(let account, _): + return account } } @@ -56,6 +72,10 @@ extension PaymentSheet.LinkConfirmOption { return intentConfirmParams.paymentMethodParams.paymentSheetLabel case .withPaymentMethod(let paymentMethod): return paymentMethod.paymentSheetLabel + case .withPaymentDetails(_, let paymentDetails): + return paymentDetails.paymentSheetLabel + case .withPaymentMethodParams(_, let paymentMethodParams): + return paymentMethodParams.paymentSheetLabel } } @@ -67,6 +87,12 @@ extension PaymentSheet.LinkConfirmOption { return intentConfirmParams.paymentMethodParams.billingDetails case .withPaymentMethod(let paymentMethod): return paymentMethod.billingDetails + case .withPaymentDetails: +// TODO(link): Implement .billingDetails +// return paymentDetails.billingDetails + return nil + case .withPaymentMethodParams(_, let paymentMethodParams): + return paymentMethodParams.billingDetails } } diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+API.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+API.swift index a1db37b5304..c31df14bd30 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+API.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+API.swift @@ -453,6 +453,12 @@ extension PaymentSheet { } case .withPaymentMethod(let paymentMethod): confirmWithPaymentMethod(paymentMethod, nil, false) + case .withPaymentDetails(let linkAccount, let paymentDetails): +// TODO(link): Confirm the last two options should be "nil" and "false" + confirmWithPaymentDetails(linkAccount, paymentDetails, nil, false) + case .withPaymentMethodParams(let linkAccount, let paymentMethodParams): +// TODO(link): Confirm the last two options should be "nil" and "false" + createPaymentDetailsAndConfirm(linkAccount, paymentMethodParams, false) } case let .external(paymentMethod, billingDetails): guard let confirmHandler = configuration.externalPaymentMethodConfiguration?.externalPaymentMethodConfirmHandler else { diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift index 55cdcbf7f0c..201648be540 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheet+PaymentMethodAvailability.swift @@ -55,6 +55,12 @@ extension PaymentSheet { } return !configuration.requiresBillingDetailCollection() } + + /// An unordered list of paymentMethodTypes that can be used with Link in PaymentSheet + /// - Note: This is a var because it depends on the authenticated Link user + /// + /// :nodoc: + internal static var supportedLinkPaymentMethods: [STPPaymentMethodType] = [] } // MARK: - PaymentMethodRequirementProvider diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift index 05e44e5513b..9761b9c71d6 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetConfiguration.swift @@ -187,6 +187,9 @@ extension PaymentSheet { /// - Note: If you omit payment methods from this list, they’ll be automatically ordered by Stripe after the ones you provide. Invalid payment methods are ignored. public var paymentMethodOrder: [String]? + // MARK: Internal + internal var linkPaymentMethodsOnly: Bool = false + /// This is an experimental feature that may be removed at any time. /// If true (the default), the customer can delete all saved payment methods. /// If false, the customer can't delete if they only have one saved payment method remaining. diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift index 86e2d786079..72e414c81d4 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Saved Payment Method Screen/SavedPaymentOptionsViewController.swift @@ -463,6 +463,16 @@ class SavedPaymentOptionsViewController: UIViewController { let defaultSelectedIndex = viewModels.firstIndex(where: { $0 == defaultPaymentMethod }) ?? defaultIndex return (defaultSelectedIndex, viewModels) } + + func selectLink() { + guard configuration.showLink else { + return + } + + CustomerPaymentOption.setDefaultPaymentMethod(.link, forCustomer: configuration.customerID) + selectedViewModelIndex = viewModels.firstIndex(where: { $0 == .link }) + collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: .centeredHorizontally) + } } // MARK: - UICollectionView diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetViewController.swift index 18e5746461e..5f88dd8dce4 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetViewController.swift @@ -194,6 +194,10 @@ class PaymentSheetViewController: UIViewController, PaymentSheetViewControllerPr self.view.backgroundColor = configuration.appearance.colors.background } + func selectLink() { + savedPaymentOptionsViewController.selectLink() + } + // MARK: UIViewController Methods override func viewDidLoad() { diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/ConfirmButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/ConfirmButton.swift index 96d54545148..d77adb4767a 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/ConfirmButton.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/ConfirmButton.swift @@ -37,6 +37,7 @@ class ConfirmButton: UIView { } enum CallToActionType { case pay(amount: Int, currency: String) + case add(paymentMethodType: PaymentSheet.PaymentMethodType) case `continue` case setup case custom(title: String) @@ -233,7 +234,7 @@ class ConfirmButton: UIView { titleLabel.font = font } } - + /// Background color for the `.disabled` state. var disabledBackgroundColor: UIColor { return appearance.primaryButton.disabledBackgroundColor ?? appearance.primaryButton.backgroundColor ?? appearance.colors.primary @@ -309,6 +310,12 @@ class ConfirmButton: UIView { lazy var spinner: CheckProgressView = { return CheckProgressView(frame: CGRect(origin: .zero, size: spinnerSize)) }() + lazy var addIcon: UIImageView = { + let image = Image.icon_plus.makeImage(template: true) + let icon = UIImageView(image: image) + icon.setContentCompressionResistancePriority(.required, for: .horizontal) + return icon + }() var foregroundColor: UIColor = .white { didSet { foregroundColorDidChange() @@ -316,7 +323,6 @@ class ConfirmButton: UIView { } var overriddenForegroundColor: UIColor? - init(appearance: PaymentSheet.Appearance = .default) { self.appearance = appearance @@ -328,7 +334,7 @@ class ConfirmButton: UIView { isAccessibilityElement = true // Add views - let views = ["titleLabel": titleLabel, "lockIcon": lockIcon, "spinnyView": spinner] + let views = ["titleLabel": titleLabel, "lockIcon": lockIcon, "spinnyView": spinner, "addIcon": addIcon] views.values.forEach { $0.translatesAutoresizingMaskIntoConstraints = false addSubview($0) @@ -341,6 +347,10 @@ class ConfirmButton: UIView { equalTo: centerXAnchor) titleLabelCenterXConstraint.priority = .defaultLow NSLayoutConstraint.activate([ + // Add icon + addIcon.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + addIcon.centerYAnchor.constraint(equalTo: centerYAnchor), + // Label titleLabelCenterXConstraint, titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor), @@ -385,6 +395,12 @@ class ConfirmButton: UIView { switch status { case .enabled, .disabled, .spinnerWithInteractionDisabled: switch callToAction { + case .add(let paymentMethodType): + if paymentMethodType == .instantDebits { + return STPLocalizedString("Add bank account", "Button prompt to add a bank account as a payment method.") + } else { + return String.Localized.continue + } case .continue: return String.Localized.continue case let .pay(amount, currency): @@ -417,14 +433,18 @@ class ConfirmButton: UIView { // Show/hide lock and add icons switch callToAction { - case .continue: + case .add(let paymentMethodType): lockIcon.isHidden = true - case .custom: + addIcon.isHidden = paymentMethodType != .instantDebits + case .custom, .continue: lockIcon.isHidden = true + addIcon.isHidden = true case .customWithLock: lockIcon.isHidden = false + addIcon.isHidden = true case .pay, .setup: lockIcon.isHidden = false + addIcon.isHidden = true } // Update accessibility information @@ -486,9 +506,11 @@ class ConfirmButton: UIView { switch status { case .disabled, .enabled: self.lockIcon.alpha = self.titleLabel.alpha + self.addIcon.alpha = self.titleLabel.alpha self.spinner.alpha = 0 case .processing, .spinnerWithInteractionDisabled: self.lockIcon.alpha = 0 + self.addIcon.alpha = 0 self.spinner.alpha = 1 self.spinnerCenteredToLockConstraint.isActive = true self.spinnerCenteredConstraint.isActive = false @@ -534,7 +556,7 @@ class ConfirmButton: UIView { if status == .disabled, let disabledTextColor = appearance.primaryButton.disabledTextColor { return disabledTextColor } - + // Use successTextColor if in succeeded state and provided, otherwise fallback to foreground color if status == .succeeded, let successTextColor = appearance.primaryButton.successTextColor { return successTextColor diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/PayWithLinkButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/PayWithLinkButton.swift index 2b48e68c148..3408ce78e09 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/PayWithLinkButton.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Views/PayWithLinkButton.swift @@ -31,11 +31,13 @@ final class PayWithLinkButton: UIControl { fileprivate struct LinkAccountStub: PaymentSheetLinkAccountInfoProtocol { let email: String + let redactedPhoneNumber: String? let isRegistered: Bool + let isLoggedIn: Bool } /// Link account of the current user. - var linkAccount: PaymentSheetLinkAccountInfoProtocol? = LinkAccountStub(email: "", isRegistered: false) { + var linkAccount: PaymentSheetLinkAccountInfoProtocol? = LinkAccountContext.shared.account { didSet { updateUI() } @@ -464,7 +466,9 @@ struct UIViewPreview: UIViewRepresentable { private func makeAccountStub(email: String, isRegistered: Bool, lastPM: LinkPMDisplayDetails?) -> PayWithLinkButton.LinkAccountStub { return PayWithLinkButton.LinkAccountStub( email: email, - isRegistered: isRegistered + redactedPhoneNumber: nil, + isRegistered: isRegistered, + isLoggedIn: false ) } diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/LinkStubs.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/LinkStubs.swift index affbe8ce890..72ff62c76cb 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/LinkStubs.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/LinkStubs.swift @@ -30,16 +30,48 @@ extension LinkStubs { static func paymentMethods() -> [ConsumerPaymentDetails] { return [ ConsumerPaymentDetails( - stripeID: "1" + stripeID: "1", + details: .card(card: .init( + expiryYear: 30, + expiryMonth: 10, + brand: "visa", + last4: "1234", + checks: nil) + ), + isDefault: true ), ConsumerPaymentDetails( - stripeID: "2" + stripeID: "1", + details: .card(card: .init( + expiryYear: 30, + expiryMonth: 10, + brand: "mastercard", + last4: "4321", + checks: nil) + ), + isDefault: false ), ConsumerPaymentDetails( - stripeID: "3" + stripeID: "3", + details: .card(card: .init( + expiryYear: 30, + expiryMonth: 10, + brand: "discover", + last4: "1111", + checks: nil) + ), + isDefault: false ), ConsumerPaymentDetails( - stripeID: "4" + stripeID: "4", + details: .card(card: .init( + expiryYear: 30, + expiryMonth: 10, + brand: "visa", + last4: "9999", + checks: nil) + ), + isDefault: false ), ] } @@ -48,7 +80,9 @@ extension LinkStubs { return ConsumerSession( clientSecret: "client_secret", emailAddress: "user@example.com", - verificationSessions: [] + redactedPhoneNumber: "+1********55", + verificationSessions: [], + supportedPaymentDetailsTypes: [] ) } diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLinkAccountTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLinkAccountTests.swift index 5808f1107ac..9dbcba74315 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLinkAccountTests.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetLinkAccountTests.swift @@ -53,7 +53,9 @@ extension PaymentSheetLinkAccountTests { func makePaymentDetailsStub() -> ConsumerPaymentDetails { return ConsumerPaymentDetails( - stripeID: "1" + stripeID: "1", + details: .card(card: .init(expiryYear: 30, expiryMonth: 10, brand: "visa", last4: "1234", checks: nil)), + isDefault: false ) } diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithEmailAddress@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithEmailAddress@3x.png index 66dcc162102eb7a0ae22184c363b3c96a0abb295..6d290297d31d474fb885b2abf4a802e8eb6577ac 100644 GIT binary patch literal 16273 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 Xht!2LMgzbPOdv%$)qBOVj|2V>0xNoU diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithLongEmailAddress@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkNavigationBarSnapshotTests/testWithLongEmailAddress@3x.png index 66dcc162102eb7a0ae22184c363b3c96a0abb295..95e90892298df6b8034870c6cc569bb10bf2de4f 100644 GIT binary patch literal 19922 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 Xht!2LMgzbPOdv%$)qBOVj|2V>0xNoU From 70238287bcf004df0841fd5ce7d9ae30d5d13f77 Mon Sep 17 00:00:00 2001 From: David Estes Date: Thu, 17 Oct 2024 14:54:33 -0700 Subject: [PATCH 11/12] Add view components --- .../project.pbxproj | 72 ++++ .../en.lproj/Localizable.strings | 45 +++ .../LinkPaymentMethodPicker-AddButton.swift | 99 ++++++ .../LinkPaymentMethodPicker-Cell.swift | 280 +++++++++++++++ ...kPaymentMethodPicker-CellContentView.swift | 138 ++++++++ .../LinkPaymentMethodPicker-Header.swift | 194 +++++++++++ .../LinkPaymentMethodPicker-RadioButton.swift | 116 +++++++ .../LinkPaymentMethodPicker.swift | 320 ++++++++++++++++++ .../Link/Elements/LinkCardEditElement.swift | 225 ++++++++++++ .../LinkVerificationController.swift | 49 +++ .../LinkVerificationView-Header.swift | 69 ++++ .../LinkVerificationView-LogoutView.swift | 65 ++++ .../Verification/LinkVerificationView.swift | 271 +++++++++++++++ ...iewController-PresentationController.swift | 211 ++++++++++++ .../LinkVerificationViewController.swift | 247 ++++++++++++++ .../LinkCardEditElementSnapshotTests.swift | 73 ++++ ...LinkPaymentMethodPickerSnapshotTests.swift | 101 ++++++ .../LinkVerificationViewSnapshotTests.swift | 77 +++++ .../testDefault@3x.png | Bin 0 -> 66155 bytes .../testNonDefault@3x.png | Bin 0 -> 78261 bytes .../testEmpty@3x.png | Bin 0 -> 14583 bytes .../testExpanded@3x.png | Bin 0 -> 60721 bytes .../testNormal_First_Option@3x.png | Bin 0 -> 14705 bytes .../testNormal_Second_Option@3x.png | Bin 0 -> 14702 bytes .../testUnsupportedBankAccount@3x.png | Bin 0 -> 60721 bytes .../testEmbedded@3x.png | Bin 0 -> 77265 bytes .../testInlineLogin@3x.png | Bin 0 -> 66541 bytes .../testModal@3x.png | Bin 0 -> 71909 bytes .../testModalWithErrorMessage@3x.png | Bin 0 -> 81857 bytes 29 files changed, 2652 insertions(+) create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Elements/LinkCardEditElement.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationController.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-Header.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-LogoutView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController-PresentationController.swift create mode 100644 StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift create mode 100644 StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkCardEditElementSnapshotTests/testDefault@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkCardEditElementSnapshotTests/testNonDefault@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testEmpty@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testExpanded@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testNormal_First_Option@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testNormal_Second_Option@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testUnsupportedBankAccount@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkVerificationViewSnapshotTests/testEmbedded@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkVerificationViewSnapshotTests/testInlineLogin@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkVerificationViewSnapshotTests/testModal@3x.png create mode 100644 Tests/ReferenceImages_64/StripePaymentSheetTests.LinkVerificationViewSnapshotTests/testModalWithErrorMessage@3x.png diff --git a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj index 7c4516ab29d..6d8abeed019 100644 --- a/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj +++ b/StripePaymentSheet/StripePaymentSheet.xcodeproj/project.pbxproj @@ -58,6 +58,22 @@ 3147CEC02CC080570067B5E4 /* LinkInMemoryCookieStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBD2CC080570067B5E4 /* LinkInMemoryCookieStore.swift */; }; 3147CEC12CC080570067B5E4 /* LinkCookieStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBC2CC080570067B5E4 /* LinkCookieStore.swift */; }; 3147CEC22CC080570067B5E4 /* LinkSecureCookieStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEBE2CC080570067B5E4 /* LinkSecureCookieStore.swift */; }; + 3147CECA2CC1BF550067B5E4 /* LinkPaymentMethodPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEC32CC1BF550067B5E4 /* LinkPaymentMethodPicker.swift */; }; + 3147CECB2CC1BF550067B5E4 /* LinkPaymentMethodPicker-CellContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEC62CC1BF550067B5E4 /* LinkPaymentMethodPicker-CellContentView.swift */; }; + 3147CECC2CC1BF550067B5E4 /* LinkPaymentMethodPicker-Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEC52CC1BF550067B5E4 /* LinkPaymentMethodPicker-Cell.swift */; }; + 3147CECD2CC1BF550067B5E4 /* LinkPaymentMethodPicker-Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEC72CC1BF550067B5E4 /* LinkPaymentMethodPicker-Header.swift */; }; + 3147CECE2CC1BF550067B5E4 /* LinkPaymentMethodPicker-RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEC82CC1BF550067B5E4 /* LinkPaymentMethodPicker-RadioButton.swift */; }; + 3147CECF2CC1BF550067B5E4 /* LinkPaymentMethodPicker-AddButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEC42CC1BF550067B5E4 /* LinkPaymentMethodPicker-AddButton.swift */; }; + 3147CED12CC1BF6E0067B5E4 /* LinkCardEditElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED02CC1BF6E0067B5E4 /* LinkCardEditElement.swift */; }; + 3147CED82CC1BF860067B5E4 /* LinkVerificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED62CC1BF860067B5E4 /* LinkVerificationViewController.swift */; }; + 3147CED92CC1BF860067B5E4 /* LinkVerificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED22CC1BF860067B5E4 /* LinkVerificationController.swift */; }; + 3147CEDA2CC1BF860067B5E4 /* LinkVerificationViewController-PresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED72CC1BF860067B5E4 /* LinkVerificationViewController-PresentationController.swift */; }; + 3147CEDB2CC1BF860067B5E4 /* LinkVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED32CC1BF860067B5E4 /* LinkVerificationView.swift */; }; + 3147CEDC2CC1BF860067B5E4 /* LinkVerificationView-Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED42CC1BF860067B5E4 /* LinkVerificationView-Header.swift */; }; + 3147CEDD2CC1BF860067B5E4 /* LinkVerificationView-LogoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CED52CC1BF860067B5E4 /* LinkVerificationView-LogoutView.swift */; }; + 3147CEE12CC1BFA80067B5E4 /* LinkCardEditElementSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEDE2CC1BFA80067B5E4 /* LinkCardEditElementSnapshotTests.swift */; }; + 3147CEE22CC1BFA80067B5E4 /* LinkPaymentMethodPickerSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEDF2CC1BFA80067B5E4 /* LinkPaymentMethodPickerSnapshotTests.swift */; }; + 3147CEE32CC1BFA80067B5E4 /* LinkVerificationViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3147CEE02CC1BFA80067B5E4 /* LinkVerificationViewSnapshotTests.swift */; }; 31699A812BE183B30048677F /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31699A802BE183B30048677F /* DownloadManager.swift */; }; 31699A832BE183D40048677F /* DownloadManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31699A822BE183D40048677F /* DownloadManagerTest.swift */; }; 316B33122B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 316B33112B5F171C0008D2E5 /* UserDefaults+StripePaymentSheetTest.swift */; }; @@ -428,6 +444,22 @@ 3147CEBC2CC080570067B5E4 /* LinkCookieStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkCookieStore.swift; sourceTree = ""; }; 3147CEBD2CC080570067B5E4 /* LinkInMemoryCookieStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkInMemoryCookieStore.swift; sourceTree = ""; }; 3147CEBE2CC080570067B5E4 /* LinkSecureCookieStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkSecureCookieStore.swift; sourceTree = ""; }; + 3147CEC32CC1BF550067B5E4 /* LinkPaymentMethodPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPaymentMethodPicker.swift; sourceTree = ""; }; + 3147CEC42CC1BF550067B5E4 /* LinkPaymentMethodPicker-AddButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkPaymentMethodPicker-AddButton.swift"; sourceTree = ""; }; + 3147CEC52CC1BF550067B5E4 /* LinkPaymentMethodPicker-Cell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkPaymentMethodPicker-Cell.swift"; sourceTree = ""; }; + 3147CEC62CC1BF550067B5E4 /* LinkPaymentMethodPicker-CellContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkPaymentMethodPicker-CellContentView.swift"; sourceTree = ""; }; + 3147CEC72CC1BF550067B5E4 /* LinkPaymentMethodPicker-Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkPaymentMethodPicker-Header.swift"; sourceTree = ""; }; + 3147CEC82CC1BF550067B5E4 /* LinkPaymentMethodPicker-RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkPaymentMethodPicker-RadioButton.swift"; sourceTree = ""; }; + 3147CED02CC1BF6E0067B5E4 /* LinkCardEditElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkCardEditElement.swift; sourceTree = ""; }; + 3147CED22CC1BF860067B5E4 /* LinkVerificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkVerificationController.swift; sourceTree = ""; }; + 3147CED32CC1BF860067B5E4 /* LinkVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkVerificationView.swift; sourceTree = ""; }; + 3147CED42CC1BF860067B5E4 /* LinkVerificationView-Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkVerificationView-Header.swift"; sourceTree = ""; }; + 3147CED52CC1BF860067B5E4 /* LinkVerificationView-LogoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkVerificationView-LogoutView.swift"; sourceTree = ""; }; + 3147CED62CC1BF860067B5E4 /* LinkVerificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkVerificationViewController.swift; sourceTree = ""; }; + 3147CED72CC1BF860067B5E4 /* LinkVerificationViewController-PresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LinkVerificationViewController-PresentationController.swift"; sourceTree = ""; }; + 3147CEDE2CC1BFA80067B5E4 /* LinkCardEditElementSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkCardEditElementSnapshotTests.swift; sourceTree = ""; }; + 3147CEDF2CC1BFA80067B5E4 /* LinkPaymentMethodPickerSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPaymentMethodPickerSnapshotTests.swift; sourceTree = ""; }; + 3147CEE02CC1BFA80067B5E4 /* LinkVerificationViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkVerificationViewSnapshotTests.swift; sourceTree = ""; }; 3168698F2C61B0F5EC1240FE /* sl-SI */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sl-SI"; path = "sl-SI.lproj/Localizable.strings"; sourceTree = ""; }; 31699A802BE183B30048677F /* DownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManager.swift; sourceTree = ""; }; 31699A822BE183D40048677F /* DownloadManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManagerTest.swift; sourceTree = ""; }; @@ -836,6 +868,19 @@ path = CookieStore; sourceTree = ""; }; + 3147CEC92CC1BF550067B5E4 /* PaymentMethodPicker */ = { + isa = PBXGroup; + children = ( + 3147CEC32CC1BF550067B5E4 /* LinkPaymentMethodPicker.swift */, + 3147CEC42CC1BF550067B5E4 /* LinkPaymentMethodPicker-AddButton.swift */, + 3147CEC52CC1BF550067B5E4 /* LinkPaymentMethodPicker-Cell.swift */, + 3147CEC62CC1BF550067B5E4 /* LinkPaymentMethodPicker-CellContentView.swift */, + 3147CEC72CC1BF550067B5E4 /* LinkPaymentMethodPicker-Header.swift */, + 3147CEC82CC1BF550067B5E4 /* LinkPaymentMethodPicker-RadioButton.swift */, + ); + path = PaymentMethodPicker; + sourceTree = ""; + }; 319DFD940EAA6EA0A0F4E771 /* Services */ = { isa = PBXGroup; children = ( @@ -882,6 +927,7 @@ 31CC9B872CB5F74A00E84A38 /* Badge */, 31CC9B892CB5F74A00E84A38 /* NavigationBar */, 31CC9B8B2CB5F74A00E84A38 /* Notice */, + 3147CEC92CC1BF550067B5E4 /* PaymentMethodPicker */, 31CC9B942CB5F74A00E84A38 /* Toast */, ); path = Components; @@ -1224,6 +1270,12 @@ B02DD1BA93CC92A187051B2F /* LinkAccountContext.swift */, 3147CEBA2CC07E960067B5E4 /* LinkUtils.swift */, A1928BE9DFF116368B1A19DC /* LinkCookieKey.swift */, + 3147CED22CC1BF860067B5E4 /* LinkVerificationController.swift */, + 3147CED32CC1BF860067B5E4 /* LinkVerificationView.swift */, + 3147CED42CC1BF860067B5E4 /* LinkVerificationView-Header.swift */, + 3147CED52CC1BF860067B5E4 /* LinkVerificationView-LogoutView.swift */, + 3147CED62CC1BF860067B5E4 /* LinkVerificationViewController.swift */, + 3147CED72CC1BF860067B5E4 /* LinkVerificationViewController-PresentationController.swift */, ); path = Verification; sourceTree = ""; @@ -1469,6 +1521,7 @@ children = ( C71284B45BF3D3B487C1B99D /* InlineSignup */, C684CBDA487CC3E78676F52E /* LinkEmailElement.swift */, + 3147CED02CC1BF6E0067B5E4 /* LinkCardEditElement.swift */, ); path = Elements; sourceTree = ""; @@ -1608,6 +1661,9 @@ 31CC9B762CB5F69600E84A38 /* LinkURLGeneratorTests.swift */, 22E4212F4A865B5AB5D72F99 /* LinkPopupURLParserTests.swift */, 9872CF28C8CA1D2C5499B8C5 /* LinkURLGeneratorTests.swift */, + 3147CEDE2CC1BFA80067B5E4 /* LinkCardEditElementSnapshotTests.swift */, + 3147CEDF2CC1BFA80067B5E4 /* LinkPaymentMethodPickerSnapshotTests.swift */, + 3147CEE02CC1BFA80067B5E4 /* LinkVerificationViewSnapshotTests.swift */, ); path = Link; sourceTree = ""; @@ -1818,6 +1874,9 @@ 31CC9B792CB5F69600E84A38 /* LinkNavigationBarSnapshotTests.swift in Sources */, 31CC9B7D2CB5F69600E84A38 /* ButtonLinkSnapshotTests.swift in Sources */, 31CC9B7E2CB5F69600E84A38 /* LinkNoticeViewSnapshotTests.swift in Sources */, + 3147CEE12CC1BFA80067B5E4 /* LinkCardEditElementSnapshotTests.swift in Sources */, + 3147CEE22CC1BFA80067B5E4 /* LinkPaymentMethodPickerSnapshotTests.swift in Sources */, + 3147CEE32CC1BFA80067B5E4 /* LinkVerificationViewSnapshotTests.swift in Sources */, 31CC9B7F2CB5F69600E84A38 /* LinkPopupURLParserTests.swift in Sources */, 31CC9B802CB5F69600E84A38 /* LinkToastSnapshotTests.swift in Sources */, 31CC9B812CB5F69600E84A38 /* LinkInstantDebitMandateViewSnapshotTests.swift in Sources */, @@ -2007,6 +2066,12 @@ DFA10770E494AFB895BA4EE2 /* TextFieldElement+Card.swift in Sources */, B6B3481CBA798CF22EE8411A /* TextFieldElement+IBAN.swift in Sources */, F90B7028426261188B66C834 /* Error+PaymentSheet.swift in Sources */, + 3147CECA2CC1BF550067B5E4 /* LinkPaymentMethodPicker.swift in Sources */, + 3147CECB2CC1BF550067B5E4 /* LinkPaymentMethodPicker-CellContentView.swift in Sources */, + 3147CECC2CC1BF550067B5E4 /* LinkPaymentMethodPicker-Cell.swift in Sources */, + 3147CECD2CC1BF550067B5E4 /* LinkPaymentMethodPicker-Header.swift in Sources */, + 3147CECE2CC1BF550067B5E4 /* LinkPaymentMethodPicker-RadioButton.swift in Sources */, + 3147CECF2CC1BF550067B5E4 /* LinkPaymentMethodPicker-AddButton.swift in Sources */, FB653AA92B68F73344835A50 /* Intent.swift in Sources */, 253EED99635621AC0E788EBC /* IntentConfirmParams.swift in Sources */, 313F5F832B0BE5FD00BD98A9 /* Docs.docc in Sources */, @@ -2048,6 +2113,12 @@ 6A5997192BC88E28002A44CB /* InstantDebitsPaymentMethodElement.swift in Sources */, E5571A970EB9DFC4B690636F /* STPAnalyticsClient+PaymentSheet.swift in Sources */, 0B142FE21B861925B513143D /* STPApplePayContext+PaymentSheet.swift in Sources */, + 3147CED82CC1BF860067B5E4 /* LinkVerificationViewController.swift in Sources */, + 3147CED92CC1BF860067B5E4 /* LinkVerificationController.swift in Sources */, + 3147CEDA2CC1BF860067B5E4 /* LinkVerificationViewController-PresentationController.swift in Sources */, + 3147CEDB2CC1BF860067B5E4 /* LinkVerificationView.swift in Sources */, + 3147CEDC2CC1BF860067B5E4 /* LinkVerificationView-Header.swift in Sources */, + 3147CEDD2CC1BF860067B5E4 /* LinkVerificationView-LogoutView.swift in Sources */, 6103F2BC2BE45990002D67F8 /* SavedPaymentMethodManager.swift in Sources */, ED75C8F47475E4BE5D496C93 /* STPPaymentIntentShippingDetailsParams+PaymentSheet.swift in Sources */, 4313D6635F10EC460D2ED21E /* SavedPaymentMethodCollectionView.swift in Sources */, @@ -2055,6 +2126,7 @@ F4EA474D60D0889E7D48E1CF /* BankAccountInfoView.swift in Sources */, 057A899F4123F3716F2AC0FA /* USBankAccountPaymentMethodElement.swift in Sources */, 985DAA770BC0289D24A5999C /* AddressSearchResult.swift in Sources */, + 3147CED12CC1BF6E0067B5E4 /* LinkCardEditElement.swift in Sources */, 31CC9BA12CB5F93100E84A38 /* Button+Link.swift in Sources */, 9DEDA3E0FFF73F9275F5F8F0 /* AutoCompleteViewController.swift in Sources */, A4CD99B2032CBFA7F957B1B8 /* String+AutoComplete.swift in Sources */, diff --git a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings index 2aef5ceb3da..6a870bebf73 100644 --- a/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings +++ b/StripePaymentSheet/StripePaymentSheet/Resources/Localizations/en.lproj/Localizable.strings @@ -103,12 +103,18 @@ /* Button text on a screen asking the user to approve a payment */ "Cancel and pay another way" = "Cancel and pay another way"; +/* Title for a button that allows the user to use a different email in the signup flow. */ +"Change email" = "Change email"; + /* TODO */ "Choose a payment method" = "Choose a payment method"; /* Accessibility label for the button to close the card scanner. */ "Close card scanner" = "Close card scanner"; +/* Text of a notification shown to the user when a login code is successfully sent via SMS. */ +"Code sent" = "Code sent"; + /* Title used for various UIs, including a button that confirms entered payment details or the selection of a payment method. */ "Confirm" = "Confirm"; @@ -127,9 +133,18 @@ /* Label for CPF/CPNJ (Brazil tax ID) field */ "CPF/CPNJ" = "CPF/CPNJ"; +/* Label for identifying the default payment method. */ +"Default" = "Default"; + /* Text for a button that allows manual entry of an address */ "Enter address manually" = "Enter address manually"; +/* Instructs the user to enter the code sent to their phone number in order to login to Link */ +"Enter the code sent to %@ to use Link to pay by default." = "Enter the code sent to %@ to use Link to pay by default."; + +/* Two factor authentication screen heading */ +"Enter your verification code" = "Enter your verification code"; + /* Label title for EPS Bank */ "EPS Bank" = "EPS Bank"; @@ -163,6 +178,9 @@ /* Title shown above a section containing payment methods that a customer can choose to pay with e.g. card, bank account, etc. */ "New payment method" = "New payment method"; +/* Text of a label for confirming an email address. E.g., 'Not user@example.com?' */ +"Not %@?" = "Not %@?"; + /* Countdown timer text on a screen asking the user to approve a payment */ "Open your UPI app to approve your payment within %@" = "Open your UPI app to approve your payment within %@"; @@ -204,9 +222,15 @@ e.g, 'Pay faster at Example, Inc. and thousands of businesses.' */ /* US Bank Account copy title for Mobile payment element form */ "Pay with your bank account in just a few steps." = "Pay with your bank account in just a few steps."; +/* Label for a section displaying payment details. */ +"Payment" = "Payment"; + /* Text on a screen that indicates a payment has failed */ "Payment failed" = "Payment failed"; +/* Title for a section listing one or more payment methods. */ +"Payment methods" = "Payment methods"; + /* Text on a screen that indicates a payment has failed informing the user we are asking the user to try a different payment method */ "Please go back and select another payment method" = "Please go back and select another payment method"; @@ -225,6 +249,9 @@ e.g, 'Pay faster at Example, Inc. and thousands of businesses.' */ /* Title shown above a view containing a customer's payment method that they can delete */ "Remove payment method" = "Remove payment method"; +/* Label for a button that re-sends the a login code when tapped */ +"Resend code" = "Resend code"; + /* A button used for saving a new payment method */ "Save" = "Save"; @@ -262,6 +289,9 @@ to be saved and used in future checkout sessions. */ /* Title shown above a carousel containing the customer's payment methods */ "Select your payment method" = "Select your payment method"; +/* Label of a checkbox that when checked makes a payment method as the default one. */ +"Set as default payment method" = "Set as default payment method"; + /* Label of a button displayed below a payment method form. Tapping the button sets the payment method up for future use */ "Set up" = "Set up"; @@ -272,6 +302,9 @@ is not supported by the merchant */ /* Accessibility label for an action or a button that shows a menu. */ "Show menu" = "Show menu"; +/* Two factor authentication screen heading */ +"Sign in to your Link account" = "Sign in to your Link account"; + /* Subtitle shown on a button allowing a user to select to pay with Link. */ "Simple, secure one-click payments" = "Simple, secure one-click payments"; @@ -284,6 +317,12 @@ is not supported by the merchant */ /* Prompt for microdeposit verification before completing purchase with merchant. %@ will be replaced by merchant business name */ "Stripe will deposit $0.01 to your account in 1-2 business days. Then you’ll get an email with instructions to complete payment to %@." = "Stripe will deposit $0.01 to your account in 1-2 business days. Then you’ll get an email with instructions to complete payment to %@."; +/* Accessibility hint to tell the user that they can tap to hide additional content. */ +"Tap to close" = "Tap to close"; + +/* Accessibility hint to tell the user that they can tap to reveal additional content. */ +"Tap to expand" = "Tap to expand"; + /* An error message. */ "The IBAN you entered is incomplete." = "The IBAN you entered is incomplete."; @@ -299,6 +338,9 @@ is not supported by the merchant */ /* Error message shown when the user enters an incorrect verification code too many times. */ "Too many attempts. Please try again in a few minutes." = "Too many attempts. Please try again in a few minutes."; +/* Label shown when a payment method cannot be used for the current transaction. */ +"Unavailable for this purchase" = "Unavailable for this purchase"; + /* Title for a button that when tapped, updates a card brand. */ "Update" = "Update"; @@ -309,6 +351,9 @@ the heading the screen itself. */ /* Title for a screen for updating a card brand. */ "Update card brand" = "Update card brand"; +/* Two factor authentication screen heading */ +"Use your saved info to check out faster" = "Use your saved info to check out faster"; + /* Text shown on a button that displays a customer's default saved payment method. When tapped, it opens a screen that shows all of the customer's saved payment methods. */ "View more" = "View more"; diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift new file mode 100644 index 00000000000..3bb072a6432 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-AddButton.swift @@ -0,0 +1,99 @@ +// +// LinkPaymentMethodPicker-AddButton.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/20/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore +import UIKit + +extension LinkPaymentMethodPicker { + + final class AddButton: UIControl { + struct Constants { + static let iconSize: CGSize = .init(width: 24, height: 24) + } + + private let iconView: UIImageView = UIImageView(image: Image.icon_add_bordered.makeImage(template: true)) + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.text = String.Localized.add_a_payment_method + label.numberOfLines = 0 + label.textColor = tintColor + label.font = LinkUI.font(forTextStyle: .bodyEmphasized) + label.adjustsFontForContentSizeCategory = true + return label + }() + + override var isHighlighted: Bool { + didSet { + update() + } + } + + init() { + super.init(frame: .zero) + + isAccessibilityElement = true + accessibilityTraits = .button + accessibilityLabel = textLabel.text + directionalLayoutMargins = Cell.Constants.margins + + setupUI() + update() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.point(inside: point, with: event) { + return self + } + + return nil + } + + override func tintColorDidChange() { + super.tintColorDidChange() + self.textLabel.textColor = tintColor + } + + private func setupUI() { + let stackView = UIStackView(arrangedSubviews: [iconView, textLabel]) + stackView.spacing = Cell.Constants.contentSpacing + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + + addSubview(stackView) + + NSLayoutConstraint.activate([ + iconView.widthAnchor.constraint(equalToConstant: Constants.iconSize.width), + iconView.heightAnchor.constraint(equalToConstant: Constants.iconSize.height), + stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), + stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), + stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + ]) + } + + private func update() { + if isHighlighted { + iconView.alpha = 0.7 + textLabel.alpha = 0.7 + backgroundColor = .linkControlHighlight + } else { + iconView.alpha = 1 + textLabel.alpha = 1 + backgroundColor = .clear + } + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift new file mode 100644 index 00000000000..6a2a47fa3bc --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Cell.swift @@ -0,0 +1,280 @@ +// +// LinkPaymentMethodPicker-Cell.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/19/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore +import UIKit + +protocol LinkPaymentMethodPickerCellDelegate: AnyObject { + func savedPaymentPickerCellDidSelect(_ cell: LinkPaymentMethodPicker.Cell) + func savedPaymentPickerCell(_ cell: LinkPaymentMethodPicker.Cell, didTapMenuButton button: UIButton) +} + +extension LinkPaymentMethodPicker { + + final class Cell: UIControl { + struct Constants { + static let margins = NSDirectionalEdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20) + static let contentSpacing: CGFloat = 12 + static let contentIndentation: CGFloat = 34 + static let menuSpacing: CGFloat = 8 + static let menuButtonSize: CGSize = .init(width: 24, height: 24) + static let separatorHeight: CGFloat = 1 + static let iconViewSize: CGSize = .init(width: 14, height: 20) + static let disabledContentAlpha: CGFloat = 0.5 + } + + override var isHighlighted: Bool { + didSet { + setNeedsLayout() + } + } + + override var isSelected: Bool { + didSet { + setNeedsLayout() + } + } + + var paymentMethod: ConsumerPaymentDetails? { + didSet { + update() + } + } + + var isLoading: Bool = false { + didSet { + if isLoading != oldValue { + update() + } + } + } + + var isSupported: Bool = true { + didSet { + if isSupported != oldValue { + update() + } + } + } + + weak var delegate: LinkPaymentMethodPickerCellDelegate? + + private let radioButton = RadioButton() + + private let contentView = CellContentView() + + private let activityIndicator = ActivityIndicator() + + private let defaultBadge = LinkBadgeView( + type: .neutral, + text: STPLocalizedString("Default", "Label for identifying the default payment method.") + ) + + private let alertIconView: UIImageView = { + let iconView = UIImageView() + iconView.contentMode = .scaleAspectFit + iconView.image = Image.icon_link_error.makeImage(template: true) + iconView.tintColor = .linkDangerForeground + return iconView + }() + + private let unavailableBadge = LinkBadgeView(type: .error, text: STPLocalizedString( + "Unavailable for this purchase", + "Label shown when a payment method cannot be used for the current transaction." + )) + + private lazy var menuButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(Image.icon_menu.makeImage(), for: .normal) + button.addTarget(self, action: #selector(onMenuButtonTapped(_:)), for: .touchUpInside) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + /// The menu button frame for hit-testing purposes. + private var menuButtonFrame: CGRect { + let originalFrame = menuButton.convert(menuButton.bounds, to: self) + + let targetSize = CGSize(width: 44, height: 44) + + return CGRect( + x: originalFrame.midX - (targetSize.width / 2), + y: originalFrame.midY - (targetSize.height / 2), + width: targetSize.width, + height: targetSize.height + ) + } + + private let separator: UIView = { + let separator = UIView() + separator.backgroundColor = .linkControlBorder + separator.translatesAutoresizingMaskIntoConstraints = false + return separator + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + isAccessibilityElement = true + directionalLayoutMargins = Constants.margins + + setupUI() + addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(onCellLongPressed))) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + let rightStackView = UIStackView(arrangedSubviews: [defaultBadge, alertIconView, activityIndicator, menuButton]) + rightStackView.spacing = LinkUI.smallContentSpacing + rightStackView.distribution = .equalSpacing + rightStackView.alignment = .center + + let stackView = UIStackView(arrangedSubviews: [contentView, rightStackView]) + stackView.spacing = Constants.contentSpacing + stackView.distribution = .equalSpacing + stackView.alignment = .center + + let container = UIStackView(arrangedSubviews: [stackView, unavailableBadge]) + container.axis = .vertical + container.spacing = Constants.contentSpacing + container.distribution = .equalSpacing + container.alignment = .leading + container.translatesAutoresizingMaskIntoConstraints = false + addSubview(container) + + radioButton.translatesAutoresizingMaskIntoConstraints = false + addSubview(radioButton) + + addSubview(separator) + + NSLayoutConstraint.activate([ + // Radio button + radioButton.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + radioButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + + // Menu button + menuButton.widthAnchor.constraint(equalToConstant: Constants.menuButtonSize.width), + menuButton.heightAnchor.constraint(equalToConstant: Constants.menuButtonSize.height), + + // Loader + activityIndicator.widthAnchor.constraint(equalToConstant: Constants.menuButtonSize.width), + activityIndicator.heightAnchor.constraint(equalToConstant: Constants.menuButtonSize.height), + + // Icon + alertIconView.widthAnchor.constraint(equalToConstant: Constants.iconViewSize.width), + alertIconView.heightAnchor.constraint(equalToConstant: Constants.iconViewSize.height), + + // Container + container.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), + container.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), + container.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: Constants.contentIndentation), + container.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + // Make stackView fill the container + stackView.trailingAnchor.constraint(equalTo: container.trailingAnchor), + + // Separator + separator.heightAnchor.constraint(equalToConstant: Constants.separatorHeight), + separator.bottomAnchor.constraint(equalTo: bottomAnchor), + separator.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + separator.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + ]) + } + + private func update() { + contentView.paymentMethod = paymentMethod + updateAccessibilityContent() + + guard let paymentMethod = paymentMethod else { + return + } + + var hasExpired: Bool { + switch paymentMethod.details { + case .card(let card): + return card.hasExpired + case .bankAccount: + return false + case .unparsable: + return false + } + } + + defaultBadge.isHidden = isLoading || !paymentMethod.isDefault + alertIconView.isHidden = isLoading || !hasExpired + menuButton.isHidden = isLoading + contentView.alpha = isSupported ? 1 : Constants.disabledContentAlpha + unavailableBadge.isHidden = isSupported + + if isLoading { + activityIndicator.startAnimating() + } else { + activityIndicator.stopAnimating() + } + } + + override func layoutSubviews() { + super.layoutSubviews() + radioButton.isOn = isSelected + backgroundColor = isHighlighted ? .linkControlHighlight : .clear + } + + private func updateAccessibilityContent() { + guard let paymentMethod = paymentMethod else { + return + } + + accessibilityIdentifier = "Stripe.Link.PaymentMethodPickerCell" + accessibilityLabel = paymentMethod.accessibilityDescription + accessibilityCustomActions = [ + UIAccessibilityCustomAction( + name: String.Localized.show_menu, + target: self, + selector: #selector(onShowMenuAction(_:)) + ), + ] + } + + @objc func onShowMenuAction(_ sender: UIAccessibilityCustomAction) { + onMenuButtonTapped(menuButton) + } + + @objc func onMenuButtonTapped(_ sender: UIButton) { + delegate?.savedPaymentPickerCell(self, didTapMenuButton: sender) + } + + @objc func onCellLongPressed() { + delegate?.savedPaymentPickerCell(self, didTapMenuButton: menuButton) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if menuButtonFrame.contains(point) { + return menuButton + } + + return bounds.contains(point) ? self : nil + } + + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + + guard let touchLocation = touches.first?.location(in: self) else { + return + } + + if bounds.contains(touchLocation) { + delegate?.savedPaymentPickerCellDidSelect(self) + } + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift new file mode 100644 index 00000000000..5fe2fe5bcc5 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-CellContentView.swift @@ -0,0 +1,138 @@ +// +// LinkPaymentMethodPicker-CellContentView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 11/19/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripePaymentsUI +@_spi(STP) import StripeUICore +import UIKit + +extension LinkPaymentMethodPicker { + + final class CellContentView: UIView { + struct Constants { + static let contentSpacing: CGFloat = 12 + static let iconSize: CGSize = CardBrandView.targetIconSize + static let maxFontSize: CGFloat = 20 + } + + var paymentMethod: ConsumerPaymentDetails? { + didSet { + switch paymentMethod?.details { + case .card: +// TODO(link): Needs refactor +// case .card(let card): +// cardBrandView.cardBrand = card.stpBrand + bankIconView.isHidden = true + cardBrandView.isHidden = false + primaryLabel.text = paymentMethod?.paymentSheetLabel + secondaryLabel.text = nil + secondaryLabel.isHidden = true + case .bankAccount(let bankAccount): + bankIconView.image = PaymentSheetImageLibrary.bankIcon(for: bankAccount.iconCode) + cardBrandView.isHidden = true + bankIconView.isHidden = false + primaryLabel.text = bankAccount.name + secondaryLabel.text = paymentMethod?.paymentSheetLabel + secondaryLabel.isHidden = false + case .none, .unparsable: + cardBrandView.isHidden = true + bankIconView.isHidden = true + primaryLabel.text = nil + secondaryLabel.text = nil + secondaryLabel.isHidden = true + } + } + } + + private lazy var bankIconView: UIImageView = { + let iconView = UIImageView() + iconView.contentMode = .scaleAspectFit + return iconView + }() + + private lazy var cardBrandView: CardBrandView = CardBrandView(centerHorizontally: true) + + private let primaryLabel: UILabel = { + let label = UILabel() + label.adjustsFontForContentSizeCategory = true + label.font = LinkUI.font(forTextStyle: .bodyEmphasized, maximumPointSize: Constants.maxFontSize) + label.textColor = .linkPrimaryText + return label + }() + + private let secondaryLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .caption, maximumPointSize: Constants.maxFontSize) + label.textColor = .linkSecondaryText + return label + }() + + private lazy var iconContainerView: UIView = { + let view = UIView() + bankIconView.translatesAutoresizingMaskIntoConstraints = false + cardBrandView.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(bankIconView) + view.addSubview(cardBrandView) + + let cardBrandSize = cardBrandView.size(for: Constants.iconSize) + NSLayoutConstraint.activate([ + view.widthAnchor.constraint(equalToConstant: max(Constants.iconSize.width, cardBrandSize.width)), + view.heightAnchor.constraint(equalToConstant: max(Constants.iconSize.height, cardBrandSize.height)), + + bankIconView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor), + bankIconView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor), + bankIconView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor), + bankIconView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor), + bankIconView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + bankIconView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + + cardBrandView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor), + cardBrandView.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor), + cardBrandView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor), + cardBrandView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor), + cardBrandView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + cardBrandView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + + cardBrandView.widthAnchor.constraint(equalToConstant: cardBrandSize.width), + cardBrandView.heightAnchor.constraint(equalToConstant: cardBrandSize.height), + ]) + + return view + }() + + private lazy var stackView: UIStackView = { + let labelStackView = UIStackView(arrangedSubviews: [ + primaryLabel, + secondaryLabel, + ]) + labelStackView.axis = .vertical + labelStackView.alignment = .leading + labelStackView.spacing = 0 + + let stackView = UIStackView(arrangedSubviews: [ + iconContainerView, + labelStackView, + ]) + + stackView.spacing = Constants.contentSpacing + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + addAndPinSubview(stackView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift new file mode 100644 index 00000000000..3064dd16451 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-Header.swift @@ -0,0 +1,194 @@ +// +// LinkPaymentMethodPicker-Header.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/22/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeUICore +import UIKit + +extension LinkPaymentMethodPicker { + + final class Header: UIControl { + struct Constants { + static let contentSpacing: CGFloat = 16 + static let chevronSize: CGSize = .init(width: 24, height: 24) + static let collapsedInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) + static let expandedInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 4, trailing: 20) + } + + /// The selected payment method. + var selectedPaymentMethod: ConsumerPaymentDetails? { + didSet { + contentView.paymentMethod = selectedPaymentMethod + updateAccessibilityContent() + } + } + + var isExpanded: Bool = false { + didSet { + setNeedsLayout() + updateChevron() + updateAccessibilityContent() + } + } + + override var isHighlighted: Bool { + didSet { + if isHighlighted && !isExpanded { + backgroundColor = .linkControlHighlight + } else { + backgroundColor = .clear + } + } + } + + private let payWithLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .body) + label.textColor = .linkSecondaryText + label.text = STPLocalizedString("Payment", "Label for a section displaying payment details.") + label.adjustsFontForContentSizeCategory = true + return label + }() + + private let headingLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .bodyEmphasized) + label.textColor = .linkPrimaryText + label.text = STPLocalizedString( + "Payment methods", + "Title for a section listing one or more payment methods." + ) + label.adjustsFontForContentSizeCategory = true + return label + }() + + private let contentView = CellContentView() + + private let cardNumberLabel: UILabel = { + let label = UILabel() + label.font = UIFont.monospacedDigitSystemFont(ofSize: 14, weight: .medium) + .scaled(withTextStyle: .body, maximumPointSize: 20) + return label + }() + + private lazy var chevron: UIImageView = { + let chevron = UIImageView(image: StripeUICore.Image.icon_chevron_down.makeImage(template: true)) + chevron.contentMode = .center + + NSLayoutConstraint.activate([ + chevron.widthAnchor.constraint(equalToConstant: Constants.chevronSize.width), + chevron.heightAnchor.constraint(equalToConstant: Constants.chevronSize.height), + ]) + + return chevron + }() + + private lazy var paymentInfoStackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + payWithLabel, + contentView, + ]) + + stackView.alignment = .center + stackView.setCustomSpacing(Constants.contentSpacing, after: payWithLabel) + stackView.translatesAutoresizingMaskIntoConstraints = false + + return stackView + }() + + private lazy var stackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + paymentInfoStackView, + headingLabel, + chevron, + ]) + + stackView.axis = .horizontal + stackView.spacing = Constants.contentSpacing + stackView.distribution = .equalSpacing + stackView.alignment = .center + stackView.isLayoutMarginsRelativeArrangement = true + stackView.translatesAutoresizingMaskIntoConstraints = false + + return stackView + }() + + override init(frame: CGRect) { + super.init(frame: .zero) + + addSubview(stackView) + + NSLayoutConstraint.activate([ + // Stack view + stackView.topAnchor.constraint(equalTo: topAnchor), + stackView.bottomAnchor.constraint(equalTo: bottomAnchor), + stackView.leadingAnchor.constraint(equalTo: leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: trailingAnchor), + ]) + + isAccessibilityElement = true + accessibilityTraits = .button + + updateChevron() + updateAccessibilityContent() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func updateChevron() { + if isExpanded { + chevron.transform = CGAffineTransform(rotationAngle: .pi) + chevron.tintColor = .linkPrimaryText + } else { + chevron.transform = .identity + chevron.tintColor = .linkSecondaryText + } + } + + private func updateAccessibilityContent() { + if isExpanded { + accessibilityLabel = headingLabel.text + accessibilityHint = STPLocalizedString( + "Tap to close", + "Accessibility hint to tell the user that they can tap to hide additional content." + ) + } else { + accessibilityLabel = selectedPaymentMethod?.accessibilityDescription + accessibilityHint = STPLocalizedString( + "Tap to expand", + "Accessibility hint to tell the user that they can tap to reveal additional content." + ) + } + } + + override func layoutSubviews() { + super.layoutSubviews() + + if isExpanded { + paymentInfoStackView.isHidden = true + headingLabel.isHidden = false + stackView.directionalLayoutMargins = Constants.expandedInsets + } else { + paymentInfoStackView.isHidden = false + headingLabel.isHidden = true + stackView.directionalLayoutMargins = Constants.collapsedInsets + } + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.point(inside: point, with: event) { + return self + } + + return nil + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift new file mode 100644 index 00000000000..b2078ae3046 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker-RadioButton.swift @@ -0,0 +1,116 @@ +// +// LinkPaymentMethodPicker-RadioButton.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 11/15/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +extension LinkPaymentMethodPicker { + + final class RadioButton: UIView { + struct Constants { + static let diameter: CGFloat = 20 + static let innerDiameter: CGFloat = 8 + static let borderWidth: CGFloat = 1 + } + + public var isOn: Bool = false { + didSet { + update() + } + } + + public var borderColor: UIColor = .linkControlBorder { + didSet { + applyStyling() + } + } + + /// Layer for the "off" state. + private let offLayer: CALayer = { + let layer = CALayer() + layer.bounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter) + layer.cornerRadius = Constants.diameter / 2 + layer.borderWidth = Constants.borderWidth + layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + return layer + }() + + /// Layer for the "on" state. + private let onLayer: CALayer = { + let layer = CALayer() + layer.bounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter) + layer.cornerRadius = Constants.diameter / 2 + layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + + let innerCircle = CALayer() + innerCircle.backgroundColor = UIColor.white.cgColor + innerCircle.cornerRadius = Constants.innerDiameter / 2 + innerCircle.bounds = CGRect(x: 0, y: 0, width: Constants.innerDiameter, height: Constants.innerDiameter) + innerCircle.anchorPoint = CGPoint(x: 0.5, y: 0.5) + + // Add and center inner circle + layer.addSublayer(innerCircle) + innerCircle.position = CGPoint(x: layer.bounds.midX, y: layer.bounds.midY) + + return layer + }() + + override var intrinsicContentSize: CGSize { + return CGSize(width: Constants.diameter, height: Constants.diameter) + } + + init() { + super.init(frame: .zero) + layer.addSublayer(offLayer) + layer.addSublayer(onLayer) + update() + applyStyling() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + applyStyling() + } + + override func layoutSubviews() { + offLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) + onLayer.position = CGPoint(x: bounds.midX, y: bounds.midY) + } + + override func tintColorDidChange() { + super.tintColorDidChange() + applyStyling() + } + +#if !os(visionOS) + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + applyStyling() + } +#endif + + // MARK: - Private methods + + private func update() { + CATransaction.begin() + CATransaction.setDisableActions(true) + offLayer.isHidden = isOn + onLayer.isHidden = !isOn + CATransaction.commit() + } + + private func applyStyling() { + CATransaction.begin() + CATransaction.setDisableActions(true) + offLayer.borderColor = borderColor.cgColor + onLayer.backgroundColor = tintColor.cgColor + CATransaction.commit() + } + + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift new file mode 100644 index 00000000000..805777205e4 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Components/PaymentMethodPicker/LinkPaymentMethodPicker.swift @@ -0,0 +1,320 @@ +// +// LinkPaymentMethodPicker.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 10/25/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeUICore + +protocol LinkPaymentMethodPickerDelegate: AnyObject { + func paymentMethodPickerDidChange(_ picker: LinkPaymentMethodPicker) + + func paymentMethodPicker( + _ picker: LinkPaymentMethodPicker, + showMenuForItemAt index: Int, + sourceRect: CGRect + ) + + func paymentDetailsPickerDidTapOnAddPayment(_ picker: LinkPaymentMethodPicker) +} + +protocol LinkPaymentMethodPickerDataSource: AnyObject { + + /// Returns the total number of payment methods. + /// - Returns: Payment method count + func numberOfPaymentMethods(in picker: LinkPaymentMethodPicker) -> Int + + /// Returns the payment method at the specific index. + /// - Returns: Payment method. + func paymentPicker( + _ picker: LinkPaymentMethodPicker, + paymentMethodAt index: Int + ) -> ConsumerPaymentDetails + +} + +/// For internal SDK use only +@objc(STP_Internal_LinkPaymentMethodPicker) +final class LinkPaymentMethodPicker: UIView { + weak var delegate: LinkPaymentMethodPickerDelegate? + weak var dataSource: LinkPaymentMethodPickerDataSource? + + var selectedIndex: Int = 0 { + didSet { + updateHeaderView() + } + } + + var supportedPaymentMethodTypes = Set(ConsumerPaymentDetails.DetailsType.allCases) + + var selectedPaymentMethod: ConsumerPaymentDetails? { + let count = dataSource?.numberOfPaymentMethods(in: self) ?? 0 + + guard selectedIndex >= 0 && selectedIndex < count else { + return nil + } + + return dataSource?.paymentPicker(self, paymentMethodAt: selectedIndex) + } + + private var needsDataReload: Bool = true + + private lazy var stackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + headerView, + listView, + ]) + + stackView.axis = .vertical + stackView.clipsToBounds = true + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private let headerView = Header() + + private lazy var listView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [ + addPaymentMethodButton + ]) + + stackView.axis = .vertical + stackView.distribution = .equalSpacing + stackView.clipsToBounds = true + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + #if !os(visionOS) + private let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .medium) + private let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + #endif + + private let addPaymentMethodButton = AddButton() + + override init(frame: CGRect) { + super.init(frame: .zero) + addAndPinSubview(stackView) + setup() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup() { + clipsToBounds = true + accessibilityIdentifier = "Stripe.Link.PaymentMethodPicker" + + layer.cornerRadius = 16 + layer.borderWidth = 1 + layer.borderColor = UIColor.linkControlBorder.cgColor + tintColor = .linkBrandDark + backgroundColor = .linkControlBackground + + headerView.addTarget(self, action: #selector(onHeaderTapped(_:)), for: .touchUpInside) + headerView.layer.zPosition = 1 + + listView.isHidden = true + listView.layer.zPosition = 0 + + addPaymentMethodButton.addTarget(self, action: #selector(onAddPaymentButtonTapped(_:)), for: .touchUpInside) + } + + override func layoutSubviews() { + super.layoutSubviews() + reloadDataIfNeeded() + } + +#if !os(visionOS) + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + layer.borderColor = UIColor.linkControlBorder.cgColor + } +#endif + + func setExpanded(_ expanded: Bool, animated: Bool) { + headerView.isExpanded = expanded + + // Prevent double header animation + if headerView.isExpanded { + // TODO(ramont): revise layout margin placement and remove conditional + setNeedsLayout() + layoutIfNeeded() + } else { + headerView.layoutIfNeeded() + } + + if headerView.isExpanded { + stackView.showArrangedSubview(at: 1, animated: animated) + } else { + stackView.hideArrangedSubview(at: 1, animated: animated) + } + } + + private func updateHeaderView() { + headerView.selectedPaymentMethod = selectedPaymentMethod + } + +} + +private extension LinkPaymentMethodPicker { + + @objc func onHeaderTapped(_ sender: Header) { + setExpanded(!sender.isExpanded, animated: true) +#if !os(visionOS) + impactFeedbackGenerator.impactOccurred() +#endif + } + + @objc func onAddPaymentButtonTapped(_ sender: AddButton) { + delegate?.paymentDetailsPickerDidTapOnAddPayment(self) + } + +} + +// MARK: - Data Loading + +extension LinkPaymentMethodPicker { + + func reloadData() { + needsDataReload = false + + addMissingPaymentMethodCells() + + let count = dataSource?.numberOfPaymentMethods(in: self) ?? 0 + if count == 0 { + headerView.isHidden = true + listView.isHidden = false + } + + for index in 0.. listView.arrangedSubviews.count - 1 { + let cell = Cell() + cell.delegate = self + + let index = listView.arrangedSubviews.count - 1 + listView.insertArrangedSubview(cell, at: index) + } + + for (index, subview) in listView.arrangedSubviews.enumerated() { + subview.layer.zPosition = CGFloat(-index) + } + + headerView.selectedPaymentMethod = selectedPaymentMethod + } + +} + +extension LinkPaymentMethodPicker { + + func index(for cell: Cell) -> Int? { + return listView.arrangedSubviews.firstIndex(of: cell) + } + + func removePaymentMethod(at index: Int, animated: Bool) { + isUserInteractionEnabled = false + + listView.removeArrangedSubview(at: index, animated: true) { + let count = self.dataSource?.numberOfPaymentMethods(in: self) ?? 0 + + if index < self.selectedIndex { + self.selectedIndex = max(self.selectedIndex - 1, 0) + } + + self.selectedIndex = max(min(self.selectedIndex, count - 1), 0) + + self.reloadData() + self.delegate?.paymentMethodPickerDidChange(self) + self.isUserInteractionEnabled = true + } + } + +} + +// MARK: - Cell delegate + +extension LinkPaymentMethodPicker: LinkPaymentMethodPickerCellDelegate { + + func savedPaymentPickerCellDidSelect(_ savedCardView: Cell) { + if let newIndex = index(for: savedCardView) { + let oldIndex = selectedIndex + selectedIndex = newIndex + + reloadCell(at: oldIndex) + reloadCell(at: newIndex) + +#if !os(visionOS) + selectionFeedbackGenerator.selectionChanged() +#endif + + delegate?.paymentMethodPickerDidChange(self) + } + } + + func savedPaymentPickerCell(_ cell: Cell, didTapMenuButton button: UIButton) { + guard let index = index(for: cell) else { + assertionFailure("Index not found") + return + } + + let sourceRect = button.convert(button.bounds, to: self) + + delegate?.paymentMethodPicker(self, showMenuForItemAt: index, sourceRect: sourceRect) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Elements/LinkCardEditElement.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Elements/LinkCardEditElement.swift new file mode 100644 index 00000000000..61eea7e0a25 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Elements/LinkCardEditElement.swift @@ -0,0 +1,225 @@ +// +// LinkCardEditElement.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 9/30/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripePayments +@_spi(STP) import StripePaymentsUI +@_spi(STP) import StripeUICore +import UIKit + +// TODO(ramont): Remove after migrating to modern bindings +fileprivate extension ConsumerPaymentDetails { + var cardDetails: Details.Card? { + switch details { + case .card(let details): + return details + case .bankAccount: + return nil + case .unparsable: + return nil + } + } +} + +final class LinkCardEditElement: Element { + let collectsUserInput: Bool = true + + struct Params { + let expiryDate: CardExpiryDate + let cvc: String + let billingDetails: STPPaymentMethodBillingDetails + let setAsDefault: Bool + } + + var view: UIView { + return formElement.view + } + + weak var delegate: ElementDelegate? + + var validationState: ElementValidationState { + return formElement.validationState + } + + let paymentMethod: ConsumerPaymentDetails + + let configuration: PaymentSheet.Configuration + + let theme: ElementsAppearance = LinkUI.appearance.asElementsTheme + + var params: Params? { + guard validationState.isValid, + let expiryDate = CardExpiryDate(expiryDateElement.text) else { + return nil + } + + // TODO(ramont): Replace `STPPaymentMethodBillingDetails` with a custom struct for Link. + // This matches the object that was returned by CardDetailsEditView, but won't work + // with `collectionMode: .all`, because extra fields won't match what expected by Link. + let billingDetails = STPPaymentMethodBillingDetails() + billingDetails.name = nameElement?.text + billingDetails.email = emailElement?.text + billingDetails.nonnil_address.country = billingAddressSection?.selectedCountryCode + billingDetails.nonnil_address.line1 = billingAddressSection?.line1?.text + billingDetails.nonnil_address.line2 = billingAddressSection?.line2?.text + billingDetails.nonnil_address.city = billingAddressSection?.city?.text + billingDetails.nonnil_address.state = billingAddressSection?.state?.rawData + billingDetails.nonnil_address.postalCode = billingAddressSection?.postalCode?.text + + return Params( + expiryDate: expiryDate, + cvc: cvcElement.text, + billingDetails: billingDetails, + setAsDefault: checkboxElement.checkboxButton.isSelected + ) + } + + private lazy var emailElement: TextFieldElement? = { + guard configuration.billingDetailsCollectionConfiguration.email == .always else { return nil } + + return TextFieldElement.makeEmail(defaultValue: nil, theme: theme) + }() + + private lazy var contactInformationSection: SectionElement? = { + guard let emailElement = emailElement else { return nil } + + return SectionElement( + title: STPLocalizedString("Contact information", "Title for the contact information section"), + elements: [emailElement], + theme: theme) + }() + + private lazy var nameElement: TextFieldElement? = { + guard configuration.billingDetailsCollectionConfiguration.name == .always else { return nil } + + return TextFieldElement.makeName( + label: STPLocalizedString("Name on card", "Label for name on card field"), + defaultValue: nil, + theme: theme) + }() + + private lazy var panElement: TextFieldElement = { + let panElement = TextFieldElement( + configuration: PANConfiguration(paymentMethod: paymentMethod), + theme: theme + ) + panElement.view.isUserInteractionEnabled = false + return panElement + }() + + private lazy var cvcElement = TextFieldElement( + configuration: TextFieldElement.CVCConfiguration( + cardBrandProvider: { [weak self] in + self?.paymentMethod.cardDetails?.stpBrand ?? .unknown + } + ), + theme: theme + ) + + private lazy var expiryDateElement = TextFieldElement( + configuration: TextFieldElement.ExpiryDateConfiguration(), + theme: theme + ) + + private lazy var checkboxElement = CheckboxElement( + theme: theme, + label: STPLocalizedString( + "Set as default payment method", + "Label of a checkbox that when checked makes a payment method as the default one." + ), + isSelectedByDefault: paymentMethod.isDefault + ) + + private lazy var formElement: FormElement = { + let formElement = FormElement( + elements: [ + contactInformationSection, + cardSection, + billingAddressSection, + checkboxElement, + ], + theme: theme + ) + formElement.delegate = self + return formElement + }() + + private lazy var cardSection: SectionElement = { + let allElements: [Element?] = [ + nameElement, + panElement, + SectionElement.MultiElementRow([expiryDateElement, cvcElement], theme: theme), + ] + let elements = allElements.compactMap { $0 } + + return SectionElement( + title: String.Localized.card_information, + elements: elements, + theme: theme + ) + }() + + private lazy var billingAddressSection: AddressSectionElement? = { + guard configuration.billingDetailsCollectionConfiguration.address != .never else { return nil } + + return AddressSectionElement( + title: String.Localized.billing_address, + collectionMode: configuration.billingDetailsCollectionConfiguration.address == .full + ? .all() + : .countryAndPostal(), + theme: theme + ) + }() + + init(paymentMethod: ConsumerPaymentDetails, configuration: PaymentSheet.Configuration) { + self.paymentMethod = paymentMethod + self.configuration = configuration + + if let expiryDate = paymentMethod.cardDetails?.expiryDate { + self.expiryDateElement.setText(expiryDate.displayString) + } + + self.checkboxElement.checkboxButton.isHidden = paymentMethod.isDefault + } + +} + +extension LinkCardEditElement: ElementDelegate { + + func didUpdate(element: Element) { + delegate?.didUpdate(element: self) + } + + func continueToNextField(element: Element) { + delegate?.continueToNextField(element: self) + } + +} + +private extension LinkCardEditElement { + + struct PANConfiguration: TextFieldElementConfiguration { + let paymentMethod: ConsumerPaymentDetails + + var label: String { + String.Localized.card_number + } + + var defaultValue: String? { + paymentMethod.cardDetails.map { "•••• \($0.last4)" } + } + + func accessoryView(for text: String, theme: ElementsAppearance) -> UIView? { + paymentMethod.cardDetails.map { cardDetails in + let image = STPImageLibrary.cardBrandImage(for: cardDetails.stpBrand) + return UIImageView(image: image) + } + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationController.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationController.swift new file mode 100644 index 00000000000..8de873a7703 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationController.swift @@ -0,0 +1,49 @@ +// +// LinkVerificationController.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 7/23/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import UIKit + +/// Standalone verification controller. +final class LinkVerificationController { + + typealias CompletionBlock = (LinkVerificationViewController.VerificationResult) -> Void + + private var completion: CompletionBlock? + + private var selfRetainer: LinkVerificationController? + private let verificationViewController: LinkVerificationViewController + + init(mode: LinkVerificationView.Mode = .modal, linkAccount: PaymentSheetLinkAccount) { + self.verificationViewController = LinkVerificationViewController(mode: mode, linkAccount: linkAccount) + verificationViewController.delegate = self + } + + func present( + from presentingController: UIViewController, + completion: @escaping CompletionBlock + ) { + self.selfRetainer = self + self.completion = completion + presentingController.present(verificationViewController, animated: true) + } + +} + +extension LinkVerificationController: LinkVerificationViewControllerDelegate { + + func verificationController( + _ controller: LinkVerificationViewController, + didFinishWithResult result: LinkVerificationViewController.VerificationResult + ) { + controller.dismiss(animated: true) { [weak self] in + self?.completion?(result) + self?.selfRetainer = nil + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-Header.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-Header.swift new file mode 100644 index 00000000000..a506189345c --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-Header.swift @@ -0,0 +1,69 @@ +// +// LinkVerificationView-Header.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 12/1/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripePayments +@_spi(STP) import StripeUICore +import UIKit + +extension LinkVerificationView { + + final class Header: UIView { + struct Constants { + static let logoHeight: CGFloat = 18 + } + + private let logoView: UIImageView = { + let logoView = UIImageView(image: Image.link_logo.makeImage(template: true)) + logoView.translatesAutoresizingMaskIntoConstraints = false + logoView.isAccessibilityElement = true + logoView.accessibilityTraits = .header + logoView.accessibilityLabel = STPPaymentMethodType.link.displayName + return logoView + }() + + let closeButton: UIButton = { + let button = UIButton(type: .system) + button.setImage(Image.icon_cancel.makeImage(template: true), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.accessibilityLabel = String.Localized.close + return button + }() + + override var intrinsicContentSize: CGSize { + return CGSize(width: UIView.noIntrinsicMetric, height: 24) + } + + init() { + super.init(frame: .zero) + + addSubview(logoView) + addSubview(closeButton) + + NSLayoutConstraint.activate([ + // Logo + logoView.centerXAnchor.constraint(equalTo: centerXAnchor), + logoView.centerYAnchor.constraint(equalTo: centerYAnchor), + logoView.heightAnchor.constraint(equalToConstant: Constants.logoHeight), + + // Button + closeButton.topAnchor.constraint(equalTo: topAnchor), + closeButton.rightAnchor.constraint(equalTo: rightAnchor), + closeButton.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + + tintColor = .linkNavTint + logoView.tintColor = .linkNavLogo + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-LogoutView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-LogoutView.swift new file mode 100644 index 00000000000..0bafc76033c --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView-LogoutView.swift @@ -0,0 +1,65 @@ +// +// LinkVerificationView-LogoutView.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 2/4/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore +import UIKit + +extension LinkVerificationView { + + final class LogoutView: UIView { + let linkAccount: PaymentSheetLinkAccountInfoProtocol + + private let font: UIFont = LinkUI.font(forTextStyle: .detail) + + private lazy var label: UILabel = { + let label = UILabel() + label.font = font + label.adjustsFontForContentSizeCategory = true + label.textColor = .linkSecondaryText + label.lineBreakMode = .byTruncatingMiddle + label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + label.text = String( + format: STPLocalizedString( + "Not %@?", + "Text of a label for confirming an email address. E.g., 'Not user@example.com?'" + ), + linkAccount.email + ) + return label + }() + + private(set) lazy var button: Button = { + let button = Button(configuration: .linkPlain(), title: STPLocalizedString( + "Change email", + "Title for a button that allows the user to use a different email in the signup flow." + )) + button.configuration.font = font + return button + }() + + init(linkAccount: PaymentSheetLinkAccountInfoProtocol) { + self.linkAccount = linkAccount + super.init(frame: .zero) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + let stackView = UIStackView(arrangedSubviews: [label, button]) + stackView.spacing = LinkUI.tinyContentSpacing + stackView.alignment = .center + stackView.distribution = .equalSpacing + addAndPinSubview(stackView) + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView.swift new file mode 100644 index 00000000000..77ff077d193 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationView.swift @@ -0,0 +1,271 @@ +// +// LinkVerificationView.swift +// StripePaymentSheet +// +// Created by Cameron Sabol on 3/24/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore + +/// :nodoc: +protocol LinkVerificationViewDelegate: AnyObject { + func verificationViewDidCancel(_ view: LinkVerificationView) + func verificationViewResendCode(_ view: LinkVerificationView) + func verificationViewLogout(_ view: LinkVerificationView) + func verificationView(_ view: LinkVerificationView, didEnterCode code: String) +} + +/// For internal SDK use only +@objc(STP_Internal_LinkVerificationView) +final class LinkVerificationView: UIView { + struct Constants { + static let edgeMargin: CGFloat = 20 + } + + enum Mode { + case modal + case inlineLogin + case embedded + } + + weak var delegate: LinkVerificationViewDelegate? + + private let mode: Mode + + let linkAccount: PaymentSheetLinkAccountInfoProtocol + + var sendingCode: Bool = false { + didSet { + resendCodeButton.isLoading = sendingCode + } + } + + var errorMessage: String? { + didSet { + errorLabel.text = errorMessage + errorLabel.setHiddenIfNecessary(errorMessage == nil) + } + } + + private lazy var header: Header = { + let header = Header() + header.closeButton.addTarget(self, action: #selector(didSelectCancel), for: .touchUpInside) + return header + }() + + private lazy var headingLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 0 + label.textAlignment = .center + label.font = LinkUI.font(forTextStyle: .title) + label.textColor = .linkPrimaryText + label.text = mode.headingText + label.adjustsFontForContentSizeCategory = true + return label + }() + + private lazy var bodyLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 0 + label.textAlignment = .center + label.font = mode.bodyFont + label.textColor = .linkSecondaryText + label.text = mode.bodyText(redactedPhoneNumber: linkAccount.redactedPhoneNumber ?? "") + label.adjustsFontForContentSizeCategory = true + return label + }() + + private(set) lazy var codeField: OneTimeCodeTextField = { + let codeField = OneTimeCodeTextField(configuration: + .init(numberOfDigits: 6), + theme: LinkUI.appearance.asElementsTheme) + codeField.addTarget(self, action: #selector(oneTimeCodeFieldChanged(_:)), for: .valueChanged) + return codeField + }() + + private let errorLabel: UILabel = { + let label = UILabel() + label.font = LinkUI.font(forTextStyle: .detail) + label.textColor = .systemRed + label.numberOfLines = 0 + label.textAlignment = .center + label.isHidden = true + return label + }() + + private lazy var codeFieldContainer: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [codeField, errorLabel]) + stackView.axis = .vertical + stackView.spacing = LinkUI.smallContentSpacing + return stackView + }() + + private lazy var resendCodeButton: Button = { + let button = Button(configuration: .linkBordered(), title: STPLocalizedString( + "Resend code", + "Label for a button that re-sends the a login code when tapped" + )) + button.addTarget(self, action: #selector(resendCodeTapped(_:)), for: .touchUpInside) + return button + }() + + private lazy var logoutView: LogoutView = { + let logoutView = LogoutView(linkAccount: linkAccount) + logoutView.button.addTarget(self, action: #selector(didTapOnLogout(_:)), for: .touchUpInside) + return logoutView + }() + + required init(mode: Mode, linkAccount: PaymentSheetLinkAccountInfoProtocol) { + self.mode = mode + self.linkAccount = linkAccount + super.init(frame: .zero) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc + func oneTimeCodeFieldChanged(_ sender: OneTimeCodeTextField) { + // Clear error message when the field changes. + errorMessage = nil + + if sender.isComplete { + delegate?.verificationView(self, didEnterCode: sender.value) + } + } + + @objc + func didSelectCancel() { + delegate?.verificationViewDidCancel(self) + } + + @objc + func didTapOnLogout(_ sender: UIButton) { + delegate?.verificationViewLogout(self) + } + + @objc + func resendCodeTapped(_ sender: UIButton) { + delegate?.verificationViewResendCode(self) + } +} + +private extension LinkVerificationView { + + var arrangedSubViews: [UIView] { + switch mode { + case .modal, .inlineLogin: + return [ + header, + headingLabel, + bodyLabel, + codeFieldContainer, + resendCodeButton, + ] + case .embedded: + return [ + headingLabel, + bodyLabel, + codeFieldContainer, + logoutView, + resendCodeButton, + ] + } + } + + func setupUI() { + directionalLayoutMargins = .insets(amount: Constants.edgeMargin) + + let stackView = UIStackView(arrangedSubviews: arrangedSubViews) + stackView.spacing = LinkUI.smallContentSpacing + stackView.axis = .vertical + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + + // Spacing + stackView.setCustomSpacing(Constants.edgeMargin, after: header) + stackView.setCustomSpacing(LinkUI.extraLargeContentSpacing, after: bodyLabel) + stackView.setCustomSpacing(LinkUI.largeContentSpacing, after: codeFieldContainer) + + addSubview(stackView) + + var constraints: [NSLayoutConstraint] = [ + // Stack view + stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor), + stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), + stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + + // OTC field + codeFieldContainer.leadingAnchor.constraint(equalTo: stackView.leadingAnchor), + codeFieldContainer.trailingAnchor.constraint(equalTo: stackView.trailingAnchor), + ] + + if mode.requiresModalPresentation { + constraints.append(contentsOf: [ + // Header + header.leadingAnchor.constraint(equalTo: stackView.leadingAnchor), + header.trailingAnchor.constraint(equalTo: stackView.trailingAnchor), + ]) + } + + NSLayoutConstraint.activate(constraints) + backgroundColor = .systemBackground + } +} + +extension LinkVerificationView.Mode { + + var requiresModalPresentation: Bool { + switch self { + case .modal, .inlineLogin: + return true + case .embedded: + return false + } + } + + var headingText: String { + switch self { + case .modal: + return STPLocalizedString( + "Use your saved info to check out faster", + "Two factor authentication screen heading" + ) + case .inlineLogin: + return STPLocalizedString( + "Sign in to your Link account", + "Two factor authentication screen heading" + ) + case .embedded: + return STPLocalizedString( + "Enter your verification code", + "Two factor authentication screen heading" + ) + } + } + + var bodyFont: UIFont { + switch self { + case .modal, .inlineLogin: + return LinkUI.font(forTextStyle: .detail) + case .embedded: + return LinkUI.font(forTextStyle: .body) + } + } + + func bodyText(redactedPhoneNumber: String) -> String { + let format = STPLocalizedString( + "Enter the code sent to %@ to use Link to pay by default.", + "Instructs the user to enter the code sent to their phone number in order to login to Link" + ) + return String(format: format, redactedPhoneNumber) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController-PresentationController.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController-PresentationController.swift new file mode 100644 index 00000000000..fbd2417c131 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController-PresentationController.swift @@ -0,0 +1,211 @@ +// +// LinkVerificationViewController-PresentationController.swift +// StripePaymentSheet +// +// Created by Ramon Torres on 11/7/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +@_spi(STP) import StripeUICore +import UIKit + +extension LinkVerificationViewController { + + /// For internal SDK use only + @objc(STP_Internal_LinkPresentationController) + final class PresentationController: UIPresentationController { + struct Constants { + static let padding: CGFloat = 16 + static let maxWidth: CGFloat = 400 + static let maxHeight: CGFloat = 410 + static let targetHeight: CGFloat = 332 + } + + /// A bottom inset necessary for the presented view to avoid the software keyboard. + private var bottomInset: CGFloat = 0 + + /// An area where it is safe to present the modal on. + /// + /// This is always equals to the container view safe area minus `padding` on eat edge. + private var safeFrame: CGRect { + guard let containerView = containerView else { + return .zero + } + + return containerView.bounds + .inset(by: containerView.safeAreaInsets) + .insetBy(dx: Constants.padding, dy: Constants.padding) + } + + private lazy var dimmingView: UIView = { + let view = UIView() + view.backgroundColor = UIColor.black.withAlphaComponent(0.5) + return view + }() + + private var contentView: UIView? { + if let scrollView = presentedView as? UIScrollView { + return scrollView.subviews.first + } + + return presentedView + } + + override var frameOfPresentedViewInContainerView: CGRect { + guard let containerView = containerView else { + return .zero + } + + return calculateModalFrame(forContainerSize: containerView.bounds.size) + } + + func updatePresentedViewFrame() { + presentedView?.frame = frameOfPresentedViewInContainerView + } + + private func calculateModalFrame(forContainerSize containerSize: CGSize) -> CGRect { + guard let contentView = contentView else { + return .zero + } + + let targetSize = CGSize( + width: min(Constants.maxWidth, safeFrame.width), + height: Constants.targetHeight + ) + + let fittingSize = contentView.systemLayoutSizeFitting( + targetSize, + withHorizontalFittingPriority: .required, + verticalFittingPriority: .defaultLow + ) + + let actualSize = CGSize( + width: fittingSize.width, + height: min(fittingSize.height, Constants.maxHeight) + ) + + return CGRect( + x: (containerSize.width - actualSize.width) / 2, + y: max((containerSize.height - actualSize.height - bottomInset) / 2, Constants.padding), + width: actualSize.width, + height: actualSize.height + ).integral + } + + override func containerViewWillLayoutSubviews() { + super.containerViewWillLayoutSubviews() + + guard let containerView = containerView else { + return + } + + dimmingView.frame = containerView.bounds + presentedView?.frame = frameOfPresentedViewInContainerView + } + + override func presentationTransitionWillBegin() { + super.presentationTransitionWillBegin() + + guard let containerView = containerView, + let transitionCoordinator = presentedViewController.transitionCoordinator else { + return + } + + containerView.insertSubview(dimmingView, at: 0) + dimmingView.frame = containerView.bounds + dimmingView.alpha = 0 + + transitionCoordinator.animate { _ in + self.dimmingView.alpha = 1 + } + } + + override func dismissalTransitionWillBegin() { + super.dismissalTransitionWillBegin() + guard let transitionCoordinator = presentedViewController.transitionCoordinator else { + return + } + + transitionCoordinator.animate( + alongsideTransition: { _ in + self.dimmingView.alpha = 0.0 + }, + completion: { _ in + self.dimmingView.removeFromSuperview() + } + ) + } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + coordinator.animate { context in + self.presentedView?.frame = self.calculateModalFrame( + forContainerSize: context.containerView.bounds.size + ) + } + } + + override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { + super.willTransition(to: newCollection, with: coordinator) + + coordinator.animate { context in + self.presentedView?.frame = self.calculateModalFrame( + forContainerSize: context.containerView.bounds.size + ) + } + } + + override init( + presentedViewController: UIViewController, + presenting presentingViewController: UIViewController? + ) { + super.init(presentedViewController: presentedViewController, presenting: presentingViewController) + + NotificationCenter.default.addObserver(self, + selector: #selector(keyboardFrameChanged(_:)), + name: UIResponder.keyboardWillChangeFrameNotification, + object: nil) + + NotificationCenter.default.addObserver(self, + selector: #selector(keyboardWillHide(_:)), + name: UIResponder.keyboardWillHideNotification, + object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + } + +} + +// MARK: - Keyboard handling + +extension LinkVerificationViewController.PresentationController { + + @objc func keyboardFrameChanged(_ notification: Notification) { + let userInfo = notification.userInfo + + guard let keyboardFrame = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect, + let containerView = containerView else { + return + } + + let absoluteFrame = containerView.convert(safeFrame, to: containerView.window) + let intersection = absoluteFrame.intersection(keyboardFrame) + + UIView.animateAlongsideKeyboard(notification) { + self.bottomInset = intersection.height + self.presentedView?.frame = self.frameOfPresentedViewInContainerView + } + } + + @objc func keyboardWillHide(_ notification: Notification) { + UIView.animateAlongsideKeyboard(notification) { + self.bottomInset = 0 + self.presentedView?.frame = self.frameOfPresentedViewInContainerView + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController.swift new file mode 100644 index 00000000000..5f4f09b5267 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheet/Source/Internal/Link/Verification/LinkVerificationViewController.swift @@ -0,0 +1,247 @@ +// +// LinkVerificationViewController.swift +// StripePaymentSheet +// +// Created by Cameron Sabol on 3/24/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import UIKit + +@_spi(STP) import StripeCore +@_spi(STP) import StripeUICore + +protocol LinkVerificationViewControllerDelegate: AnyObject { + func verificationController( + _ controller: LinkVerificationViewController, + didFinishWithResult result: LinkVerificationViewController.VerificationResult + ) +} + +/// For internal SDK use only +@objc(STP_Internal_LinkVerificationViewController) +final class LinkVerificationViewController: UIViewController { + enum VerificationResult { + /// Verification was completed successfully. + case completed + /// Verification was canceled by the user. + case canceled + /// Verification failed due to an unrecoverable error. + case failed(Error) + } + + weak var delegate: LinkVerificationViewControllerDelegate? + + let mode: LinkVerificationView.Mode + let linkAccount: PaymentSheetLinkAccount + + private lazy var verificationView: LinkVerificationView = { + guard linkAccount.redactedPhoneNumber != nil else { + preconditionFailure("Verification(2FA) presented without a phone number on file") + } + + let verificationView = LinkVerificationView(mode: mode, linkAccount: linkAccount) + verificationView.delegate = self + verificationView.backgroundColor = .clear + verificationView.translatesAutoresizingMaskIntoConstraints = false + + return verificationView + }() + + private lazy var activityIndicator: ActivityIndicator = { + let activityIndicator = ActivityIndicator(size: .large) + activityIndicator.translatesAutoresizingMaskIntoConstraints = false + return activityIndicator + }() + + private lazy var scrollView = LinkKeyboardAvoidingScrollView() + + required init( + mode: LinkVerificationView.Mode = .modal, + linkAccount: PaymentSheetLinkAccount + ) { + self.mode = mode + self.linkAccount = linkAccount + super.init(nibName: nil, bundle: nil) + + if mode.requiresModalPresentation { + modalPresentationStyle = .custom + transitioningDelegate = TransitioningDelegate.sharedDelegate + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + self.view = scrollView + } + + override func viewDidLoad() { + super.viewDidLoad() + + view.tintColor = .linkBrand + view.backgroundColor = .systemBackground + + view.addSubview(verificationView) + view.addSubview(activityIndicator) + + NSLayoutConstraint.activate([ + // Verification view + verificationView.topAnchor.constraint(equalTo: view.topAnchor), + verificationView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + verificationView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + verificationView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + verificationView.widthAnchor.constraint(equalTo: view.widthAnchor), + // Activity indicator + activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor), + activityIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor), + ]) + + if mode.requiresModalPresentation { + view.layer.masksToBounds = true + view.layer.cornerRadius = LinkUI.cornerRadius + } + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + if let presentationController = presentationController as? PresentationController { + presentationController.updatePresentedViewFrame() + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + activityIndicator.startAnimating() + + if linkAccount.sessionState == .requiresVerification { + verificationView.isHidden = true + + linkAccount.startVerification { [weak self] result in + switch result { + case .success(let collectOTP): + if collectOTP { + self?.activityIndicator.stopAnimating() + self?.verificationView.isHidden = false + self?.verificationView.codeField.becomeFirstResponder() + } else { + // No OTP collection is required. + self?.finish(withResult: .completed) + } + case .failure(let error): + STPAnalyticsClient.sharedClient.logLink2FAStartFailure() + self?.finish(withResult: .failed(error)) + } + } + } else { + verificationView.codeField.becomeFirstResponder() + } + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + STPAnalyticsClient.sharedClient.logLink2FAStart() + } + +} + +/// :nodoc: +extension LinkVerificationViewController: LinkVerificationViewDelegate { + + func verificationViewDidCancel(_ view: LinkVerificationView) { + // Mark email as logged out to prevent automatically showing + // the 2FA modal in future checkout sessions. + linkAccount.markEmailAsLoggedOut() + + STPAnalyticsClient.sharedClient.logLink2FACancel() + finish(withResult: .canceled) + } + + func verificationViewResendCode(_ view: LinkVerificationView) { + view.sendingCode = true + view.errorMessage = nil + + // To resend the code we just start a new verification session. + linkAccount.startVerification { [weak self] (result) in + view.sendingCode = false + + switch result { + case .success: + let toast = LinkToast( + type: .success, + text: STPLocalizedString( + "Code sent", + "Text of a notification shown to the user when a login code is successfully sent via SMS." + ) + ) + toast.show(from: view) + case .failure(let error): + let alertController = UIAlertController( + title: nil, + message: error.localizedDescription, + preferredStyle: .alert + ) + + alertController.addAction(UIAlertAction( + title: String.Localized.ok, + style: .default + )) + + self?.present(alertController, animated: true) + } + } + } + + func verificationViewLogout(_ view: LinkVerificationView) { + STPAnalyticsClient.sharedClient.logLink2FACancel() + finish(withResult: .canceled) + } + + func verificationView(_ view: LinkVerificationView, didEnterCode code: String) { + view.codeField.resignFirstResponder() + + linkAccount.verify(with: code) { [weak self] result in + switch result { + case .success: + self?.finish(withResult: .completed) + STPAnalyticsClient.sharedClient.logLink2FAComplete() + case .failure(let error): + view.codeField.performInvalidCodeAnimation() + view.errorMessage = LinkUtils.getLocalizedErrorMessage(from: error) + STPAnalyticsClient.sharedClient.logLink2FAFailure() + } + } + } + +} + +extension LinkVerificationViewController { + + private func finish(withResult result: VerificationResult) { + // Delete the last "signup email" cookie, if any, after the user completes or declines verification. + LinkAccountService.defaultCookieStore.delete(key: .lastSignupEmail) + delegate?.verificationController(self, didFinishWithResult: result) + } + +} + +// MARK: - Transitioning Delegate + +extension LinkVerificationViewController { + + final class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate { + static let sharedDelegate: TransitioningDelegate = TransitioningDelegate() + + func presentationController(forPresented presented: UIViewController, + presenting: UIViewController?, + source: UIViewController) -> UIPresentationController? { + return PresentationController(presentedViewController: presented, + presenting: presenting) + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift new file mode 100644 index 00000000000..ded3d7b0db0 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkCardEditElementSnapshotTests.swift @@ -0,0 +1,73 @@ +// +// LinkCardEditElementSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 10/3/22. +// Copyright © 2022 Stripe, Inc. All rights reserved. +// + +import UIKit + +@testable@_spi(STP) import StripeCoreTestUtils +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripeUICore + +final class LinkCardEditElementSnapshotTests: STPSnapshotTestCase { + + override func setUp() { + super.setUp() + // self.recordMode = true + + // `LinkCardEditElement` depends on `AddressSectionElement`, which requires + // address specs to be loaded in memory. + let expectation = expectation(description: "Load address specs") + AddressSpecProvider.shared.loadAddressSpecs { + expectation.fulfill() + } + + wait(for: [expectation], timeout: STPTestingNetworkRequestTimeout) + } + + func testDefault() { + let sut = makeSUT(isDefault: true) + verify(sut) + } + + func testNonDefault() { + let sut = makeSUT(isDefault: false) + verify(sut) + } + + func verify( + _ element: LinkCardEditElement, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + element.view.autosizeHeight(width: 340) + STPSnapshotVerifyView(element.view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkCardEditElementSnapshotTests { + + func makeSUT(isDefault: Bool) -> LinkCardEditElement { + let paymentMethod = ConsumerPaymentDetails( + stripeID: "1", + details: .card( + card: .init( + expiryYear: 2032, + expiryMonth: 1, + brand: "visa", + last4: "4242", + checks: nil + ) + ), + isDefault: isDefault + ) + + return LinkCardEditElement(paymentMethod: paymentMethod, configuration: .init()) + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift new file mode 100644 index 00000000000..240a5ffb90c --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkPaymentMethodPickerSnapshotTests.swift @@ -0,0 +1,101 @@ +// +// LinkPaymentMethodPickerSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 11/8/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import StripeCoreTestUtils +import UIKit + +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkPaymentMethodPickerSnapshotTests: STPSnapshotTestCase { + + func testNormal() { + let mockDataSource = MockDataSource() + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.layoutSubviews() + + verify(picker, identifier: "First Option") + + picker.selectedIndex = 1 + verify(picker, identifier: "Second Option") + } + + func testExpanded() { + let mockDataSource = MockDataSource() + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.layoutSubviews() + picker.setExpanded(true, animated: false) + + verify(picker) + } + + func testUnsupportedBankAccount() { + let mockDataSource = MockDataSource() + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.supportedPaymentMethodTypes = [.card] + picker.layoutSubviews() + picker.setExpanded(true, animated: false) + + verify(picker) + } + + func testEmpty() { + let mockDataSource = MockDataSource(empty: true) + + let picker = LinkPaymentMethodPicker() + picker.dataSource = mockDataSource + picker.layoutSubviews() + + verify(picker) + } + + func verify( + _ view: UIView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + view.autosizeHeight(width: 335) + view.backgroundColor = .white + STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkPaymentMethodPickerSnapshotTests { + + fileprivate final class MockDataSource: LinkPaymentMethodPickerDataSource { + let paymentMethods: [ConsumerPaymentDetails] + + init( + empty: Bool = false + ) { + self.paymentMethods = empty ? [] : LinkStubs.paymentMethods() + } + + func numberOfPaymentMethods(in picker: LinkPaymentMethodPicker) -> Int { + return paymentMethods.count + } + + func paymentPicker( + _ picker: LinkPaymentMethodPicker, + paymentMethodAt index: Int + ) -> ConsumerPaymentDetails { + return paymentMethods[index] + } + } + +} diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift new file mode 100644 index 00000000000..2763e508613 --- /dev/null +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/Link/LinkVerificationViewSnapshotTests.swift @@ -0,0 +1,77 @@ +// +// LinkVerificationViewSnapshotTests.swift +// StripeiOS Tests +// +// Created by Ramon Torres on 12/7/21. +// Copyright © 2021 Stripe, Inc. All rights reserved. +// + +import StripeCoreTestUtils +import UIKit + +@testable@_spi(STP) import StripeCore +@testable@_spi(STP) import StripePayments +@testable@_spi(STP) import StripePaymentSheet +@testable@_spi(STP) import StripePaymentsUI + +class LinkVerificationViewSnapshotTests: STPSnapshotTestCase { + + func testModal() { + let sut = makeSUT(mode: .modal) + verify(sut) + } + + func testModalWithErrorMessage() { + let sut = makeSUT(mode: .modal) + sut.errorMessage = "The provided verification code has expired." + verify(sut) + } + + func testInlineLogin() { + let sut = makeSUT(mode: .inlineLogin) + verify(sut) + } + + func testEmbedded() { + let sut = makeSUT(mode: .embedded) + verify(sut) + } + + func verify( + _ view: LinkVerificationView, + identifier: String? = nil, + file: StaticString = #filePath, + line: UInt = #line + ) { + view.autosizeHeight(width: 340) + STPSnapshotVerifyView(view, identifier: identifier, file: file, line: line) + } + +} + +extension LinkVerificationViewSnapshotTests { + + struct LinkAccountStub: PaymentSheetLinkAccountInfoProtocol { + let email: String + let redactedPhoneNumber: String? + let isRegistered: Bool + let isLoggedIn: Bool + } + + func makeSUT(mode: LinkVerificationView.Mode) -> LinkVerificationView { + let sut = LinkVerificationView( + mode: mode, + linkAccount: LinkAccountStub( + email: "user@example.com", + redactedPhoneNumber: "+1********55", + isRegistered: true, + isLoggedIn: false + ) + ) + + sut.tintColor = .linkBrand + + return sut + } + +} diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkCardEditElementSnapshotTests/testDefault@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkCardEditElementSnapshotTests/testDefault@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..23d7572fc6065919cf692914b3ff5a2f36955059 GIT binary patch literal 66155 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 RXdd{pv9jM?xYIM{e*m(DZZiM? literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkCardEditElementSnapshotTests/testNonDefault@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkCardEditElementSnapshotTests/testNonDefault@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b009bf0b14a9aae192cb7c5c17a0c1556492cda GIT binary patch literal 78261 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 JP`eZI{{clH4if+X literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testEmpty@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testEmpty@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..074be8faff1f91460ad4db986fb38583c0cef172 GIT binary patch literal 14583 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

2dlQlO$-LCIWhxJNHeWoSp)Zo(=ltmPmMK$l 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 Tr%S#kkV562=3Tg=`HTMpw$GdF literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testExpanded@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testExpanded@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..34ca7b2b625bfb1913bac4c6eae06d6650a4b76a GIT binary patch literal 60721 zcmeFZcT`i`_6DjbiXdR2hzO`0MX4%HI)Z|V0*V^xB8MhTN)kwbh*FLXuz_?CkzSNQ zfRG>}ptOVzc+R=^9`A3A_uu>DjY~$dH=Dh8_L^(1Ip_MmZ}HI9 z+EP?_zwo9_n?x_1KYMl4rY#KMJtVXZI8rgYPZZc}4!LS+wyC`Pz%=lSpU2G$o|i9g zQU>;gHf`O!f0N+GDZtx!v+Te2EjAz9wB_el|xfyYVvwyf?1-b1RS| z@b?*87&%-1wZHM#O{qnsW?-}9?s@x=O`8s#-gs|5mwfUTaPWZ7S(|IX7Wk5lpUpGC z$FV=R8~ahaEz;b8i%d6NID6(=*yb6sPm;v-HylLZrIA`)CP`^MXzbx6d7%@nl=X*! zroO(W`e~+Yz?hEym>ePKb7YIhfxE7|Ys_nay^+!Tyal4_?!V7!bMkj0e;PbIk?wyS@Lp=+PM1%V6HB8z8 zV(;L|>hQL5Nk<2wqpl8$NvbSc`nXzVAXZN5y}jIgFY^C>eME^L(^WQ6wp6xJ1}VEL zdnpGhLzNLXytT?RTJ~I}muD$n4O6UP4As3d?UwH5#Eu!UMcAAF>lJ;QwWU3~J-0ot zJwIkyAyM+}!KlIds)dG$nuH@Uq1dpN_3u{{xDwn=|MfC8=H8nx3ND^64)z_-V5;{$ z4}~y!jUc zKR(<9+Ml*3wm)ls(f+DEr9HJhy*=|vlS|$8mFs#nm!9d>d0tJ~pYguh!^>*lm%(Jn zi~53(GnA?daqXR%oZY6IHgDba?~h~2_slTCh4Y2MK4G5Z;Wtj{PQ~h1I{eY~Hdb<& zsl~G8K{k0k-MGuVB;G!J{Mz_+*M#fX>)mQsV$@x$)yQOih$FpQ zwCU9)XO~+<2zbdkElK0>!l8dOMChRHoz2cyE7pn+$adDWquVj#R>SA+9FJvJ$uZiYURxjvH zKI}h`#4w*UC?Z?c!a8y4iV=F5{S(>+QJP zioY~8$=MWmNJ3Y0ds~qnzwF*?=LUNN0|S2J)1r<|BZ7Vb z3KD~aybt~`A3WC!mDgqvt0yOm6ot8DLDIm0-IgDv0{`J0KYgWc$1!pA%FS^5I=#eN z=VjG0Ik`qKJRT$tgR_|({!d@;|EE1RMepBZs}6y`1_j)RQa6m9v^76bNnedLLMQx} z*)bwBbjD>g4pZ9XT)-x4&Hx_VV-SI1Ju5Z&=X02*-GiloTxwD}R4h~0uC6HPXL6_I zA!;Aj`$ahtzdF*c^U}61kOydHkcRzaXwf@<7vqRa%IAf(rA5(CD!-oXw0Ycf+za07 zT&KSjKBusK(m38(cOXO@jh5MG`Ad&|)X0I4kh`Z}R)kF5Q0Kn&mva^$&J)<*Yt?`- zpH=_oLvIo=-aPKD3sUj&vKc%1&YMnKMFg}M#*^D{@L$HE&{>hK*<As%ww2{*o@m75BE^!K9pV3?N-PsShfu_ z{`aW-bMIjKz2Iun$;@DAvNw}on~&xq>T&L@;W9Div0tC%pzR;`=Btg)l#i6HF>EGw zvjTj{bxk*VM_N7RV*Peaocq-%lD6G7sg5fKhqJt*`fEzKS_TWNWom|r#T`gI`fQqK8#ZmrTg z{^AX^htWm4G(+aMk$i|8eV=jsD&sb(?|ZswdwlKrS#e z=mBD-NZ_mgl#FvYFKN&@)0`n|V1VwZQ$@!9*NF-Dg6q1b z+UfCcVQ1X97D-(W%JhdV>wO%nlR-Gl>CSHb^h6r?)>O29!?Tz|J~$&-BHKS*XS1Yn+!u; za_qnQ1oScT26}$=5bPFOl(F4TJh;Gy1AAuOQmYB=0x3tv*j<*j>sqXmS1wbnQpOyYy&-{Pv8oQ2H`a4#I!XzsHUNn6|ai1}pCRh(c@Q@^}xA zMZz&=*ZLDbmQ-MSrYsjia8FNBBdUgqo?QVVVon$^M#7STxAmpJh@o z1vD#DYTvn>1_5&xqH}G%Hd+SZwEHTBam!I96uygC_WNQIUY^lh@K>m?bry($c)=wN zkSYy)=9d?p9BRc~2RDi6`5hw=E)@ex?96Vgj1W0v#S@4P5I2LHc>EB`HF_Q|{?}w6 zr+upsqkEgmId9Ni6UO4gWlPKWzCC$DFD-NMNjJ0dOS5kXljVVSa)on^vi92jRmGcv zg?14$84^-Nla(Kud6sH|{K0Z(FJtb^V{DrcZ~TKV#!HKlKaZjYW&gk5F6r^dnc?j8 z5dQ2W*5s*OyAoi?(q=PmuSZ8_(I?9S8~*15(6v;`Y`Odt%5PZ8STp;etw6My`RyH2 zMdc-`86(P^Zcl6t4$3S3_#CUoo4V8O}jAdg0{rR;=v%Eqoo}!#p?)A|2s)F89#; zm*q7~7;!x|ATh!Wopt-YyJbmFq8G#PxGB}s4I>Zo1Ot9RQ5sj{-Ly4YiMhl&fpDnByM=bUf zXwt5b9Z~OGjb_K!DlmO&4vYSXYBZEJ?YM5@5)rHST~}$bY%Dik&bQmjXkon^9iLXH zBD?4w+5R%IvkXOX@7CwuUg&U@>(k{|h?|tNu4X>VYfYPAsPX*AH9xpDA6@wT0+(jB z9(tYlYVRHQZyz6bQp+*xCA#Gev~3Hsip`z0 z0bfN@hF18+w8mAtN`7U1vu_1P+h5S|!Mh)%0i!s{0{dW0#e5;}4Eq2Owi$?~_o z=cfO#+Yad;bgifxo_dxRFR%0Q0GF$|id9*4*_s_^`vhOkLaFm)Pc8Ofqb@A+Q1pV) zXO@|_*CVD~xyimQj|O6GPyH2PBvp1v4Ker+w{qtF^v%#?PNjHbR!2o|)W~qA!)EQ$ zQkTBp1F+)(tO&^ZH(Qg#uCVC=yr$#Rrz+<3K5=I4Ig|4b{OQ#KXJ+I1wLyCu`ji_A zOD~j79xqsLGI;85ekNjhcK6YJk7PlmG!Y?4edTCi6#UJ~R9@m(xeGtkq2>&MOi>8_ zL_@K}PqP=X3NvROtP5v8^HZ+}n{kAO>zm`^d8?d>agd9Mk#F$>dA9{mxa)Q^VYT7G zDoPFFJ<75MU%urq>TQjCjei+V1GBil$|!M*6P*yKr8^Sl#ot_Y+TVGxt)olYwG$W4 z>AkL=Xfk(+--Icw2~GM$xqr>uJ6kWLMsG=rzqz8)1J8-KjF@P6n7VnRSjxFC_(2fD zMI3IzEXqE^GxtfWAXRpeGEbi#sS8Qz`!1eW<%v5Pukb8NO6jy~KmD;rUHjD4JFY#$ zk<+G z&=A0j!?G-9H8Fz&hF8vk=67QF?=yCiA^lP2&Cd&uF7NzVEJhda5)zrIueU}p`H1~W zwJDIQJw!R`?O4e5q7KXhgDRJjws2G-C!FyE>k|@gnbO_ zt7(rUQ6eC6=`5z8Dg@@_Qd6~n)erS}5cSbZg@xgqvGx*;^v{g!K4QT^$Gtix?Jwe* zIZRoQdwC3Uey3x0CFeg{iWq+t6wa_DtTB=+yHeR$u|>%-YH<@(^l}M-W5#Kr-}=3V zb&s{MVAs@8P|#)&Sc6|5a&N{gtPpp=ZTQSmr#d3ap&|Zfacz2C=&T_7a(c}^-tLhO z^zj{x1n7G+w7Q-s_e_D$b@nU1UD9j8BC#!w=H!waCr#s``)V zj#8P!gnZ=iBmG+oJX?jZiE|YDX0!CD^XQITt8X?YV*-I>W@teMEUS)2lkJ@tm<%?c zP1&8IKqm)knb4=o!b?{`dQMR*2N#CMaEs2{D&UTJ>Z!ao6Zswf%AMn#RqLujZzf_tZTmdEqS1e_j5|70SFVa*7EyGWQ_q{w(^<-Mk!x6a#Dt5YGj4M4>kICb z>e2+$7N6YvJ*5x&?JW5BkSl*gF{*c1@OBNU91ZPgZc{+q=`TttGdX>Lzxw&x;ddBy zBx)Yne!JmIP1aI9Pt7@(q^OD{@yxalWy!DKUxB%qBeHkZ`$bLnvN{E&U8L$2rgLuH z>{*j`39W;=$nCOiOI?*mpEDXjoc8y0uuOo+X!m>k(9fAtsmGk>U9IgykLf49Q@J~% zc4jq-PHlnn*OPQVq8BV;AS^KtuPgrvXxsRA`;#`#P%De?t^>4Rr5&kSX0}&Kr z-gvWUZiaRTqIP)|n!P>S;F_g-z?A|o=Hz}tqPxQ}ZG;N_8 z3MXGlsV^yyEwcTA7C4i#xO(yBxOcJ*d**?gZ)mdzzDv&+rPDN+%hC z7@)oyHshuTV%^i*_bErH%&xK(ovZiUSVV548q(C(U)UInq?fTG$zl=^`~^_?a=Tq~ z7N@4b!?qyw$~n0&vE;P3D|tX2VzJxFW+0yw@@B&n-35fP)<#Kf+3Y_{Hrp!#b=x55 z*{x8OE5t*&M)%qKQ^kk( z+UU1AXFLhweIcBQ`6hmKX{+3gPiEPrFRhaI*fVb5rriajL zrzg;-h<*7r)JSR8&S7(LlUFAji6o>?73mT+?DgY!+1kF=t&2^%pO~O-h)h84p_8=- zhF#*zyfA?X`i&{}AHob9;}sjyrKuCDx9*rMf}a;X3KdK=7GF17#J|X8)GAy`X9u-5 z6k8=C`x{R-y-|63-+#JVEV%W!8#jjrT&_PQH;dN_0Pih zSiUJXnykLJiG1;8zE&jd3Q33iI4x*ecevJ!U)0TS4Ri0BDC523 zLvH7`OGMC5L1xn3s$yKW$xpUbs0S@o7jWJr_o+Y03S_2Jp*prH3#-hYfu^L|bBP)Y z)dk$32S-%TPtEgApWE&p;a{{jsqm`z`6tCBj{Oj9kjqBh0LsWhygX#-u|G+yx!k*F z{eY_QJQn^PeAfze@AL8cRZC6`m+iV_!IE-5_aoh!5zD<)14SL`RL?yN|E4!N6v}a;BI6SCQ48tblid}ji9O-P)^}p+axiLE@_j^(b zD_O|VGWSr=;9lrHAXZ>`Wv)MCMTufb-@!FH^N05-OFB zd+(!P9a~SrGhfHWLbzjU)ZD1Mp6~=z)jpZL)%S&(F7-1GUKx$+uxGlecUC@`aVZ$M z9S&ryH)iQGWHjXPhvqhy*C#REo|dmF@$4J4Ue4)rUbFYR>j_%cS0=-n!k38BL~!-J zK;mS!!oZ};*l7foBo=BDQ5jQLh^aj?Gn1>|CZZA>_qh_*Oc8g)!KmwlCHRfRQ$;@N zMk1V0H7&`GyA=-Zq*GX5pX!QpcSsmilCCQP{rp`F=x49vW@zS)#1J2plzAo+v(U}8z(~?9 zYrDT&EWPnVT&i!b#FwvLuP`W+JOp#FbrdNCh~YPG9?a$kCm@|n^gm8$FPBxK;n;G_XgpngRF+^y{B#B^qg?E2~>Nz(BXo{@_*URq((9YeJ-^y#o*mmyp+ul2K$-^SR zydJFA0OPWkp3GtDE$2mI~GH6GlY+VdHI1qu(8IU4I+T6rL-PtoZhH}e(8e5(URUX>y zJ_LCP8_5gY9E$IR(k}wFemx8Zdm?X8fYplV$Y2;P1@;mLnU1QIKcSCV07{}##y1Fb3+gX=HIe5v2+%4s0IshWmut19ag8_QrQ|7==` zyB6AoIs56cx~@J+n!`$KB!AD;3H$iYR@z_I3{5uYH9MKX>rjo(-|vVp#N#4tEE44d zLB|JA%mjmZ=`<;_CNoNb5!Sy~Wn_gBHpDOrGDDY{^TlX23F(1#B$C1(&N@_EkiDSz z$S_Ri@K59_>FvENov|z*jqA5i^nE*-89t~}b)vvv0p0X=t@o?bydGqM3Jg4nofM#N z&tZCHYfe7K!bh4NM9>5+M{hz%Or*&vvZj5XA@2H(N`g`L@WtFwq*E?0c6UXXTm+}l z%W?8_wlwXHju4}#_pgrn0dy4jND_m6`w_(s1+(u-F8WDLX3w|*dlIkw!OAC>sK4(0fD zHi_j?npe|Qg~RTvi&}}gS@@WE1Zhd1+(YcZ@EFfQj^3cQ7i{WL=)M`#?sC_m6Eg?L zj5vl#Ivurhf#IaSR~B_IC$koy7gGbhIn`y{xy758IDWCdZ%e@cBBe}E0)SG&8;wqy z<;~;WNb!0mgq7G=^O|E8Cs=zr*O@~?o2Y9?wHHk;U6^vg=OyZCk1gOPqo&WtCQ9wM z?vNxl@}thR>bIZa0f{3>{5a%lsM=zoZKCCeU7ma2>lV@$yjkO9LcFFEjiZhbm%JVQAfh3BeklT0}lc zPF}Q{|0K4bMnwVWORG;g>tG3wbKId6hlX8522#)5V)@n4LOgfak|ZS9aD@&Wt; zV=|wXjxw-%saKq|jBmCHpBxbH2h3mX64e5h0Y8C-m!k6Y!4{IJYj)lu=yPXCo*br; zJ;*+#Z58%f9>#ZZOwv~%RW6S*&t-blw70+pe&GwN`SS2E>*$f@IxnDf{o;Mp4?*Hv799r-v8CDYS#GgzDRnp(HF{IKn!1h4^tMSN4l7ZHBVGEsRno> zyq@!2t~(|gI3cGTEsw*HX=dqJa%CL>WN`HuQ4Fg&0bxjHZHvo@cEY^-YCUM8+J8taqq^&@9tXIyX`J2(JAcba0KKa8~0^U2<6fG*yoeZh* zxFD;3vl5TS-Qf?M`5$sS1hv}rJez6fpG?Aj6?ow)V zF?o54NDd5Tof$4{@W(g&QsNCe?>;knmIE}B9K`zw630^`39o7PRV~L(U`#w5sAIfP zpN&M`$Xq3H)kdC~IbQ=A=Q?u}oNK<>%6S(B##+kDdCDWcr((h26us;@GeT8Ht}`7} z&InW!A4l-!6a$5LCoO#@`!j*y*&#tt+ z)sG_L{-)8f-EV4i~QHnKw!^!o+6EO`$gT+esr``43WMG2o%Z*uj8A$KJ79px| z`rPl=66e}rbX1=U05PDy{*^j_{2?f^izxRgI1Zvs0&u9(Dl$7hCoWzg$cZXLt+YHg zzGnjgulk~pb;kw=#^qmg^zN$%Lm;X2z*@zUShU>zF@0HSNNOeVSpPZjkG(`~Dp1+A zI-p=X8S}^6*dT)%i4R84g&7VIJ#yICx0~Fnvs^dV>`eX2e9iu#NBS-Ok)sewZL_Y@ zB^tWAMK==2ve6F<;*7FG;7yQzrMS|6hu-%aq4)PXb97o3ki))ooF^;9(1x8-2*nbL zNER8byOg*560cBHZ=yxG3e-rP)Enri)uwVQShG4Dih5vBZq+$(#kGd(A_DFSo{%MK zSExthAdpHIb9BT-3~wOLaUSrSIEY$fhD(GGaxT(_%!&HZ`gKNGoT^%F%Mj*64@H+Lsf3*M|B z{3Z4fwHxIn3*iKQ*qr1BynfNZH1~ldQCe8-&s3A`YfMs{#s?70JB)$iZQ_Sr_tUkk z!m-n27B(V0FH?JRG|LFSS}vu>dm_@{KYi;Z^BJ`v+!sLxD(UNQ5WcSa<}OY_yVnhJ zMlUF3lTZn;w5|VQ%8$hYq?JT*_+U}@)5Sa|xqU@Ys8N9TSZfz0>-mD;VfUKK*$Rcc zpe;TY`P#E_SymM;-x`;1M^Q25`uB3Jr$Q_I9BBuw)FjIC^!5ACC@#G>UAb`ZA;a}4 z$$T{IG7WwzkRqTNK7UO!_{Y9H&4KJFeZrJ#9V|)XMvr}zoT{xCl(sKma7HgOg~)|H z*SL{h?A4ZVV`13Kb+LMd_L{)$o}f!@C%Yi;45Z!GIp_R0KYb4b6p9{2iMmUQ%g8<) zCkwMmsz&v17w~=f_hA1?DqpJv8hBsVx=31$HfN__b@mr}`uvT1_^eXI;WBz~@5+Mo zesT(flJ3(s&|IYs&;Ny%{!PWy+h(xQudL*S4v!qV;B2pux41-j++O3P74wg8J-AEV z)LR@?RAlq1yO>l(hunN3|JheK;nhFCeUHRJq|zU*-S5U?AVxYx{YEEKLNa~+N&Oc> zHk-k#1DjrVC`b|!&>t5(7pLYd5;NZX@^IG@fQAOwoV$?n#r&Ot7tRL zsTB}*gI|q)lGGjjsFr(=E&T}|)EM6{<$4bef%QOJm9$)z^?lqvv0k!r^Fp46NGz z!|xA$yuAxM8uP7E(yDz4Y2DTVMaw?8TYs_E*;`LHTMLPcjIK1`WH{Ma$0x5`fST;V z+-K2_PJY;A?q>nC=&ZvwH7iWYhEC>s$&J)l5$XBKeWk9Alml;@U&8pX%JrXxVZuG; zxo)M`C&ka0+)?-@51q7X^}Zk|#5ftoVY0LzNLgPtEG6Ls;vJ5vIbx&);LA;qL}hjQ z=>bi!Kb5{ohfE7XVpxTRJW(RXUl(Z|6iMTxbxbHRUGPxiEt`&SKs0X-=(%qlH&&R)uchPhzh>)zoIk7Dud? zS84^Md)*hf*&FWQgK))}YCxp=(i*7L-_CRb+j$pQ zk`i(|cBJ8wQ_lOK{8Yp6;_$iro{8w~*(U%PAZJ6b=eb7T+tr}acnX8bulsy=iB|2| zouSeB_N(1bVN=i;^;F-xNIyV~(BW5^8e5+tCs3dftRS^SBGa`(F5^(S2KnXWY)nel6`XT!|X=-GFae=L?(lz6=;~ z<(dEbJgDt;qZ6b|Mw2btH*mdPNqvUeNd1EM@}>3#+X6C|Wr3J6;*Pdg^=gkB2{$aB zG8HNJ!xfhuQhMz!Zm8D$G=PCf!+juWBn{>#KmOZVgn8YZWqJ)TWqc?+2(Wf9Lw@RE z8chOj{qD^cTxpKt!8L>XhZ?#YIEynnHllFKhT=;P1s|F7N;__6d}_P6d}p|GRo4mF z;&N$6-UBIM5ydgAY5q2&(BqOV`I(#{}c;LH8Q4>c>&Efa``}YU0_eC_-7td+u zVs3EOzn2jvx*WSaQpDT$ACsQFnlv>2F8n)+8XYspEX?juKd}+i@ z7Fh36_0jSj^gn4pG}yD_=@oiykk#WAt~n0iR)P_&)Y;u*DgohngDpHia-6>my((h7 z{_J2|@S3ISL~dB-GJC+jK<$b#+5ow(K%RU|)~lYQ!eH133EP5G(xdgzjo zr8Dj-p_bC;mDURrODh(iD&DKhFwaB#z|2t&~G($Xdy1Kflox=-{YnbQAZbdsc zCz_Ju*+3EVNd6@*YoUI62-Vgs$4j2*X=o8+IDQ568M&G!Df~-8lHW~^Dj8@Y%enXlh)z6Ry>0$u4 ze+9uCw%CxK2Fi`Oa!gvUreM+j!*c*>sq1Lxlg%|l((X9DSN5+ztr2>Z_xVNl*PG>N zraaLEU16l2$eMK98vRE2^NxFNeOt}BTM`RaTVLzxG6LuO?L8Nlp~(i&dtQTSaC!22rY3Aq63<68yg#kh1eK&qf1DLh3$Y0%LxA6HGFY# zR{9hT{{g$cO7iLOarLty>y~@vZ0GNn1raaY7L}ZLmNme-Tl$u+kRQs!{lYAqg?}*Z z;bv%+*3$y{lE;2KyUm>YI8VtU&IN3t`~B4ppEJX8oQJILCmE=u@tx_Qlo%3Qdo7gt z>4S#(&4gNFz>HHq$1}u=OI~woeVu)ab`f_ls*xrs zA;n_~iT;ju?-0pS$&#OT>hGD2Rq#X~Ck&R)dWTl9a!j~TR3b2f z8w*V?uq;utCUeWVW7G^Sa_8!r?*gwF{4Np%Ed>wvjwBCG&{Vf&lHq;t2=mPIMjyI~ zM7In)_I6j?di}@)>HQ$Ymh#x-zQIg-kQU!Wn6q=*C0oZdgCsSchI zEb~>9G&9J>B(o=j%OAt+K(%5jKv!1khlKM19t9_a)5qh<oo)?m?F%*B;B$iQ6hYgC^=)&1{|tnNQ{#*rL| zowX?A6S|^Nzqz}}>MJN16C)NF916^Vq;ED^wSYF4+jW;fkmJL8g7e_t$kXH?xtM)v zFbY@qF|Xq`y*F9_YMe^MMVQO&yjwu1)$bCqmQ?~MTSn89`ukuKp}y@YzI!Y+t|aA*-9*$5#lsybmicR-uOIEfbpkilj$D_7QiXc9|`( z0~!C}*hk8&p65nVQd~W@x(Kp0ajWiM|43HjQZnv-AC_UzzD28JaQVwwU&~2b2Fs{P zS44A-9>nPGI+kiW@@+i5JPD7*fW0i16NF1k1_Mq(MMcHG>NpWc;R@Z|La8l6jN-BJ zpcn4(&T5JBL6Zx8@EG=U2GOIawy1=>7SUdb@BFLG2g?x=x*@+$iM_T8BUBAqUB3oZ z@7SYL_K!#HXn$3rDNuSpB!e<0VxQREtsXLee7&vbsjO~pQZZ(MwkIlfraAGnx_hML zcd!paJ-@oTYs!A{LonZ>;WW`vG?(1*DP8F0*@LQ=TEiQY0L_i-0p1OZy0%kr-#;ITnt7Fm5R zZU#@~N2_l&ne|byRfSd-7?Yr*lEmh$>T;K%km)bX0__zyzs@1uPBj#zk6&Ol0IsN) zEhPsDLW}}S1q#8NHW~G7{4W4wLNE&>?%7|YvX#wTf(l&p#$A6sz59#n$GEnLxY#&$ zorsjz)^CE;h!m-SC7~Lnb-knR^%v}nPnIBdE(?#P1x~qZyuA$N$%&`FTXN*m`*`1I zJ8|oRET8NX;V`~enkSvT$gN!(f$09>yOx^bqHBe9^dMg440qUaNG02OXHfYH=l8MK ze0d$C4oWh_vIlWZOTD}m=46)|gE9^!9Pu;cW2!z(Mu7dzXI{jcCwCXmyegW{F9C*V z_6zxk7)6U%&Sf(CVvTGev#@3?>K$MyKysa;=6K`fb?5iD1#>aSp2vbt`OHg%^eAZP z{#*#uG<9D@gKl8waGuehUX*gy8&nB-P-S3@SpU=++c}!)XctW`)9_o{DEj&e5Vsdg zmz}JdzaOFKgx)(|x{KKSdzeD>caa#uvePW-{ltMD`xB~BYt#3UcWW!%!dtaiF!e~n zeDPSV0aG?vhgV2Anm;gE4yxoV`{9meFH<_Pn(O+2e77xI#-C`gCfAL5p?{Sf*Uswtl&MP!o8u7M3$Jj>+Pe1FQ!}sXZ-ng@*a(TjtK)xpjJ|Lk zI-+6KAL>AGPzLmK+1lFLspaM6*f#s=XE*BBe6V*+I@BNBmTNczrb_8D1W3zRrk-2R2N73sAj?sCl91?-pn z-;kE`vxfxENq&*4ePgVlg;e={d-Lte=Bj7z)C=hoUng5Vx4J@Q8pUGP(yxxfyu1>j zSwIm$vaXrSf9l(t>`0%cKh46s^popKU!C(1p?Y~Z*XsKMGn!T8%|@RdgGVKakl z0-$6~#T9-GFo7f5kr@y(n&>2;9mobae9oLVv0Rs;HB_j}HnYmW2XOMt#bs}Wt~BV6 zJ$9sojWM1?E^eq8wY;W319N)N>*-y`oDMoJKUrbKSnUusP%h@BGmX7#ZA(kc@(QVdh}c}V09;XR}A`eZiBJ@ z8}x=6R^XZFP3A1oH?Ygc>mB88d2lS-#w62M;yIb&-L|3G=wg!Lp8&JkEDqI#bl1J* zvlcbgPtbbEHRG~(>eg3AzVzqMa}PV-@%80Ej5$Q#VS{c(q-F2?hK(ynPiDL2=8`!# zPm#p~QqJK_#p7UPS!2cvjl=x=3lYh%ICNQ`oD}^MIyq#e{b<#(f#DHp*GOOE)P+~5 z_;54$6)5?$N{GUol;q%2s(LyEk^9KtnlYD58!Tz1)b4?GnbLA)BY4T{YO(>gbj33TN;isY`D^uST zPfF({A2);FEt%aP-MgdqkPcza%$(cH($qM_kBBlyd~~UUxLbIOZ<{||QE-W0+Gq`x zTM%V9rja`Pr$agyG#Y)FYnH1D8E3m_PU?;~QP~Tf?B0M}!1RXmWk>_i zabIAn7UfMCZ*g;L=R}QIhF%F=)UE2z<#nvMrn@R+t-RLu?_0PU?d(<2;Y^8G$izo7 zfaQL3>fOLHy7TmXJ83K1{x@)D!k0{MIIn){WH0ntv}v-7La_~T5gVQqQI z`#>lW`w>A;w()lT5K&#nW7&*XJH@bj8EqH(OWSH&B7ZpU=>XaI4}!fL{npV!nv&>gH|@h)6I$U!eE$W++>&hLEhEWly6`*1eA z=4u=S%!X_f=c$Ml$JRw)K~F*8RTex3q9GD^*mlom z*Vj+EF1fk9o&r~Ek;VrBaQw`9@?-#sph&*owDv0KMHgD3^U+%RGP4tjdknVW&fprm z!(OIm;i9ODxKuAoY=DalzZ@vCd@L}e#LN>%+=n;vQS9C_WKoIHsalnO-~AVT1Znz6 zlX-H+o2|D6r*sKw$5)fDX4b_mR8CiyS6>riEbS)7?~K$^+*jvDPN0IJ0XCL7lv#x6 zMSycxTh);qvY8FAS;A(0mVtnBwZU;zrcIL@2!t{yTA8WRXy`NM;!--1J_>EC1^}j` z2|y%I0cF%Xp0<_*pP!6;H7Y0oK6qN~>N( zB*2Y3{3pMTUxL$tw7x)2EC5P|m6|BK5aKCP{Q~0;>%`J3@N!%_%7Zd#!lECMSy)~b zxrq&SZVjz@nxmN*(ZT4b@Tx&4-s|Hr>myve#*XJp17)DGJH7Z#?00^qz9Qv)#c4Su zpQ;k|0U4=JA(5_scB(=y=6#R{4a2#eI5c+ZGmbs&G zbA&m!J0S~O)z_4>?32@63(Tx02H{!fMcQHO;l>@bbfpwL6MYR~72-SfA)@ZC4>8!+ zIns+Lnc%!VvyL@IlyhJ`XWhuZToG=yhnOk0ITBLWkkS_LRaNN6Z?=S73>sQ-e6Wfr z`39I+!mg;lAb89bs}OF<>tF`2{M|lhZmB@{&AXsm1euWt;ic69K)suy?kHc+QwJ8D z^$ib?yC%J6VK;QioVRF%Ld0psiIM3S&XARZf%_0Fo_OEU-;f1CvjWkNq`w@A5G?3Y zLI#p4p7JuuQT7e@3ut$&GP}fTPEK@j`pjs&#KaTAyr$_90=3NhlrXAZ)dfLvgu)7N zN07Kw)G>d(fZ8#)ya&PoXlAYYD`<0VYh*4Ndcu^`g$CD+<+-H4yb=f~rino$wci`Q zH*QtEHLx*NBMi#U&UKs;O9 z4y-b5Tw!yOumOu9%sg!~zn-Mf`I;h4toCEh-vNL>S8WEmUej!0M3Cxvsbm^B9{_PM zAx8cM-Ap5yjwIar)j3xIsY;q4%@`>jm;vg)S87{U^<%|Jxgz{gcpQ0KM45Y;r0k{0 z=2T6uw1O;{GMid>C2!RnuH8-7#KWs4h-4lp(NE=EE=A$mV@cw5+=lp1sJ}jR4Nz=p z85y(tbkK&DSUx>wmj)D0NPxFMZu^z?zW(6t6r<3pX@dv`K)sY|bW zQtxtX`j!PsWv@w2_-A5AttzZLg-UFUbO$eGFXh|!A&32j8psjk%8`cI`IsluE^yyF z-sHLr9|CWwX$hat-Fp-_W$-P>Y8>2%so0{AF2~}_m*fn8Og|aNvPLI6;YDH$iGGvU zb9Lbp`2@{(@0S4O5#2Pp3?~Lg@RlDcyiTo}lwCUWjieJqDOuLoEOK*60IWdVV3H8o zC*DpqIdk$#6zfi7+I{z5cI<=?`QIYc`^fp0#Ry)S*jTJqV3HovY%PcFP;(rops5 zwERNP)kE}wT9N!X3yTP|DC`{U&a-L!ZshJy076B1cq?Y<%#25v-atp>-Hr7Toi>wR zmt->t*uiLFgMfJ88TC)xqA!Rl*<`)~8`u-Ro%lD-hOX^i^NZ*)M~imBekXlv(R`wR zpVW`(m?2Y1fAVyXmTu~j-Wl}Q58U1%QVioai<@*FN7DDe99^}$eN&81|MnART?H#^ zA$7IObT`zxy606SSR_|HNZ3dKvSbZM14C>RLQE}>w)9KnlJxJ^C{s-Q6G zSOL_Z>R$<|UaoK^95&-PLK$NOV|eRr_Vmc0#n0FWy8;~dYXJ3T{;d9&-K8Y#QKU2< zZTYkXSleHqI;o}mN)?ITtp6~m%uy}*mMPd3u`~ek?0kLl{e5l~&e#{&?NK0>1i3)T z35ktqCViPo_HtV%iFo*ua9Q z&Py4~)6;V`_EYIGY%{@Bh3I7g9jyt?C$hvqKG$xdNy+6D z|B_LM6Yc~R3AUW6WU8mYuJZwW=b9xXuVFM8?=QY6h-y`4QdHW|t%eVX_33|&xhjJrDD~!5a(Y92LNrZE6*?Dh`;~D^zbaa;# zG7RB*=8R-x_F6Bbc0YXgKbS@Gd(7{Y&uKfD4k-@mF^io^@>++G8_ZHD{YF_X`B4P0 zQYd6?$BOHliiG+5m=;p~W4+&y(snQEcl{xC&}m&l{r$10=N9E}VzROIHHRQN`#*%< zSSt6HRMi6(tDJX)>HlPWhYSjg>aY2jmpuR&EUObaz{KbC-k%&>J-CF8R|lqx0ULtC zkfzv_7X5|wbZXWR6vxfbbA2hMW2>2KwCR)8){DnXZPhN@wk#NBVr^?qIaEv|=cU*7x{_J|g&$4Qmh*^b#s7!UtQmOkIJ{BCvJ`#oFVWG6Rgp3e|X zG!j2xP2i`a(+@dxHN9QOFlGDglQl{MdsPB1;(6=Z%+&aJmTXqU0b3K40Zwn6zLm29-ZmOOf20B&fosLG%`3XCkGEI;1JjWo zr`z}a&SyIAd$R>JI{DrVWjt#=9vhir z$*@Lczj(fKk;nL5V7P0e?|Sp6U$-u!8;@Tc`{KpfaHEK75k(vVNv$z}#P4`GzAx{L zPegGfMnYmJ@TeZqY=b%6$P*ehwRn=1UC zYAm_s2!L!C8@+T3jxjXK+WI!Wgvp=WmJyOB?0d9X3t@j0Qe|z?Sywz{BAuIcu~ZNPNAVG-xEYC~i$& z?=j_`b2lKn3*18p-jcq z;0CjW-un%dhGB)}G#yavF2hApFN$s>aBecE3_dK5Zjog5H;{V*@;|!W1$_j>)%*30 zhkhrt)`OLGkW~M@9i7x+fID6rQ+T-e+#lpxO)OX(a;U))wk%L0-LpUp+o0?IqdnZ8 z;RAL5BmD)2%^&6AnZEzuZC#LnDwZYsguVM~#eX#NUB(V_BCp=4*I?_?+945I0I4ci zd;eH(2Bc@Y=c9VrfBARbf~$GWI_KfKV(xAXQqPkf@39I~XUxjluMRVP+=@(M4 z3}DX&|I?nW1$J)j?!CVZ@`7`cS_3}cIEYgypw+Zq~N6&3TN*O_^56U_Lp%KR>29)i`F4UgYzTkdUHjvm%calVY#*f#KolH6e%p9fK$PEsNnh zwi|2T_R<21_~Msz^mtglv}dHbeNC9frKCa7!X6WOqWU7!c5ZgYuKDd{yRP@a)5lj0 zkusUZ(FvU#p%%%-!xsn;O@*_LpV!txeA?RFJ6!U;y`kkFl_87iED7_qc^F)K_!~F5 zCz0uvfWv+1hgDT&Xtme=Z^TK z_(Rp!*NR;9g+M=TB6CZ3J-qZ!8ECaw1M)J@Pd`a|egT3y1{y-yChBur4}!9GY(Dc~ zTeN~=hQbpWgJZldifZ4#ZtCN8{NPokKLp8@7o1+>#QgmH>##+6JliL{wztjFxLc*E z>PX=vmO;dF5>?RdaUU|)Q{TQRhy~dktbCsNPmXynTywGo7C89N6JF!W$q&9!A+x;h zpn|6H|E6BgH*4*u@=7KznAud6SQixuFl}C^rxPHr<2>2r7#O+txLui}-KRPoeZ$77 z+bzwtcmzj+^(o;4K5;a0!7M()-s0ZNcL}oi$;R&ZnyQm}*|5^p)QIDDquHbEUE9iR z9puhuoQ6AU7$}?Z@$QD@2|6g$76<9K{4>c(_W8a}t*k!d(Dk3lA?t`cW*xh32>{R}I<=`kRge zV3CpIYdu7y@6)nGic*}d#k;pJuCjzT{94hWAkQJC=b&KPyya?YZe3wyOAGGPSEmoY zxGrrW=nLn@z7ZMp=c03M;7Qv77>fbd-S^3uN@Vhd0LO=^4|MqMc@6>btz_Nw3 z&Y8TmP24-TVho3-Mkmtc=rb6?oAd-Hj*wh&N3v;>sa(mU?f&rkS0@uOn4L6@8j-Zr z?N%Vk=gEW+{RU2Nj#)3xJcH2Y6hy^y%U@| zoU*SA*2~Gs`C2K;X8umFF7b^1-tw)rOOaH!z?Vk;cfNG+55DxRbZ&RSgjJ;oHx%u>g6vZIW9!FK$0qrqbh=k$*4~faG z{2=Nni+w9It{fX!vgIaU8R&hw<8zuN^-kB7OwY0|KxzKFHdQF$Hg{@VjKHe?LQ3o` z=8>N>c7I2nbKu+@-Me5VJ!QYz6&I;BmZYX8X?%61M(HChIu0DiQHh0tjLTkij}7q@ zC3mdvS1ER;p&v#x6}5(&g^4$801VY}F41eC#hj?F0r2!Ax4&6<3(?_NK+e;nB2Tb! z6b3z0qxK$L^b)-1!DUP?pb=xKBsR$kA`mMx@$Q*%$JcZlP}g$j37fDUm$YK5UQ_@{ zLk>fTyS?FuyS^u!RhS{K%?-N5{3Nd_XK_jbKfHkbpL583GgEl6r8m1W#QyF@3v~wi z9hfDmzl0y+xZF{S6GJE*k)zhZuaJ+tDpe&9a&_PwzxRrLQ6vwA^17Js6ncnIm>( z9;06v$HtbE98a#F(LCb5HS-6xAvRKfH*5jyi%MK=Ofobx?{%MxksjM54$1;b98A5sK zs;Vm#n&&PKU02Hb7t69?=+*kK^MqF^|K?_;>jzC6Fvza=ArE^mDF*;R`bcD6E1XxC z(}^oCo|!9otK=_!kYDyL`;cho{52oRyO;gsq;g40%pq=L54A$!*rkSREn_*YXN{wP z)gvTmG2=fDK0XF0M}?sFXg>^XgaW>d>wE6`Xp zR`S%A$5q9q-r=)Hk5}Sj_F!rHl@I4rptc(w2Az~N;*O+g%onsxoozgSM)vAa3yTo8 zoSepZR!MP%yd=prVX4%QfA(~Q!H)W!D@4rYRp-$gTi8Fye{bD{Ki2t$GoT{Y}Ti6vK)e9 z2;C4d_c5Wik+hsLIeubWAp;!ji7VRT+t$dwSxe7PTwYwf!@9@V+?Viz*FncVDXOSn zQ>*pnmpDnrX8Xclof4$>FO9M6ihyNeWcXjo{P3m+0;@5V@fO#knEE=S1n5&~DJh>p z>ymNkwbLk*s$K)uWv+>r=;ooXCw=o>?3|0Hl@BTm%z)6T=H>nh)p5&AKWmM-+ojiA zJKbo=fBa5|F3=y%2uVp}QC<46D$oy=j4)n_lE(uUI1EH=Y@82GcJFy4m%LiTfJY6q zP-<+pV2&`VHjz`Ey@^}NlXykY$u5!nX!9}udH&+n!DD^lN}aV?Gj!%Tg&GqT4?Pvo zQ1xrwhgI7w)H7?_&s?zk@{*2Ri6)nV)|9894A3u+9xQNV{t_O|{d~7EYLuai@_Gak zy|1N6aDj=a@r#Lg`^`GoA`>x#<3}Nr39&>1n>L`BlWVO{D*at{2)TYM8i{4SHhMzFs)a(e8w`bo#7NL~;BzmHdKH@t$p1=eY@&D=e(W z?8FoCx${}q%9BD=_+Qm^W|SjO-2$&J;CE1j=7L6O!#0ZTA zR6jA;k`!03l5V~YiQUlJvp(2bUW5>Bm7u-mxfdia{Wzd@RhW z2m>#Dvz~sT9*!L1%F%>pq+HXj`ZwO8fW~5zFckM6l;yFpGKulcpv$ExTUzthUqOa@ zvYZFclfFt|)N$DljpDy}WM_07rEhwoL(`@Q-Tz#F2J)`H=VjHZ2>0}cU09MdHWTl5 znIimb6?rMzCc=8RXS}@veQIu;%g??&*J95Gr7upS;cnrkSCTD+>C9! zqUiOW72&d-HOP2>jbq0q<~##uSx3XmO48_uZSKxkTUkShmmMH`($)w|@pvuIbD^=z z<JVKy{qcUeLDv&K;|K1i z#grCbErC>A?wj;gA_$uCSpIrSk6V-qmg-KNIjQypT_Vvs@m(uAvtTNEh`fr=F4%Ay)sEt>MdG|U{PM#N%Gz&bzUP#fz-@kPdG3L-1Rk~l+Ovxg@hj6 z9`mY-aQ8HFgDjScU=qqfg!+I2FD3L0MW{0NDY~?tcOhd_bWutX+{AH6b&tBAKiPh6 z1ZCmg=!finLaGfPM)p=}n59|HJSnul-AG?0N1_+#iIX!YT93({;L@4ONv*l|%y@m0 z8~%#aQ=N84Zv4J1gQPGkbz`jmYknJN{KMx{T8P^iUEZEq$?vgwpSwkx zvnW|e=1v~H!z%WM8115>>r0#F$Rp2jW*VcPq{~62Wjn_iTzAI8Aa`(J_QG+O_hXZ0 zloDOU$}fiY$O9hjKq515-RJxc_LHD!g^Wk}#j#LzMDH^w6t%^A5=yhIV{ao_a^GC@ zn`)X~X6(RhyQC-uv>1$F`*PciRG0(2BpfdQ8uYSqbv_sk;O0iHU`g@Y<0_wxp3vfg zOAu5f$(3%@b6YR3quWY??8w(bn%7p1*%9(d0@)%~z2^(dG-9$+!__(EYsG3wN3o~U znt->HV9WKAoaRz9YxPT8au3=TMwVKQWKi1ZLFmi zz|Em?XvXxux@yQ=?iFCPBDnd*H#I)lA3d78LMft7{m=_>p!Awo*Q~r|nlF|=hr8$4 z+380j(JT+oP^K)>y_@Auj601yaV!BVjEX$B`ZdM-hKJ$w!y@C89o47OyZ`cdW3~O9 z>NDwE@J@VTk2A>9u&fD_+ji(5?*&o??cS32I7w1^bE6S5kJvkR})1f@sxv9{lPC4oTM9a@v7Y=Gw zQ>P(U2Wny4Fod+36+&v4UY5Fa<)>Aaxy?M>Dp@LnjT&s>Sq;s2jUZ2m>yS?{VeN3Q zUvF;d05cwE`bhJ|$Tf>0Svp1u(H(w`(>Y@!>fflL{PFn5!b`r6>ytb4LwqoVs=4Kn zjP?*wa?ioU#E7lVEol(>((b{M3_M8Ij27B=D#84&Nv*^nrR2pn@itx1F0>g$+c(ow zjp-^Hd#kSVy6Q2czdCkx?Z4i2wP;)4(L&Ui z!`F2_@64b`?(<@Hc7)e?&r53lIVu7Qp`(^eRf$g`VOw=s=(^d!+HJcXnX^hXSK_e( zrPb_Y_x$4#A{}N&RLTGqvv^gDt2IuZs;{qa+jQ-%)`H~|mO6B9`M_p4VL77x418V? z?-W;gQGknjl5vgZk?PNq8@WJo+pe6sf~zT6OzxaK!v#EVg-36~=gq^s{d~RraDjPd zmSq6EmVL=}0&KLff%_F#U2EP!SNWS&-PlnYyIw_P-8RpMMJ=!wv9WSqjP`*Ch(_2b z=%aiM#wbWOi}Nn|F*o4Uf5a3iZw)O1bsU)WqZ=N_z@MQ~nj^1Ca3*RzO!FP^$&`z; z8!)S>pGqStmvtLW77SX_-VLAwrUtr$MJ)I2-MjacD`PcJvF2wwxN}LQpy|N;;4Q!H z+*vf3Vi{f4=k?({@_qG)tOEURrSANOiU&8>su)Mvw~EL(z~{Z%!eh1`5O&8U8J3l^ z7;apD^YHwKmQpoAt6mLti5sT8VHHIAY(U%Fg-UkzJg<>%tAw8tA3T(9hU)u%Y~G0d z7|a34`M%mKf^?(;$EBxjq|d%e?;~iyQll@F|D0BBL*2GTJ>s&2l0_w4NBrQgCFl88 zWRQZ80DT44Tg|G(+lqTtJo&J4dr-xe32DPdcVcPfW!9!}T2GG`+vntQ^{}3girFw$ zytiY|N4Q+M``C&{txxAyY*8#B2OsrmVUWuTDkF%SGbNOL&v7<;X7?(4O@{<8`Qo6= zBfB#g3Us8%&%;x9t^h|4w@cHX%l(T6E+rqnv~+;{ua|2f-eS%!>h;2-j%*YrA9Y%L`L`#h0KSgXzIj9N^VvZU zflYh3UHkIl>lfyuc>r+pwu3vV7DdMUMM`=Z2AWWDe#^g91AP8SfS;Zc0#bJW{`Q~Y z&fD8R(&cHzA7%J|k23Ji&HVw$xr*tP-zDo5%@jGqd8Vz z`pX6;4{(X6CF@p?EkkPl>qpSY;0n?5>VGcpp+C{$mR6+RNeoX)qyP4;Wyp9}4Y91_*>!Cp8`5J4co+ecdN*U`G?gn{F>L^!!+Ue!ARl_1|9S3qJM5-ZA~R z6$DY#)@2w%@W<6lUneC5tRu?nyx`}_% zMeoBMYhGSAMoRki_Mmz=IVDk1-;TRQayI7RmCrp~*Llsx1;0$OqSd7{E8HgZD^jn_ z?XR|qt70oZJwJK%(Zf3*_i8R*vj#*cL5~!)1Rvr=VF~qTIUeBOFx1^@#;hp4F`tqC zCe^h$y@<-49BWE9%ddsf5a$d?nGCNMf{@(xNdvoGzb!@Lfk*aZK5DYaBh995%1fmw zm6c~>;h?nbw*~pIvLSYeja5o>zZAMe&SW_tjpDgH^pa1vAC$r>6}VptU-Idn?=CFF zA36My!@qYOPajBib4kRPpCcqR{z*?0|GYKQI5%`_WG?6=R>h!}KJWc{ShBi1?}|)I zIOiim|2IRma&)aI%KnYP_q8%v*={PT_y7e8bxl`F&$+&Yhx=r!6nLlVpIcEA!Pjth zKbCoQ#}3tiBdRwXY`?{$z5Z5_w5?P;yX47r>Ol&U0(9-Mx$IiZFoFG+sao(<+|;Dn zNEPwLrsGMHVorEtQtr{%57Zu+J{uGK)}fC@BWSF4!(^*bn)4F76U63!U3lI>GM;MS zx!y#hz@tFHoM~lV+Y+%uY#@uRyj#8MUQR>pXPOP=!s3R3A1|w$hYNSWvvZ@=*wHA& zgChyU{;HEUO*;o0*p8r-qj)HzI7iI2;GMy>8&o6*CQ(z*9>L7~ntI;}DPqvbKCJPW z!;V_Zt!R-*FkwQaWJ_4{J=jNFL+yjfWW%QP^e1JOGq&Y394fWN8q@Lf?`<|;QTIKl z%EcL6Hz=GEZ!@->$f=2wF`rEwo+cDm6l^&;zERgbzRq%&XOTN&a<-f<5{<}mPsKUD zw347ageApp^$b(N!Awm}bG)H##g<;!cmGK1kQEPNqZU{3>ciy-QdDlG#m!oyD@1L? z?6%Bul|(>Hg zgg0zfVDF+*J%Ai9b$yM5X;jYOD6Y=rN0%2;uHbn=q8sk9T3F{hnTKn=m72kEO&v3Hf!2MJ z7QL;Nwe!MS#s!Yz+2vF0Tb6x0vH4v}C&U)#G0s0GI9N^^N(sIQLITLcI|a{7A2hty z?iRe<;b*FLsbpRL9a+JYNSM&57Plqyp6H@q58BE10E4Hpc829o2`_h4hs~hbhOvUg zHymq}U`b8YQ_Gj~WMS9~+G$OyL|wJoUAFJ+y5uAnKun01)aWtlY{BZ#*jM0P#$ zcvqHdyR$ime!|j0(nr}OTl)JO2)!0PDXsAja;B#=VT>k9^qGx_9XwE+aWetq8A-6w zh3}qUf=!$6g;kFW4owa*+AQIf{B+b*1+>oap<{a}vMB={s<_rkDjqJ>Z!4k2jZaAF z7%CSDfX{`MenEf#C=(SjuJ(}$ib8qguFy@+9ri*gq|5Nu!erAuO2In6>UbrCYn za}1Sf!DZ8l0gT|%rlV<0g@qS|IK|qcGD%PWp5MiLWwN}Hh4wd4=Ou@p4{rIyvQWb* zVkK1rZp!wr`j`?P?$_*m5ITtVa>BwSk^*-6SzBAbrcmV|5PNW?W6#-8ZwyjGXLf?@ zG4MvRdbTk?a85G_dYgL)K_23XOFOSNr;_A+X2BvgZn%fQCFS1=V|Da=pKKL_zqOL8 z@lFR9!LLtu;p^}%ur>9oE^?r#og-**86Cxy4c`!qLLCRmu-97AyR(XlqGxIY5p8AG z$mdYH=Q9iA!g`2jWXJ0OW03`wy6VMeDoIvSF*Y&Sa1I^aK^UGq^ic6N?15q}rAZdc zY|FJjScCljZgns_Tlc{0)61!ID>O_+Tdls|7O|Bi3|BRfR<|`;8n<~q6Pvkc-=;t4 z?fK*AZ)Yr3?)Y(l>z z^rkaEDXJuq+C527)%A487n9SyR;UVX=Lc0!xzW9bDxWm59EZJ@`hLq<2R+#Y&Gc)$$sM$NkzxoCajdokl)wlRY-}S;E(G{%S zl*gfsKK|vhma*c{q8Z(nZozD~NNAWR`g$CB>w>F1L|vY~p04u*kqexVf;UtgR;8*; zRxx-|CyymI`k=3y?fOe&vN+&S@zkL686{OGhs=awlQj4J8NojcbC5Xyw-;b;-agY+ zBYP$tkFzELit~8OkKWyXL&CUGZDrL}y#DLo7Q4@>1P>vT+WE zo$r3l*8K_j$QcJFDPsP)4hFHd9M-7H{3M^_$~wn;huxxH=5A?W)uA;ioUokIYKOopmg1 zNta!*Nwqm#U*FhyuW{Ba-uSA)9mH@r&#u}R8HKPxctIA(OX~YNJ6vx4xHA(91lqV; ziwhFmU)AaB#1uk>GVS8#rq{KNj#gc9PHeAK9$K3+uksk6m#CB&9)7uOdCevt8rtF+ zqLo#K)+p(2NsS@hI{x-Tsy26qE0V9ptr%!@Z%Rig>>)q(zJc{bCt6~7mS0TIkXg{P z9)mpiI6-7IC=Bu$J=X*IA~CnlfJ_#gZl}$dd(|W4B~otmda;^CFD~q5FsI^ixrO~u z^P9H-vtl?Jhy~i!y58Tay_ftHmtA75F!>k}%=UqSa@Mw~si{7CT6d(;hv|=8J0t|L z?cq>$*k=xdEmtyRAp+wYA8WCioThXJykje^oj66X zt4u1)(zI7E$_+8lNI5HW{|&S z>NGa?+s}NTXpD6};?MO~^8^o+qfQapK0irXHMPaa6`rV~?KH12y3HnDO!W5y3+kAm zX>Oijb%kiF`G<17sReImsqp#IA;1Wzmu8tZcp}%kawE-y`$llD7 zTz5;Z(AZiAbqYp}>hK$)Yp;X%8oB>e+LYRyRKz>kMN?F{a`Y^zsxF}Dh9oOIyb<;J z%Y-?0550Zf3?Wpt5D(kO@UCz~4Lb~Z_n-%uDEXsC?9tulkSxD7*rmL!{?_)y_ z!h1*ksPr~x(RxjgjhymxJL{^3yN}R2h$i$CUf$PYT^fC=N zfKYXHf z1<(g(+7fJN16gy^##slFD@I!l)z3Nv&J0I7cz6oYxOKtJ1^Ehp$^~J|==X{Kk2aMCuEFiMl=HF==OV>C4OEYj z6;XzV;}eOQrL$AR(=4LozJfRqRJ3g|HqV|Pup_0>mlwnY%)ovsyjQF(i5i2OH?b>E ziTqETPPk>k##I}2Sr*RP2;Da#ug$KQit}gQmp$3RIu~0hSl8R~ukd{63uWS@j0m9?UK?F;TsECBfGqA;MATlvp2UT6h< z!6ky7o_u=VM_3vj+f3P@n`=45!P2C65o}HWN*8xz9Or?gn`m8;p1vAme)ygU)w}Fk zI^7R>!VMfs$9IiwUkH47f%uuAYhX0^94W{{fOJ8@iKzCdeeHFwh-9%h!tf5_aF$MN z0t5DZtB43s!Xz9STE~+nlZg#k! zl8>4w8eu~jI7xf8A|c`e38$ZQF18B5y)YD_>(C?=!N&I83&Vx`(ie1VCI8toQm#FU z{c_a3my>X=03U5+ZFn3OT2-0eoaiRWX|?k+%kKyHs6y%A{U40E)ov=9I}S)9Iw<~b zMc_{F?zr&b)i%0&2ztOw{ z&eW?sL*6dBp&u6c60kAHzWfG{t^yg3b%XyMN`1~d^)7B0@XI;?yNWf5{$d#{{O^kZ z7id0Yu;i;Nx9l8rsXevRU*FR=zlyD7al}@eDjXLIWE={?8=$=-*#oZ9$@e6%3f+k_!U6v5`Ib} zneSg_2yEPbV2O%#5B{_Y3%}F=Of{xn$mzt=hZF&GD8Etgr-_~a1ss^}vhBwH1NxK) zCL`?Q^4|=}TJWjp%zpr|e}??ai2jlCFK78jm;beY{ zs1v*H{Y`dRkainL?d9%J`vv>?WZwUG@U)Wut|oeC&q&(X8g$o6Ma6UWp(K-8r;6YJF75&`el$8~Gm_Y4H|`(2qKz7mUcqC;eSi2e0~_ zz3S_GyqL=<&NXu_+(QAUKiNQ6!gz}ds3dG7lgT!R`u=5hpZf->305T3btb8jP!dFj zp8VdZ9yu@e<4Q}Go52OUr?GIEz=tY-TaeXZE-u%>$=ulM!#bsj(`y;U%#xaf<79Pp zY}`+wmZ|Z7JI;eSA4r6MXsdqDdf(t=pUIi{;FrBUJG|A1Y;suA^FdLb=f>95(zJrP zSuRE8AU0<4?*U|3ErYVPr?T%4?>8=$=2i(>;U-yktEo?8OT9_k@?RxeE_YnNnXLEv zoOdmhT3RrpDPsFep~u`^^4r0NJo<(uDhDIvk^jfG*qv7w1Xm#Hk9;qq0qY+ zc-A={teBrq_%2A_zv%hO&Myai-tFx+aD0k7@JH_z-@6^o%1k?EPqb~?L&ql%DU_Z~ zzM2Lb0Ywc5vEWXaVsB;Gi#UulO zcnx1G?3ct$5H6mnflb) z&$X(|>EXAj>d%^egS07V{G_nEU#TE1^KeGsDa zwq55KeEcfOhxdYQXQbriNsu&JX0bi@JXSmNAXekdR*t5@VUQePV-T6&Lwp^yF{hsy z@Qu-z5x!_UWbRP6^ttpkH*Ut9{f#;GPMnXec1gV_G%k)#;ndY7;-LOlC7b>G&yB9) zy}%()v%LaVXI7H8-D!EafxA~ zIab`fs7ocBSmtzUiGCiPQD>R&OFfsp{70(5A*dyk9bS96#qjQvBs*^iLcQVDI>(q- z;Vi{*0Xm>{i0ZjZ`hP#c1A_z{AD5BIe(ZEA8~Ns)>ieF-K~v%&TFv(eVk9gub!>(@ zD{fG;tJPQ^XCcu#q>wo%SiO)E2x12Vz5ujLu_xRLJi$S;D zIgo!IX{`d-$}LyA?zqG&lcBcea{zkv5do3L>f7%3a%MKZY{v#s9Ma?4?0Bco1 z%d|z()HwEfAJ~I~H@s_<8z(jPtPdrA@SB>b)9y8XoKL4?kQ@7+>@dTfT(DG4(g6Jl zP$*R5mfX=B=Qqf1T8cgbto7nnY-!JFgN_SZ-fB(sMg`)rYLtM3Sc57&R{G$NWV_uN zDWbZ#e8yuJ>P7eplA;VyBA;yzK z5IVo$LVEbtf9J@|Loc&+?`@2)Xeio;qAIiQEB1=-fW;=Ab^w$GM>T^SISsBmM1CDz za&AH<^le24XIM^7<~_oE3&AC4LFTqIS4HPld)uY|yRd3Y;?24K%e1ENg?4#t3_}dP#IwP9g2~Ooo#It}n>Y+f>5-vY441JD%Eit6%@72t;0{jeUjyi8*U6p78~hylrI@7hMF3LuKW zTR1tP?+Qxr&)EgOq+a8f`4b!j;B*l(L0u9v zVr{wBlGRB5QVXxZf%t0YisWlG#_b=3GWLT4Im;m_rBS{ z*U(Nbs$+bg*q}q)OqG9{-=pQ>R^U~{!8y&ALuS)4rxI@F4$Hxjm72KAeFjstNwz{7 z{!(FIEzM~>R|4gJz*XNt)MrolZ)TyzyB9pk`CX4XyVI?%qO=D9VGFB*O%iz(7KW># zG_?rUuNgzFoHEf+Q(s>`%VzpG8A}~p^}=T!?_CiaCSKZ8h5Qy+bYtSfG9gb$bY&i2 zM$w>Q4ByE|2TNvchym}U#Zo3nxKJT_LbS0*a5*oq(2T$M%NZl~^jxt7YUW*?pZyS% zvU%4c6kPQF>fs%UL`nY}R85-;g_IZIVhWpB2(-lh>Ja}otLbiO5rnz9+NG(IxH)2J z4pMpx(FKw9UHu&EK}Oc|dC_^S`3P%YMd&pn#mH?-)dci`_oIU?!DJ&6Dq;(6P4LN| zcrG!}0W~s(P0~nG*qmq$?JMPQ{UjqSc5tgY={UzS8i*PeMFou$u0Fg-OKrobLfbDVPWMKH$V5r zh`a(w1p)_%1+gNQ6SEDozC&iz7a59mcwRsiACbLr-i-9~|EEiy=V<(2z@4A2`k+=2 zIFygH;t_Iq=(g%+~%e0J@X13yNB8C(1X{X z(c*$zTVDdkif>yCz@)3&&W^F*XOyEvcPJ8}!@C5H7avckHkOTT|5HkpDmW75J7iXOaZW~IJ&8n;y zDrHeEjZ7ZG;NHM|{@kR(&qagONaZ$Q_Fdnu!MGwcnf6mZXjD&EH|A8zX5x<^=+0KE z--(n?HZHwRJ&Y-L^qwtiGr4iZjAYr4d&;Zizpxz_IK?-&CyZ6K`bGCO4~^MP8dj#Y zJg=I=Pw6ZP_21a{EEe3JGry0n+N~TlCz0zc)gJmwFi7amIH-yjdOepInEUp&(?Jxp z_rqN_sdRSS41?TCHM2dO3Gmq!65e~WN&*si90_t;XCmpm-G0&@mQn@ zzI-B&WN9|(-r-4t1&?17&7J7HCU%$YkM%jYX`{yx%C`9orL2%f6Uhof zux(BFZRerP626yp>irH*Oh3t~I-Q)#zz=rp!!-wf1bR$&5EKv`I&f~%9$aOFWd<1 zBF^2!;qj~?yH@u1cgRbuk?7Pe|<7o%*!?tF%y$BH%qlbms@twpmV`(nKM&*IV5}^F(<6k-OYpaM%e~uwF{3F0aOM?nG^oulwWfJv2h_yaa7|IJUKy+#h$Tco^pzFF5>+co4iB%TL zPpjr)NIl}-?K`pFu5i+j-~*5h$`rwnex-db32fH(Eu}r<^R>Pnq`+K5N8Lmpci&4X zooFRcVz#%31wjXQc)~wm3kq6~X0ZiwVZJaVlCVzu7nOOX({GGn0ZKs@1w`}|_BEw} z^OM~>K{a!-d(2)0C6zPZh61)-fV@zd4F+<^E~ucuyfh14%0Sa?Dj=HyCtR~3Nh~(3 zaLXNp`FB`!mohHa(nDV5(BL*t7{z0-Da8dG^VkI<>z`0_?G2nG3LGfUNtO#{>sHz8 zmEDT2cREL57d@SZyza8qp^`fbeUkkFoW7mohJq#Ldxq7973s6|?yCFemF`Gd@ewnc zO(N8YBo$Bg#pHr!EV5=MZIkqTC+0!1#axl_^ZmRX0==u?=eIf4U2leQ9?|-4XS%yIc_6R@00%a<6eH@A~ zk~qcJu%lng1Bvf3avDIkyW{zZG6vxqc%2vJvTc>%W@T7Gx>+3K`;rpZK1(TLEI^`# z>N=8CXb~dB{lpC%h&;Sg!u2Vux`*I)d19X|L<#v2rX#+zOybboaz}~H{rxkvBm$GT*1Z80&t`tWg;iz`rr|XZnnX zV3$4TYcSu3W&Xu!9eL6Qay-ld^s9*fNqL5$09|@4a7Rl(L2f0U)XCXgOycEM!*4#H z;nyEA`muluDL{vN^To`EJ*x(4yO=tvp@huEQWKS((?PYcZU)m_Q+_oHa0);*LAEPi zrgLc#$Fk)+AK8EM*-Q>!v*gKtkmp66{sZm*AYuIBPW*_&{*Y6CWB~uy$SHs&?ATKS zxxRMWwiOk(4qsjS>qpta@Ss(;L*%!Q+2D5FCuCe}{Ov||G$-!KlCLfNQSPx-+c!g; zQ_raE4Q7YhIp0c*wYQ{-{{Bo&N`)rubRod~k>JGM86WUF;ihhn6xREnE59($`FvaS zPQdy}ko>*)*aMJ^EOu}GjgMpp(*HI6|4{;M0hmrA_xTpoWf8227X_alojM`+E3V)@ zO*0CxflglgtpwU31bq51;6Eyr{|xz;m--{+MHdB-qCbl9|FmML|E=-zbM5s?#dEep zN$0NffL1-32s?uA(ZIj{l0U(_=v}Z9b$xY2CVX~S0~ZPPaPd5#kxj=-gvmr)AK3(Y z3Zaz=^(m7tcA7dZluay}8i(5;FxG_peI6yOmaeIuK|duH;ren%e7Vt*b}&JEfq8-Y z?PQ;?>>P3n?n`{S3AV8l;en6(w+X2e21x2_>F)ERA7oHOiz|=-M`4&ptN-V}vhFR~ z9-d`e2bwqtif6m^jrI8smfup%B-&&mux(4pn>BzM{Y3r#cNJ9V2M+iBi5mv1f=qr% zcI7l|<2dMGXvr8J;XzFM>1bS@4cI{xR#T!FIf|i2)(bB;1 zPVLHgZMo$-1*ewr9KN)!m}gaE0~}b^Bju1i@8AD6LSYA_Lw*!8Z)o40o+N`~HXd)6 zFsn@E>!#{Te7bdw9po5DR|@OU;U%@wWn+ARH)arbTsli~sIyVR>SDp;>9N4$&5OA3 z{2~Eg;gR@rg%^2iN(;5unngOD9DdYBP5wEIERtB|(z6Aqy z`R!a`5o8qVC4!OFh=Z=jSgE*q6iGL>EaARNZ6eFE6@>g49DGLpjrJ|yhNkDb&eC?> zgA`6a$cQ5`OK`O{c8z4$^ze(kP7i&$UxTD&Eds^5ndJy(DJ;VDxS!!PRIKCt8gK%S z;H6xHdWOQ4)n@aGHDYEcdRB4Jkx?bv%!2X3Q%(C_&W^A77%NyZ`aa5Y#{YwDpymH) z?7PF7%(i~d*k>$Y1EqzLQB;KJh_nC^Q5aER6d_WBA_7uFhlE71ptOjHpb!uliGYCg znt);mMS2N663{>hgaAnhY4?RWGv9c=bMJHci-&~$?!D@M*ZQrss3wrZmY%icT4ob~ z14~tjl;34A$f^8U>{Pc9AlrFG&D1xh-Yr}Hc;vr;+?@0ooHxM1~;T>|POA7#@M;-*EZR_kwOy`z> z5}+t>>1QC*MU)H<_cgNL2<8W622~p1CBD4AS&kq1wo;C-crfh}@A~;r2}7z*57J*f zN7c;nh!{*A2*%&=N?Y6Q1ppxa-f4;FbyC%HxAIBQ8ZXRsK!jX?6}KZ+7bor|M;cHk z#fcp$M|x9pI5%AEMsN>{z4y4sHpCW6{3t2)?9B^!sqqn+D3kJlKJnTHE&gYN%4L@P z1)!}P5&lQYn7=i(OPoX@RuX?&J{o2R(#k0xQ`!f_Vx7-N(lK0vHxh~?XTd-P7?}Xs zeV`nApZlRtWFY^!#SY+1^j)CL5vCLaoi!Fx9TsbPq)PZs+)yEeCA#M|H^qLe9rWjl zk2j7eN6P#dC%4D`{F%g@gkjJ*f%DiDYslGR0C<$)rnQnwppiCRW}YQKxU?WHBxqX- zEC0Qp|KI;E8eK>%>=J_wg~NqwsSt5Xefo;;QkkLGWzX8ZTPutR%QOfa-BcaJO2?Mi-); z_(ey=AksW&ony%I@|9triZE?_&8mtR_9&KShUM#o(%Zj!K~E?_pW;R*aB>OW>7Qw$ zAdBMod*lICLnUmwUZQ#kTFL}xvh#7a59SF^J8VZ>t;BQ=i@VQV5yjLJKS>S;nX^OG z#5Ng&I@XjU70Dwk$#{)8!6*N|Dj*~7kJc#P>F8e1%!1TLg>6~}pD?WAe-P$tgojaP zF~MZI$!c<()E^kX5!F&Wnij>RI<2lUF)Y;X1uO*SE6&KLCX$>aH0yNox&SF|nH~5V zT?!jRx95q1>2j3E42SO-OSXMnmK$?a2ah6_u++V>{ zG)Na=!DxNtw=uN;Tuh}8*IT^V z$!k(FD-<_%YhQ_;G`^o?#Gh)HAv>rX7f}zk( zi7g|>-N3CHETKdi;~A`H5IVK+jasf6A@sIY$d!@6>Gf)ekf;?Ank}o*(!|Ex>_fd?IMH$ji3Mo&HP z*z{2{8G*T80XM)?k5w{PJ10F$PNZ z{<|9Z^{*BAa3tSkuMVWoH5{~HpzmlS*%KZ;*Nts49Y-GLS)SnM- zE+fkx>g0cRmQ*&S#7phuyG}di#|~i~mg*~rCug;DXq+`GT8cFYq$E5XI3Y9`xzbp- z=AK>lNduL~)j!S6;u_7D43INhYys?q%M*GrIsEIVVx>23w%`;bB+`J3-c?e7!maohGuomM z(VsGQs)ZH9?9=qNFqjeq&$OsZDf)xdBFV-ufp)5CeB%R^+h#RE0o|s&u|$!GC+Ys( zf*K(o(Xvp))Uyq4}6l;>wA&+O-8o6tymywH@`e2a~r| zx(3aZpWt?o!p210j+Erx@Geq{vnVHIzS`q0;i2ouYE4JhYP6-zR-Thax2&rx*WQNn z=2MmNO=vxBmM}d0>D2Eb5^OCr`~ep#?!kv>KBrB;LR+D_Q$V+=zFypLgM?uDTQ7lQ z-z#g>TXU)R*VW3}U6R$2RYa27i|`3UV67E)!5vth(8Y(57~ z0dm-2*jT<&eQv;YcLeH9P~pfgT-x(~^@PAjjqU<-#19oEQVhv_&muMYICfe}(RlX|aUJ6n_eo(;!t^leZRJ7=322CFgb%#^oZ91?jN?7Oa4L4ag(4ip?sN)^|5fgL`jhzc& z29w3GHBA&m{i0UK?pU;vx(WUY+zG%2mfBt!e*82ufeP{d!8L+km8b?Y*kXY%bvRq@ zhQ8r4IcR$f=y@-XQ&UCxi6peNhK&h&$MMD$3r$OMQNq zw3UK5+?9UluC?r?wplqW`;A39(Vxut_zgMvTWl&+Fkty?;MDlukeEl*;*w*lMU3BR z|kyF4~b^^AkcbO1SOm3Y4}{YBYm%fp9fCP&^7L zRI@3b<-digv5vp*j6!>Rw;o8nCBfgy=9*f&cakrlcFTkq^RLmjl?ZP>Mhpr$u~N6# znCnC*_9@~~^)woR{nZ5_3RQw{`SjrYBu@uNJI-MddC$FN{V!8N_}8CgW2}1tBbc98 z`*ls$fvAgNP8Zsgeou55*BBKo3Y(kn^g%nvN_q1wPsmrKUzY$^-Q*vHS&C%=avS}h zc@t+kI#bZoRW~s_5`re=EN?V11Wml7E>nXe-YpZZnAG!3m6_$dia(hX_D2!<0@1%s zc*?MjRPZR=oENy7&9vKuxKgP9WjS1;T*TQf2MwD;sx`u&Nrvw6T#GA@`NCEYAW!8p zbbn0Jd3UD3(opgmyiCoPlReT#u>>uBaVVSndH|W5zp7_(>9GN8MyrRvLYNNvIe&0( zMqy?L%n^HtsQ(+KjjnQytJh~Rtbp%(rg&HyPkLrf0KEC#Sv|O&wK+n*K5q$MJ z_l-+&`W54w#dQGarMi}O=a=F9kD5Rm523=t1lo9}LzjGYYJ@pTC?Wj3@g#H^We z5j1&eAr`c9b;!Qrc|>&pf}97&(VCOVG45Hn<2{S--R%F_nac_T{#bc>(#LrcTu`O$(#cJNd>rEY9irj6f z%_BGVAj{i`J617IYmfXfz()yvo;jwg7jAMqW36k_5Fh)5^KyK&dhB{KJUxHJH-^yf z$^ws9fWdUKp=iF4Gx=VWM{K30K*ftYQ-TT5ih4KiV{q5m;?~0h66ee>dmmiG`Q60cCr&8p zA6tN&-(Jw`Hbc#8in|Vs2t^~UQq}QDX_$GjX_XhG_#NE2r7g}lY|^RA_3O0?zf_DwKACE4@o}IZ}|y# z9-qQl?54GKL}S5~v~5p}a&%g!q1Q%9hYC&L>B9@WcZ0V(fj8x~Yo6i5E+r#fsrFuU z99TML0*UW5Rdh%~VMcG~FgN;+-p;>MQxGtLE8%^rrdwN$_SP~D*gtrr9^*PcOSa-< zh1iWK=9p&}%2&#&o#vzH`t69z)n8eOh%B`5 ziBo!>L+gM#Q9FZt;Dq4m&vmQuoq%H5Mue;9-|6Rrz!jA()liNrd}mP{&oyFsx`{xe(jZ(-lFfe-)kTyk*@+^I~Doi97<2YO^|CRc<*{A$Fr1QX4NLG6HOMt+OK51;cf==|W3K zt>EDapXB`@9hE_D%_926#jz{`h4i#__*&5J#zA}i=4<$iIw=RAJ1S^sC|g(fEW?U& zkH064mm1|~~0hc<1_|RPP>qA?a%ES{E*)`|G*aEl>*7nCabGeO4^O8XQ zzWu{U#m&#xRp8t4hupmEFsJaPWYQs|A-3^LTa(XF%EQuC-aFO1vVidaUb^m}h`oL& z54w~iq6l?gf_tvr!Ry!OHrb#YQt`~jbE8|-3Xf7}@ppXB_d7iVNtj5p%Kgy?cAX|A z=eIE&_7CIB$8HQiE0m{ekgFSAqtB(3*HTJqjFF=^y;6_uvQ)3_i73lrY>PjN*>j|r zUiEnqY_=h2D5H2VKb@La(0Z%SPcOGi+)E)8^}YV=rrH)0y@X}#89#^Ye~a|uzk-hf zTm>22GUQOZUQG23J`!KcirpN%O%x=(J3tkWww?}#GXueT- z5c!H0Z0`!vGqJVV@06#(?Vq)=cJ+>t61ql@*{s>G%6Idk=cLWzrriTe;(SOMysO%h z|GpPGGwP}gc&;kpG@&K-t9k1$Xb>%i?SZ>#Soqp8z13$sM`dIBw^Mg?aM#?6R&mFM znag49?Juu5zQ)|=(vHrd4c*-{110z~xHkrKuCPHY^|2JMO6l_O0LsuJoIp< z`{c9xI&_1~o4(U$YBl3uhbA&Q3rT}q<5`haH*fN||sbOl-9UH42@tQZLqAVas(#|VQ5n3YIa z5CJ`89J1^D$v^d>CjZlWQ=1+4du%kLU>PIP|23cR;$yRU3<;2ZnAFEZbqNwdMqCc@7}d z<^?eCZpSO$PZpRTikPS>bwR^!xkA- z6Eq0>L7_pxjO8ZfO)Am77dKVZ{p`v!z=BW6KxEtH0%K}7pAT)p&_aq&e2$a5m2Eh= zYi{k0z$i_(FFd;<=<51qcLQK;j07%EvkVv_mPUl}j6{|txA4?-FS7Qf7A zaN?E-ng0C{v)O~PS+OH4`|%zxpY?OBE8$7Wj&C(IOwLSeszs^~TLp!mTW;&NQWa>0 z@g^R$8zhjxXPp8?(Y51{yi5D8b1=q3DVsbtqqAtkN{!>55cN`u@U1ss7BhkODyM8N z`43}c|BRhvv9V}Quo<>#Ay0)&lf25yoxybGF}!uxgcis(0zwN6Zn8lrjfbFxa}crP zYIR3-2uX_0u3Py~N!dR;`Q&5$uz+;Juz4STR%X7lm0OoH!u(TiA$b|FF&1wqlXx=L z*+~mG?a*Dvh^TJ+gg-?YHChxYfY6&(Blmua>J8mR9Ejf$eB@_ ztCT|EZtUDwVF4Jh5{cEvD*~6EEJBJ^TuUC9-KYMcahMl&|)Mp_e*2OFWlxX^qqt&>*3|-mwSdF54rCA$f-A6Q>5cV{7W!9SmxcPTt%F_==xQbQ>lwfETxI zvN*(W{zFDWc_5Jy`?)W-1=HCR{u1!(XZNlrCBCg`sskr-bv$N4vl(p9yb*6a+AF2R zN2PB~x7ghy_8}?N2@R~VnCzt=j&f^K2;<;2_u?^<|80`kFX@bSvKlTdsmN&)U!(_n zSgx*&m{9?LiJ5hTPs@Mqt&yQi7Ah=l5^wctJtnk}R%J5DDXNW^OZN@Fc4R*|KkEN} za2}^Gk;2VtDdg#Z(AQGl&RQ5FQ4_y&FtB1=r|9#A;@rfXDU52@0OCunS;BlYp zw<_+K8;Y59RqdRVEEyHbcTWLPK+Jb16L=DZFM6b8sKR1xtPsMP#2LJE1zo)fHb%rK z*C*L`kklJ#?}5tGi5rTTff zT}wIYg3mG-mxmj2@-Sk%k#oqw%daIakQq%g%w?4_)3L@GTZ*tKvgwLpMhq6tOAOG) zzBN-1Z`bCtY>UE?YaQK_WPth)D#oke*Y}2+Stl_wM2J@7xlIp+^rsQEc&DOhh?Y5S zJ%|Lo_US@}363T`Pm6vMswA5myHpfwHL9UHzvRfxpq1$CfKb&SX6{%$Aa6wCrWiS}ySA^A>hTYP{Nt>})0!>v>`a zBp$fwRHvNrwr5_9GY-#B=xH&J!6HJ#P`XyZ`(BtU4vcHk3k(m6!2q zU3``SiZL&#ljM$eswT^(N`nP(PNBe9GFf`QL2I7`JeMcL%kxF6oxSl#XLO=^_4NO(~E-i zP-e_*@2v-%I$I-3d0p2ggbw_Fii{JyM3pq$6qyK|6E)wv?;{|5x==t zWkWARVmpgniQ-?1mbwjN)_X2VKEi_0mbBRRDnC!=&seo)Y`~pGYAK?^$`+7|12#a8 zU*x=zTLzn($>1&;;{>nLwtY@&cn`Gn8&(3{l?0J?D_csY;2p+$%m1ts1A-I0wS@B} zoU`7X-)P_5_PGE_EwyG##i=r04d07=mD-O3Sp{OPX8C{+cRuGIs45v$%lb9L0pR8qxbxyHiyo!=&aA zi4`mSV$1qkR>3wX0PfchDyaAiul5ZXBA+EXPk*idkHcG+0P(_hB+kq-H@)5lrx#p#SFve}^do_9J@a{f4cbS)%=d1HHYORvpP<|Z!Y(Op@SyIt(jsv~erb`Y zSze3xE;EED`;9@IY-jy==HG>`+u~rr!Uj50RdB(8tn7^&f75*ZV1I&3{ETY)3%Y#3 z$kXUk{olb6=|FFHlU-}!L9Oc7L|)a?lxw3@ZR-5|ApAn1p4lPmrX~a1RvQd8<014 zg#HcnU#C8hQ9o?3d##gz0?$3$n09H)-3$L*el3YTo~=SNV=RS2s@$y{PEr2@CL;qN z7p60}v7#*$aQyr>Q+XhjF85y%M#jtM6wH*6Zz-0zW*ZBoksXV>?@#6}u}jyG7*P>k zkRsD`Jh3kq)^~~_7ZiLzD6Q!I9iB<^ytBP~y|0A!0`=iVN7&f+TPA&u`A zlXfSZU0cr73F>*ngVTfhu-ZLYuyw;}7>(9l)FR6SnqU9FHkPllNTEHP z!+Do zPgeOVl-yO?_Jb9&;mX@l5HT#j1br zpvyn9c`{53n@-$64AB_r@B~VfYrbB4`5%4sj;KoO>Ps<4I@~&w1d(t0?HBjkU=`9F z+P%Jqg>5TyQ1%baXi>?e+eXZ?yIO}!m-chPg=OiNmcFNS!_=lj(exMki+sRWyXjf; zW0nVeRV}?Q7Y0{+uLhg!j!W|)QcSFpoMeBP4V4?}7d97zBE4yxRsY)K^&NqfPwGZC zQ^RDi4n+00c*}tS3zRqUrs|j*-tmc#KjGG;e@G#KxYUbm9!soWI-yjp-#+8GB#^a{ zSxg=)B?L`gxcA+5ouf9)5QbE+ArF>mQ5`!+F-N85c)s)A(9<6n!~6b29-|v(dfiHz z$HKN?^_@OXzv<*DI@q;Q%SwX(P_(nV_#H@X(~+anVUW)8#Kub-!-qb;X*A8qsAm&J z+lO*@!k%V2*AIQa`e#4_n9U<$+yn)u=bdUP1}OKhVqyE%=es&}Q@(w#kdZAvp6}>5 z9Wupg^>gBU{FtaBIZE&qbi1e?fg$a`GpRpp2mpwzC&f&xRl&eqmonO9Q()8#*=3-m zkk1d=_>Cr|e;fU^Uz~s4fQYSZri2Y7jE+r?yrH|DUGIm-2*=hSPL;pGY?9{jA zj{%AK5OqPGQR&L>vjqhOqI(@pT8qA0xrz?0T6!?z|FVW7n-76aeL7ADPR%s;8*gUc zfEl7zRwjD{m8P4S2 z{5wexJ+Hio2>%T=MQ`qg{PYD9VFmPiy~rs%?)&Jwx}~#en-9t2WpQa{&Ykzr%wfw; z1a@+Hj7(^6v>N#*A-kL+X%T}eU`ytc75%reAW*f=SkGhOr`1q>ziGeV;mwR;$kp=n ze_C?&J&%O)x;pJ7MDofoSP!;i+PV`G!L|mfyRu&+gyL= `$3PE$J7GP0R4!=Fuz zRsn_B*>`%6ej>_!sK{CnDI8=&3?A=`asq-NQ9bs7P6= z$4Qk=SZJe2v_-~9@5sjsF0`M*+wymhTXv!?J-$crmzgO0drb{3w=N_GsPIh0b7xVc zlhxI`XEhXb7qLo)W&W7exyJ1H*5|v5YAcbR4=W%3ll;zFn`s%diEzjSY9xcxT#*=} z!qYl*7kl;bnx+$3UwZ6L)sdG(v1&t%M3)g=R=Qh4GvR|w;mqv=NHs6c>FEt^P@*5K^Rq!TG@uPZsf2f@|3sx2nXEmDE zzX^EzAq}GanhO4e^=;sPb@lj1*~!0)P|k7=tRHgGeX6G!ALRDs1sM87Miz@Ur>94` zDd^P&2XAHdY>bU&g}UDen~B_bNtK0J>GJqM4DaGUxaIPX6&ob=-I^y~ZZYX?aF@I5 z(6WUAjap57CI00t{6_{nYW2k{@sYPw-BifTziuS(>nrwL(Eba CJ#)DL literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testNormal_First_Option@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testNormal_First_Option@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..31861aa33547ec0026c3817dc085854ae76f53f5 GIT binary patch literal 14705 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testNormal_Second_Option@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testNormal_Second_Option@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..50b5afa1ed5083873233cd692ee76b2f4e69da5d GIT binary patch literal 14702 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 literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testUnsupportedBankAccount@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkPaymentMethodPickerSnapshotTests/testUnsupportedBankAccount@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..34ca7b2b625bfb1913bac4c6eae06d6650a4b76a GIT binary patch literal 60721 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 `$3PE$J7GP0R4!=Fuz zRsn_B*>`%6ej>_!sK{CnDI8=&3?A=`asq-NQ9bs7P6= z$4Qk=SZJe2v_-~9@5sjsF0`M*+wymhTXv!?J-$crmzgO0drb{3w=N_GsPIh0b7xVc zlhxI`XEhXb7qLo)W&W7exyJ1H*5|v5YAcbR4=W%3ll;zFn`s%diEzjSY9xcxT#*=} z!qYl*7kl;bnx+$3UwZ6L)sdG(v1&t%M3)g=R=Qh4GvR|w;mqv=NHs6c>FEt^P@*5K^Rq!TG@uPZsf2f@|3sx2nXEmDE zzX^EzAq}GanhO4e^=;sPb@lj1*~!0)P|k7=tRHgGeX6G!ALRDs1sM87Miz@Ur>94` zDd^P&2XAHdY>bU&g}UDen~B_bNtK0J>GJqM4DaGUxaIPX6&ob=-I^y~ZZYX?aF@I5 z(6WUAjap57CI00t{6_{nYW2k{@sYPw-BifTziuS(>nrwL(Eba CJ#)DL literal 0 HcmV?d00001 diff --git a/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkVerificationViewSnapshotTests/testEmbedded@3x.png b/Tests/ReferenceImages_64/StripePaymentSheetTests.LinkVerificationViewSnapshotTests/testEmbedded@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..73994a01b5c36146236d1b53f2f7f1a671e15b6e GIT binary patch literal 77265 zcmeFZXH-*N*ER|W(xoX?0hOXukuF_91Ox=6mxxkCKzfHnkRl*OkzNG^l_tFt>C$`e zHT2MHNY09PdGGsuzVVH5ew_2`aSY5(va{D(bFDS!HLrQ?9sER1k(`8)1P2F)TDAFe`-z%%gSRV#V*r{EPdg8he!1pnRo;}v%c2PfT%otZ-&2S*l1 zNnY-$JMKnp(9xCVa}4Gzs!mDhReFobN4<277fKtvhbD!-Us+jM)89Bh!IzV7^7A8l zM{)xXPZJ;iTmNNwS%h1vXsSoC+l-;b(biP88}dbWrRCA<_>s;R7M6(00kq89w>bE$ zIJiWzICzwA{ya=`#z({Zo8J-1{o}(w51&z@%<%qoHueiyVq(@~mAJ3+#Q$@ZKY#FM zmXqS27ysj9N0wkNq!hc-F zmzr93JNAx7F!g_o4yRt7`LB`wPeY#~as1%^!OEZhw=r<=h@iXw(Wq>iKRzXj{qfUu z{D0dHTv2vAitsRLQ@O|L*Rs>$vzZVw&h%|2YYisKx(i z^uJT^&o%JhDfqp@|GNwRv9JE?i2g9fe;v_3V$}a%vB2!nY$Jtb{CWYrb`?&}Bw|6& zUGtAn_EG_aH=W1A4P>}Pmt%g$6)tpP&ZZnxF?o80-+#O(qW?QAypfd#f#<}&g#@3q zmjfKye(aT}`FlhqAb!F~*{J3Gaqta-KuB}2Ds@Ae6gwgEM`t2r(1R7Svx0wL?B#XP zEUhw+9|>qS_4nEPy^Y4nfyzd1=eA*__|gylijcmvH{Q(JeQvt(6-4_T5bc>_9}=Nk z3Y#teif8RgAf$IYv+IBpqKLo=gv|9bVr9o*NWbI1tT^~pM|^%02_EH3YS7JvpEr-0 zT4__S|G7zTae@!U2cq>r#8bt#cGVr6G&=uxf0wW!)Ut}2n@BcI3I8Jznq4I({sQ48 zk;S74JGgML>_X>_|H~C4<+u4EXw|6uV+j^isJ!^s{)~Ux&3Bnfc3U(;D&{)QZs=ySNhxhg@)pFPEfzIsIZc*!z{2IQCHQvT+P@(Z zrfUh~k|o>-POmuMxn-ls;`A!>8dJCovy0=)n%5OO-K}IS^X-^>0T1S= zQYE&$f1GM8jzC~8MKrD&<3a=8m$b5KUZ}||pnC1?CM#}t<__%iAo$75x70gGxjeq7 zh;uaUq|zB}nIRLb?OaIUnDmqAa+@iOly!;T zB=`9lt>%dqxdylG$PX4Xbv|<~H@Y*G1WTV(d#8QX-Clq3YX^3cBgk?P{%Boj?29>L zxpr0My)PZTpEJ6~EFl{ku(a(O$R6(cN0kDHqMhAd z4Pnzg^litK{lF+6?8e!Aj8i|;{Y`xmtj$j1Px{*`ms8xP&DCzyb1S3H)^=ely`LW) zqP>bvQ=e}0>urA#-^naq3ojN$y-GHLLm!x--l}n2(S4-=-^&k5YA`97)pbu@8EsD9ZxIQ!)G^1p4$_->j@cLVxiN4n5AJZpPK7GauDZ+OV1|ke5KELp z44oTJeU7Tg^n<+Ud}~8^t>gZ7jv*{^My|ErwUn+Pr=YUAty|v`(?N`^Mna#3pA1;3 zK`%D5Z;dK(rrJtlP^8&EMnl`Vj`zBwVmJ-|4|dVsp7A+qj3>RJYD2d?FaLCWkIxU1 z7inC5&?#AmzJu91YL%dHpv-3T!^A?M0-S90evtvQBcrDSYBD{+6CYrb-|m*oA$}}U zNaepiQoQPs9!0Ktg8^|Wi5Pa7PIXnnV9*pWfr6U5*ZIV*Av$gyCw}0RcvEx%c(=4L zV3Y~5o#1=;tdUZ_cY#slIj@NEjih>x%Ww%M5=J<zOWQcK!GYp=$R^``p45 z+oIg+RolyqSQD6Y0DtJTMlDJt%j$+_PJ>$OPdT7>Ex7e@g~V~%x@a#xpX`9 zwMG&$yH9={^4P387#cfbXDj8a9=1~7os+e$ZWY(9XK9w$Fw*gZI2;EpG=(EDdom6h zTh1mdHVyN$Qqs?UMyef+Ur_B+L>Dd^b+wGXP?%spaz z-hwux^u^{K!sbBh4xbitn?Tg41jd(yY33 z6BjA3ksqs7M>DBZE2&bWm;7XUB&{lofX8F)4F^Npj9Y7B0Na(`m(5QmSk}H)$8WOv z3sr>ZjH6wy7zTaT^-$$QWuWeel6O_bLlUU!pxZKp-=5@1TX*JaM}3Rp`oQ|l_oNXO zI%pxQEaI()VT_hSrUoXjr>c-i^V}SEYVpfgbKC6dHWv$G!rwb4)XuO=Ifr?sRd`4C zx4vUTPunjfYsm2!$3pp$7K?3K|gJ!UC3G`YcRUm%;&XYkRy>&B>6IHm*g;+#&%#^Om9+PMkQ<`;XH}_dk+F*RNV$WV zes>GFyQBsQ=arYSX|7cdjaL`&v$}Jted1KOjycs+7?-shBdVnd4Khq>x#yGe`%3x9 zbPLcTgVkH=2d=vhT(i_u8P?QCiI*s1@2oK%)DSrVM+WqDT^fh|M z-0?wJHieTCKHOr}E{le<^m+B-OvTdPWeVek`Pk)VA}0g9U4I(P)?&|>SQDmY)kTLc zONZUt2(hu_k!IbXQ|*WKGaHf&B#AUw45X|Eu-z^`hbP$Xb@=VKjt6pM`PTAZ%xB2w ziykntAD4<$g~pK?YW!qs`FhTskFv{6)>4-c9Sj9a?)!n*pll1LklIv0jzw*RQ&med zzbZZb@^TMkWie>uJ^hJtoM>SyHYkm$jhY3UUq&hXiYg3lCHUR+|1d?edqkf!wu6E{ zinZqp4$e3r-a43Q_lPQQ!w-h5)$sCk3lPZ-46YxBlOt&IUR|L`E3PqG9nlEnQgVieWzd64h$|dlJkP86XpNO zx54qhR@G!XL`aTLDP;;9Zgc8qsqQgko>vm-7}Fg3vIj>#zB^`=P~uXlXnMS$!P&a( zn-MNOwlM>j8B}qJa@#>PgyxeSJm54M(5K<4>g1-hc-$yzG;j*C0|HO2hxHJDNd}_C zxBqE$0C%^hyy9aol6UNLp7C{SOESBm;`yctOfrruiBc^{(acf{hSSFLABKcgV)-Z* zR}(C#dleiQ^XD4aUs<(Org|?g262SEca-wnciH89#r)->Fbx;n39?UwlEc zGfuLfr`P@(;gH{EgFK#SXJyFD!MdowhlUiiN6I*f;yQPWAFqNy6Q_ZF|# zDXe%|381Cm6cu_1^F6LXdG6)5-e2~3SmP^U153gWc~aoKF5%*1OtS?qT<9X zbPk`Ig`+rXUFg#-3$8Q|@xxK`B_cjg-Mo`S7d&^^=LDw>{bL~xFLGsyoOGL%iH8d+ z@;r%~0`w8W8|=TXAHV%-PX-#n!S4rzUH0b|DeUomkhf60wYpM|L1K)MY~4oqMzkZ3 zlZ2M;$oH6VlRya|9eh>xCv!p9Qby5sZfA!qNn6)MY#wKOofDR{`>BWx(xjQV%?0R+ zjgc7cQrAQ5NbF^Pr(1e}MpW_R1;@T**hU`MT&XV*$2anSW-{_gbsKiN>djfFH3LQ3 zFQ34rt~t%sIV>C{Zym5yU|}1o>ac18RnCEijjtla$JQo}nq}csC|^A>qTkuoZE#5~ z*#%lGDli3(BdDz;WY&!wfrV5x+YOO}aNG-%Tj!_iryQF(meT=^-(sgyVi=qm2ABuO zrF%)ZrscMDShC~!bz1seBwFP*P1kMX1y^=?3+dTe`~3NWYwalU&ei#h|@vD zbHAeTgLQ*Rj_WGjcaZ5sn0v2TVOHd|Tjvdq72kV*8Ss%Kyhy>oupVoZ?7TZBS1!Ra zuWRK?+B4_44c1V~&dXNNQxZWb>-M~Y|e5y z6eOE^t8y>FTA}59Gb@wyChx}a(dLAuQHzm^(I$xf_V`ZI)-LrjAonZ0vA3LvTuuA# z!~L_dETgq%*uiJA8`FO>s3&92z1f=lAm~zjaZfnr$91MEzD{x$>6Y6`yOxcCVW!jm z%<7tI*N-0vIR4&mDqts+%ipDX1j3It5!<&%*mQXyJvzwUCT7+xxv7g3Q+LMVLan#Z z3ZJXx?W^Nh@B#?t1Zzmf5IY4gm;H za#-Eky55hU<|HpPij0X~YcR4)$mzt~x1Yu7CWmAA z!!WBGm~of6J^aq(vv0*Rir0LK#;RNlv$y@P*~iQF-R-5VXL0lPX3-h$2v_Xj_@ zkAug1AEzEB_PK}_g>|sBa_b{@Vpl1Hq)NH0#U%=Qi6`Jo!(LrjKQ+5Pr&8s*zPfmn zsFiiCuB}}6Vmfe zHE?YCn+kueNPkB(x30t)yNs|Q1^}6x=TDiDQ(m$+U`wKYGSu9hzs;8ddbq75j|0+2 zog2W3L%iFDv_G(ZjywRVR(k8f@^$87S`^=lpLuDgNL4p+Vqv>!NAd!juk6!bzQ7h* zREKtEMT|5Iee6f!Fu3R=;WIGRVf7bLW13dM=qY4`I?uiH$wkGapX8*_h?K3UwYIIU z@=5Eub64XyH;cB9=0m7iiWh@0^38XS@bkk&@ufj08i)R%_vP8OcF@tn;+FMm(U^p| z-E^37^e-7EC_ao_4GkO_W5NOQ&Y9BT&n3$$}W@vo1RVUA#ApU!i;jRE=9{kS0|EQgz=t-p!|hHA5N4;U$v zzBB1D^1uSH4q^SK<0Y%hU*sC!OY?XXIE{_8-iS51FqOKNJZfhRX*4iHlnnH!Yz7^W z)~AYOJFsB={&TRs=x$ykA^_Nz8jP%wIKFgtB+ioie*fzp3Cv8;1^ORHW0s_v6UTdn z*-T;CYBVBUK%y_N`or;;H+89 zDxnl%)&Elrv{R6BSrNUHIrv=X{*<|x!qpz!3xS!J9`x^*j#wZ1=w_SX(3!X^JZKOD z`A|0Tv{Blj04M&fEDX}h{7mQyFLeNcFD25d!!<|^>!~l>-R)RFMsMJ_#DXL zeHZCu-C||PQC~1bB$P6hD(!$78qd>56uSyqc8jz!Bg%MQ7}3`vusLNh0Gw5RIT6%S zsj6i~Z$!ylAt!oK5*66w zC-7}HHcvZem_D!7q^H7(yGqC!?s@5D)^TS3V~{K(cOM-!t!DEbhdCxZM$QFQoA3H6 zs_DF)0vgas_wdN&E+ zxi7Eo0)pm=F=LmD?U9h*Ov|HrRpafYpevgB6Qo>G1>`IOWiL*o*DXKVj^Se_)umNB zH9B}i##djw4kq`lVHfgCCOm2@Qd)1Tmhj|fSUzs$MdMovDGl2~pWQY~)l`JZom2XZ zFWp7<+`9Q93Hq2J2O8CxI({8nW2eo$hknQuud2BGDbEB1A(_Y;SDn{U3eV%1?ue5; zx_iMoXBrApJg%GL$=pFM>ve*~7F_}$$eEtX$oz6%-OcRF^c6)P@$HSiP*3!|01+ur z_a5j>k?OITu3<0#VHF;%&(f0zmDh~;P`w2mHS!ozU5+tC<^?(cLe`=$o&8}Wu01wh zu=Y-arMsDoZo-mj*!P$5BBT$W-l)d_-aV08?LBtdv4JHXxb0}Ih#!9v@CK1TTf$}% zZ-zfEo1D~z42hl?lRm%k>-RNqe5(LZUVr$G@Q=5+L>1JdWwzCQNf*m<>N*bRRq|aA zQr7<}NpAx;2Kf&P|Z31AS0%kF7&&~Ehy&PqWF0;7g(w_Ya|3P@j1KTraEb& zmw}#Ff1_BiFtBV-l;FZ8>>|OocY`QX-;qD}3nc0~`f$RIYFLcmuPf7o>7!=||Eq=& z86vCWhl!I(9=19^eu_KK@y8`(6M^3-w`!oV{qubWkr_xRuQFfy!$df~`@m+aV-B2u zbpaQ@h!O>m4(+U9&|jl^1fp-MKkdk$_G6_~Nn@@rSUR0fIfUkt^I>fbpp`5u2!}E$ zRJwn5o;C7~EMq;UdWOYrs~V#LrhObgrsDEn4c`J@`qsUqza$c@0=|Ggtl8reoT@&$ zo1>GbWD~^nR|npK4HL24sQ;H;sHyb|pGU_Ft@7^8t2A~N*PbR~SDzw_*Y_$cSQgwW zRk8rsr7QfJ1kGvZ(qD7Ob{(+v_d|bUpTByE?fD-7W9A02!X0c}|Myo)V24Ka&Kvx% zkFl5)i|HQSr+WOKUtwbqTS*1&pQHVsYxdp%2Iu|w1pj~PN`EyM=@0Bj%$tuTm;T+0 z5+X3$p=_7yvE0tTzxwZx{;$0PJ4ZdoSCM zZz)b7{UN5^shX8MAD5Su)t_T2YOq(|fs$H8dZRe@O*lTs<2a+6yXWZ;47P5QVb>RX zP13#Bd#Cxv9_mf~a(6ZJU0sMzu{b6bBaofqnvbn2bOKoYGsz7N?{XQLv0(PvuqyW0 zi;<<+BXfF&BNiut+b`+1NbfI8?i%+DW^N!_i%y?~7Ec6HgagtJ(ZBL3+me-NVa!+dtvvr5H+s?-ViLp-Z&SWyDG%Nf^ zds&}b@8I7f+DBqOYMuCWm6p3sHeLej&DRs`fc4LZ>f3+gM#_aUSJAHN6J5X1`>1>5F~n*PqS zcg2(={!pbU)Cp-9OSoA5SfK8PwanK5c%P{nqhh|DByNAr&ig_fUoo(g#O@~r;ouhm zFVK^43k@Qct>QD(v1n4Wd%pu}qRdu(s>m(?7CCEY7B|6n!R+!}t=CZksH!!ip{Skg zr?g6YPe&_=@#29qv<#u?0b7U=PzHpLjPStpv4;FCGUrYr0C@?>UDurXlyY*f9HVW2 zUrs{7?}8dWvu8z)mUO?_d#kHfDS?bfvaE)nS2iB=O!%yn>Nxc*J@2@&`?87Jefu-# z^Jar`&eX7jR#-jY2)KtK@SjH*3Tjl*z}Gux3qN6^cww|C5(2BO7+NC&--p=pXb2A) zI9DvYU}`3Yr6^f(al6uBWAFmfD+pcfnC^*kI|v?2n0_59@d*Z%Zh|SO*o7}|S|Jk) z>I`0q*pAzXyhcrXpC35V3=`B)nW|lu^4kG;OTgsPSpyy>h zcsO7#i*DGj^j^oZ?@sjrx^XwdB|q;<^clJLMO*C0jdT{k(FvoSUdSGMTGR!|)r3*l zRHRFs7J*;lcl=#S)Lr?6s5#bNNpQX8!q&U^b>^s?i-y4fuEC+Ju2H?3{lHiK$5lth8|}5o&X@C7;u>wLJZcP zmjh)n2tsjUG}g1h{aYjx-5Asq2 zn{e$N$7(l~jfS^bf)>4t zxk6rtsL|DFi)+}F?qohx!D2r1c9vTz-Q%OJ+Rit)58iY14^$u|jTi{vI%L1&*ujpG zAQZ*4e1iM7>t=*&!R|Gom+sL=t;I3|IXbXJ!g)p}klYyxr`GLtJ7=8Gn7Et1^C&9% zl|8(COkHZ%nzCni@|jh1Do30*YRB?@%(ttO z?*1N5?LvF2*?V1pt8wxw`R1SDVplH#;*%QI+lTc`q?)Hf&;S2{xDIQzIf@ z6wxEH#}pR$Bvg5YA!N;?u~ z8=*Pr-#^S_vQrNetOl|YgIKmK)FfAV5I=5v(?J|dKe!v0*(i|tc4ybFzBmHO$WzWU znB>}G?|$7}i-ZKz8T_V4R^{XFRQQk6!o{x{>aHQNam-$m@mXhDwORrPijuYr&(8Hr zUItep(TZX1?8rUZ5*R4`Ge$R4zg2KnfL`P+ut3l;h5y*B@!0Dk7oDU^q$|1Kp(;9M zJDjV}w4$Bj2OmSu$>LlE;olLERz26mFJ7lqm*vF=dI4pd=KEKA1iK|=rW@aJJHwt3 z48u0otX~IjFKvJ0jgIL-oL&;*OgVPrgq^!?z=B!BRMo3oYsuTN#d|pCvSB+av|7ab@PlQtTb{t5W!4zcqENsX>g( z?9W&%xudz@!t4jXg`7)x2V5Gck%J9A(EEZOuMdB#@`wsS(o#N?A9~2Mn7c*#z2xFG zt)q3Z@@Mt2!G=n2Z9F2*_xw7#P7j#oAG_U4Eh#F9IhR0s{t71agVSuO5z<0WqQwtN zP6O&h`McI_v5LhCUJzx z^SaZu?bh~(r05&9L2u(60bl+LsDxx-%XdG42prsni)|LLj*eAR5sWNX*XV7}O)T+%3 z%{{*Sv1V5m||E zf3k<8twT^`T)7I}{4rmq1;T!j?rQOF|ItaqEE^D~mH~DVjg=X`PN^i@p;xIR`O(#F z=>0D~D9cG})cx3wfx8CzQKVI)j+GB{2%31k*uLgR`vl0W`adQ@caQ0)Y~C)Y$TW=^ zk=*NaO1?m2zj!FY{7cHF6|+?E*+W?6q6vKWGKxvWMkt?K$-PkziH?VzXKNuZjog)G z@%xzH8_9Nwy3(T}UFNMq55Mxw(oYc2)lzb9?)^H4_*KYBN2v z^S%NPPxWS+!%xODgl6Sn!l9B8HkhB}?EI2bqtP@zM6M^Ho*Zj`gUtB)0gXbMoM0tz#GEO^mmlh!#hGD8V@!>jzy{%-(9+yW!qaMgTBq47{?9%(qvm>M^ zRifDbT%{b#X zuhNUv7W>HQTHSPSF3jLO<08r`6O;d9wzSi@_xxVg5MF~(j8#4Yv)f_!_><23=lCNQ z*nIq}gd9SDPXVhFg^p<#;6Wn-6^a+!Y0cln$PSV)GHNa|ieOv}9E^zD7?`oQ zOZpuX&-g?=UAH4vQJc84jb>^G=!cCXEtS@93O8@PmTRTuL$xCnx-gzxX9;XiSgx4( z9JuV&6SBmsFZ-Bm3fuw3qBXIZyt*$3MVB?FAMLO7jRd#ymUE;wUhlY54V5ff{mOjh zw3lXiu=dmr2JgMSwX3yYn=$z!LTYm{)*#2S^H|JrqgI-ajbS}+_@yr59;O~-Cd+H) zT`u}r9{pn-{9ixep4w9{LeCF$1rIil-p9VLzCL?;y}L!OkrH}pWfueq8@+uhI7)J&z%r^17%F*>Csrs>9JCW^%WuCZ zVHY$_Wzdb><^Bk}Tzt}^uuXR^HTkY4JQX+?tiEBfv*H3?C3P>gL>V4s`T2DV4j-m% z<7!ulQoV0q?(^|FCVUP+dDUT$jELM#}Z3_Lv)_B#8jv5*v_y?3`w z^O487EkQkhVT_rDllF7=6d);Zu$9x1)=s(P^r|qTLu-wF=U}9xvF59IzIQ?B_$oI6K>Ovqd%I!vmN`5O+MP}23I89NaJuHKd&unq&m z9P_rxIFv>#mSQuddpz^kv4;`PefUx#APF2I-*OWPbzn9Dv z`-^Sy-#nM!%MXIGYLB6m(y(rS|qF9Kv+6bBMk3~4De)IEG^-0~HH zS{`z|g<+1s%^I@9+4QAkS%RW+f8Md|mdu#DKJ9q@wT#+!d4pGlh6ghYcrr8K9NOF+ zgz*#Zr@0|<)vg5a8K*dtq_*_7Xp1;YKbBXzS~)2Lv>(~q$NZYQo^+U@Dd|r3ybbjf zN#V|%(S=Q(V-}x{+u0?Wp4|!2-oZr<(fWDDyA7fIRGdxAs!OD?}mD&H%AK` z)^PNz_FFe+RdeV#^9q`AD{q&#dyTdvgTi^Q5jKn4ZM}z|L|oBrcHSl0Hx*RsACXrf zZ`;WA)8K-{nzUE`bo@7A>)Hcu8>R!_n@Z*~-=llkeaE%8t> z7K{*ggHOfcTk>nOf$Pj!q~lGdkAb6Fqw?Rq7*L-0a1-KEM#Fw=xFod^CUFK_z#ho| z5?h%&C?Cns2G9kHX zhTG&x8X|wgH55%&rVLfO(Ii|6F+iNw8!uUWnzf5QvNuqh1acxXP)ASYRrh`?+enoA z{hcOvN_v@tpze(8*?A%QYe#;}EfPni7~TGg(GvJqG0&a=?ZK$0hXc+%`$bluP!1%j zg&s;)Ur>W2YBYsbS?D9Kj@sILuhaYP?J(x#3@>|a`82JJ^*hESyz6$+3!R5#(LzTM z5E{F2_V)hF+Q0+%)V;6gKPn#@b>R4jJ*8U}+WMeaEfG+x;RpZ2tfk|MO9EbMQPr>F z?n`yMH2dAEN49IvshwRK_7RzOnD}vIFO^h52jFNpfTI#I$N0X1H1_%=j|Fk9bDu>< zy~7Nos)zanyKN2&t{kov{#M2;a1rXKjG!*cfq)Gg?BgVyN?FmXCV`G9W$@Lkw98BG zRp~WCgg(R!_epQLm&eZyEKc1ehK_u>f$^wca^cKa*R(hlqge#K{^DaWQtMSPy8F~4 z>+eo?70&M3SU-n*PVtscum8DpD@=4Iu}S&^U~+OrZ(o2qjSQWZyU&I0Nain~OBVIw z1~h&6u4L5Y$BR3;K6|qFb;Gc6lj~TRZ;U;;bW&d|)YqDZs%wNw*z#U9XJj^}4E^)}^x_d#%iF7A{0@8epIZr)!v}tv}Lvp1)`H3yEFn zLb~hTwOc?g?4Vp-_<|EZp*@4lo|l42*ecc9Q)r#RnH*BQ7rOq6RNsFOKy&-{5e>f? z;ThpGsjJ7&9D!c$S2CE#-xM$?Dz#H`Xm0EP(ML^7WDIRFqM?lXuET3k5GzFg!T_af zv&T^Hp2yQeTYTW2DLgzfwM=?zD7zeEjXcA&=%Xz$jtw*KJuh??!aBI--;A*`aRa)f`|gkb75?ps|9#PjsJHj0`JzwUCGLmMJ-xNS~COVUQ3y zi0yv$YF2e^`O~A+&7m2Yu* zG+!r^n%NtJs_}d(2TZPXZ>nVb8=yO6Tb)awc>65N=VFw9LHx-QxB(?;FVPeCi%S8V z8B;h7jeGxlv#E6ip8@jI29yDcmxApme}%p2V0*x5$#b+;5nLF}5Ekp^aCW#U$oIlJ zLTncw%e~O?GdZe)Ezh*g|KDtRK&g0MLi}= z?J6IC)f#%UygDped)-7cyJ8~5V{%ygWvSmRW@ZoeU2Adxx(_tFk>Y?;12>CQ-HBCX z=(YK4V|FMyoF%26jKC5g&=Yo^i2&x2CvQmktNL$4I{tK6x5(5$@>mHnT|@}e3lM;Q z4wlb^f+-<+8@m1BrHhNfe47q5y$manS~JgHAC#CI(uG8v2ZUvJW)#_7n9BEq?7(L0 zIg@t%cH8Eg+o~Jtq&9sxF{OjiGnL`d+9R0E*QfjOYIB-3K$jD1;%eMKt5eX!mHG-A z`4utk^%^Um3KCWl-3Eo|O9wI$chkoFARqX51@*`wp^LG_Jq~BTGEq`CqjA07bgnm) z*6VCWkKE#50K8u!l>m3e_XgMoxuvS;SPTn+bWp#g$zdh0m_b>e;g zy6uFBWH)^q=_lx3uFKFPY>24Rm3sEE0*JwMf@uAhR4@*@^)o<`uQoS?x@u*lbK*SQ z>Xh7Y`;tM>Ibc7#>(6J3G3u6>k$lorPF65FB0o6bb*SsKcU6GAsPPecA2HB5&km75 ztlQP;YbReGgowzWgIgWI09`LO1%MFu01S{Rgs$g$uO42)OP=oyX-L) z1%4!5p2Bweqtxe&g4VEg*j$)2U>&QxtKfWX*^|N&mID{*&IkUmb_t0k@chPCy>(8W z;-UT96$zQ(6?y#{Q~L{(*n78fxL5+_QN;-U+WqlI{Cl@9gs>im0&2zA0OTg|cCsGZ zqYK@4Olcl^3NC+SXUfOP{Oef&9n{euL}0DNXdQP7FYzD$B8IAny^l>#gYD3qUl1_{e27L`41|yxo?^J%IkJ%X3#>rw}Ni~l%mge#p&`|kg z)oBxFSZtBk7w3(X(l|Sny}XDm^;ybXBxht^ROk{|>e=hYlozLpbmsfPW@7`k)A&jo;YH4NfCegJ-i8^(^t8ag_N0+R z0QcY%=XxG#yN5tRVKo{fr%N61Zzqx8t~df(-&Tmf6{~WRKN&y0#(CU4ER1REv8V~M zJuL>+=L7&^XN=H#LBM@KmDAvUo5z|tmUWFH_cLC0szY7zW=4egkYrzJ5MZ^HTFs!0 zu!1jfCE;Z;J5I?sYCBH}?t=b|l^+&g)*M#1HB{KP?sAU3PCt$Mru@V6>&xd#U*OA` zy-gng^Js5Q5JHo*Hw3u<>&`K*v29$nrd6mACamh&+LQF9X2}7FHwr!aUPl1g_K>9} z3jxOcDM~)$u3PdI@qDg9payS#0*~^H?)m>UJlsT){9A`AZ8hXJkF{9Jr$8q_!|Q@A?xz;^x3Kc z;-WPdMx98rbl#C40mh=<6%&q+0HEQOz{g-7y`;Xat=ZVm*Rep|;!rDjnM-w9x8U7j z&>5D%28v{n-#MpI6cO~GVrN2SSH`ZsU>AWUXSh3+<~i#Z*LHzp;5ZIFCi5J~`E}CF z)D6l$F&-(yMX-dpA}T-lSEMPw)*+U6#g=EWcdte=;EpI~!=Fn5ZArYpTy(|5(oD}r zNzanA?YEL#XSB?IGarv3v7;unDLpks8(oB)Db6}B_j4O{GLD2k$1F!~pMG$KEI12O z1Q-E26JM_XgtEq=&2T&PZA<^rI%4?MD!KJXpS&hYQKi&|d8{q-&FwN;x4jnfb}L@? zq=|Yfbn&C_ysCKeQIgRmZ<)QX>60T?F<1T$X&OKZl20M*ZN?{7vP7&;M1A?|^gdNQ zPjBnS%0ORFm{4HVItqHpAH{eyuCOO-k#2JCNgpMIO!Z(xr!SDjU9xMIX=8iu;PEqM z!Cbg$NE z;qXu4ou+k*N1`Ib6Zv{O+$)<5C38g+=}UA>eAPpb&y;lOh}t_&N5z2Va(E(;7;2sN z2x-d1Q3gVb69_Gd9W3jVzx>~DaVS;u<}kg!Ir&}N`u*^fj>^j?OPp;2#19Xy_LB7| z8Do(P2R@u#qk3r9lR|RaokLJ3)w^BX0tEQdi_~bXBebDiHNSS<;KnZc3qBM3@fF@e z?EP|Vm#hWB(#>nzAG~%ilmd3TvNJf~qvTr6Njl+ z_eAx5jpbz{*_y<`}KiWJ?_W&w~?@`s?p2NVsCyz&7OLc)H zS9e5KxB0TJ3Ert#dVWoU%za*CEY3CZnzGf_IQx|`mD4JuV|W9DNL{D#cDT%bt2A>6 zXtd*FgTlWbaxh4`%a?N2e^(YOM*X6siva~j`F|=BAH7@?*R(zbw}BfbCmUP812=V` z#0nf`3R0-Bg2Gp~H!&#IfiE3V%T?=kg8vc}CXCu2Zg^PiE%R0e6-<%Qt}>84hb*Gf zr=78!^dU3DJ?D}>wvVDy&gGS7TR}NJb6B;|6>c2{V_l(EuZowq@4K@`vVd#>np^mv zkEHn(1`;#TLHd6@a^O!z+@d02CRnU_uoBC^L~?%|I^G0TTyo*S|0U)E==TIGS7>Ea z`CmT(esU7)Cm)1e$4Y$u^{p%v`1q5;mj8Sl534Ak^(LRZAo}+YfQanB!y)?b?EH7J zz4`Cn`Txol^orrB)R|b-8Jw!NB7ge64HFFP;Z>Tg4oj5S4ccul+mtZ4%Z&fmQ$m2` z?I$3(W|FVy-cS31|GKuk`UGigECH2p-Qu&+Bi3^wdhc%TsEB@I;sI-!T*k-G`G*gz z#5&Eud*i*4MKDVrl4na!lO?L*F5DoJ z2W+O|&$hk6&@iVq(Rm0f#Bc3yhFpt?C>CfreDV{%1$rJCPd`iyt;#pt$r;^a4%Q)XIMWa%)pjVwE za%SxUyD}+QmR@T4LE;(!8*7c=+l@)Ca3R6&B4l0gF{nThUO)4k!% zYiJpL2Ci9`piAekXnFPLqz0|vRM2)Jbi+@JvL0HVtzQ}KnDXh7sY&$Dfp1VB!tkQ$ zhp!V&1@Fq@a^7~kkXCYX9Umrl_YGuQ-P77r?tYBwom<}N;=>(;^(uN#jTQ;^W&KiyW$0%qTY{MnR~~Ilp3Dj+hgXuIKWA|0Ag}F>8(JXiQgg(F_@<%q zD`R$ggz2U0B065{tCREXBm$=Splh_CYs;0Zf(VyIjiuJ18K|YYu+0QnqSDO=m5HD9 zP6`ya>Da=kPy|ZvI0!PP8yMp?&y`YrZcd zWRB$_#c;<-B;#DR%`87zjYro^hxr+WL~S-x(G0df_y6DaXD-F`1&0ffEq8_RKJsnE za{LVRERT`E#j*^6?a&z)?`hNw`o};kUa++MWU3#2wM+iGvB5NrwGd^}Yxu~)Q%K#5XFE^>l;)nJ!hx>2V%v?<1s60%< zV9(Iz^j-#o=uYz5q@0N|7^Le-Inv%*G^syUfGt*m~%- zckyzk=uEDG;d#UK>ctsfRl~BO(I;*X?7qlh@_dkou@?xvr2{ZSVh#FE2whG-#=DMw zeT?6=rsJ&!mjtZJ^Tjw$U*!fH3`VanX%y(j%4+(4502`u$USKyMzgqXd@sZMCb2wA zwb1pWFY3EPA7h6>|83G(b5AoW<^mR`x|!z|J!k3TAzyTg zOh;~q2pn^oig2PelW8kt_JQPk99b1rmvnO4Jq{B3*Q&P%X&O>tATt9>_{X3-CJ%~0(H2&7UD`LJit!YlvJ;W zyPmg%<7pBsHBOznJn5}WYkOnk`#q2ATB`S`$XuzfhsWlqvXgO3p-VY6;&HJ(l1nEG4T!FMB<_!SfBQd19pH8AWJm zMrkhlI^b+aPJE4UDA<4V(_nh;8&iQ|P-%sy# zJ>R&phuO2%tXb=xHEZtOW3(-R?gQ6wi@m~KgrbI~k6wG?6@h{u~$ zX*PlIvH-M5zwF3TA5=J;rVExSD-;|)c}5BTm*Ds>EN>e}C^ zuX~mgY|qkM9P13brECTSjpbjMcr)Q*t)h)-mtrN8fQZ#|0lwYb9(Fq@{J@_`Z6(kB z?_ENb@z1uI#lu0xhSp-GuU@3KM65np{3x6#bH~YjvZX6EBeBKh44cluGBLHS?Lp_! z{qyK)mO)EAi?)H&Pd+Ft<{@g}hG)xUkhbiVT94AYRWMA=}G$WKetLz@OO zy}olrs5QaEP1+xhDxkUGT2h6^qtdm`v50l1>oa38EQYEAsl=Ve%@}kNK)6z3jV60UC)#`!Ig%?ceRzE=LVP&6!G08K-L6Hwm4ggL z%&c-2&Dz5}r%a4}`eA;(^_N-Ii`2B>%+E%zZS1Nr<@cdqy-aIRIbfPDV!C?JyFd0! zuyQnE%8u@%$THF&F|iQK*;LpSwM6}b_A_O$kwnG2Xv=F$PQQ2VAN>qMtCP?4rP4fk z)@bISS+#d(CA->u-fC|;*saF_@3l4Xz;Ujk}RQbBvwLr!X0DKVj!PP z^rc3=yMoQ}gn0z>W8l=KC66FX=5^jQUaK88=#%d5f16DJVHJ zR3xJ%`zu1OxcCS!H(sl39P4SjdtdH}!KLSg1w4d&`QVn^NK1&EsG~rkPV51bc(}g& z-CnaT3#ms(r}}FKv)tuc2`KJ?j|-Vp z6z*!BRE{&Yk>&Ab)_9!IsEK4(Uvcpb3DcG(RB^g1h!ppI1GoEnh6S*E*AL+Bb#r|I zzj1i`RA6mM=u$%;^QWnoZYS{=;4aA95pn4}%V|H|@n)5sZF+&vYgLPt`3dh}iS{0w z^sY)8+`JjS=P8e34_+C`kDB#&Yf=oiK}cxuph|ciNR=cWR|*m}zYNkb~N9_K8A$HB|A^7r|G% z%@uOF$wLVaJ_^>Vb8!pf0D%U-_6e6SdZwasK52FQ&Ffs74v%O@0P<6kniY@!3>{T+ zy%$$4hZVCLFR3_;NM#)dgxLpaCORJ>RgJg0;AL?rDDNhT3)lp(|6xAS`4rnN-E*I7 z=_7ygTJ!Rn9?M}pFG2tkr*3>`6C&s2KawWd8KX!-mU@ABw=Nzhv$Z~*XWDbMJ^H)_s#=NucB^B}_SJokeNn?Hoh%{T+@h_jWkKY^v zrXS^Z{%Ph#Zn*D}Irp*>QfFN9MV1oQrWp3G{)Qt{%!jxxB$92rO^-|y z$}pdFWlaPA2tT)z1ZaxV9+-#d-zz@5Z38{QcB@N@T8Z;gX5DI&=#9UU!3>;vjws$3(IU0rBQcwIZp>ZNw z##M{N)DgyxJU?T@ZTqdOga+HT$onRDPV{QF0eLl2ccChziX%Pak)!LNpw;uzkTW0w zl>D$CcA!yR8)fzTQmD#gX~kmkiJe~aszyDZexa9Y+J}{E#XdzE zEu5IU8B?tJgi2Rd>bZ}}W;3q)W*8!aNFjd?X#%^1UmFZ zS2N%@KGDJ^B0uoHJZPk^K&s|$Qnu+F>2u)&3{Zx3{`$iXBb_OGRX1*Yi;A`FGWF5V zDU+nsoZtkY4fiVXBUtpkeMWHwTHk&&xcwJ+Ku;2%r6r2?qeZQXDunFc)||~0pG8Rk zr8wGI;U%#o)tZm3h49WNri36LOw_#Xq4&8t=93f&zV);}*k;^d38rBhg#VWc4u`Zw z^{FmTecs_c*ssGjB0FP~$HqM(&Y+jq8aI1pl)Bq&m8r4f$qrIQa^wOErN^~DZSO;k z!f)CfX;wa8k;d3vur-}_!7q0D(*`d7pg2Iizjt|O@Z_axs{E**^)_ZNzs@@jfS7sPfobZxTV2SEM3ni? zqW2>p@%<>%qpfD8K zX_s7u0&~v>ZGuRc`j(DQ$1+%hv;D&Q%4E{Eo+IDHG76XeC_VA8@l#c7wmj9;CZ>{XLP zjzfPXR-Mne^={fa|0?15ZdCiN)0=_m2He}8iyQ^J$_kn*YlCIj$Xs4koIE;tQrwOL zZS{LUcx(}t41|g6s11)0Sqvp`N0Q2|lW4O}OWH6#3~1-@qg|>XC}rFW>++II;&qsP z=U^ptc+Ti>PlKLK7*j+J_!N{X)_mj__S_`LgRAGLAt&Q%h2G@5nV2}-Z#L1!Dix)u zKfbgr%>V&o9>L(=$4eR`7E+7-L4$W$SNS5Zg4g<##`% zQd&dTV0ycR?~U^`P_!Hthuff%b4$COvi+mIE5@9m0Z7K6c+Jdb^}3gby%a81#&}JZ z-*p4%LW#BmE6exAbOTcrw}ao$iclIwz4sOKonZrFcJ*wjO+`}GuSltu~Eq{5InF3K{VKS&sg>A}8$KzDf6DjrNWHA(6+OFXO^5Q4RBE>`JcXA z|6K2V{~)p^EtS<8Jkgt%M$KoR^lY#->n1;cYc7aaMK&LOh{a+8I$Q2Fn_PTE2 z?54@S#tru{w57bQQRfp_wRHAO-z`DBupa-z>8_tZCP?Pfy{-4Wh`r;hyoZb0(L+)~ z={n2AC#)Y6d5sCgU-d_xw0SDo1#LS>W~>JC7cH zjx*3Owbmh@gpGIp9uBRy$EQEd=T&H6Bnl$Fv>em}ixjF5d!pUlG5%A1dpVv{!c4U) z487GLQPuvVz7C*5y8)}l17Xsu4$_pUZogX=MDGu>Rr2&ela5mcvOZ2PoB!!X22F2) zleG^K5+Nw(R_`}G1_nM?e39Xe$^EH=7*fyRiS3nFrF9VxxBXR(p9ME@hZ z>UkJy@e4e$n_MBW2Y|Y{m?c(97^~gnxeqoJti_99Ep1!_w-)pgn`r(LYWr#Ahwo-U zYSHGkg;tiJ*P?@A*EGvh2QO9t+Hwom|G_-uGi!1ozd?o9nRiHsM;>T5WQP(y1W?U8 z7NwJ|M#htIbvy|YPE*sX)2A-#k*4!aK`#5-!cA}xu*iAF)Jjg1lga)$ssJ-hX?JHz zKGWHip3H(gDrpbm=tF=<4!$MYx-o%w>t9TZu=W3jH``o)qx^M<+nuyUHfnZq`c=2P ztKHYR7hwOXxRL_^bjj_$2@bzE4YX`9++K8Qz$s}aL6-yizFNl9_?u24klKh^FqWw(opBM!LGwQ{ zUmi@T-$mZHbYe;Il#2i$Y*(V`w(yCaVeUtdaRQg@0OqTuaZ~j~Ix#4jL$>8pYWs7T z*z%s%V^w?jg<3!hN~AhYL~!K01)f7ofyn)+G%+o~-Q&DBdm&Zy9-C}qw~Oh|E8Twd z{K~kN* zB#JZ%XDVyFfi%?Qc9(PPTs;TrA2^}ZaqQ@w%EA875ywvvY>@q(*Y`sITNjLN(iT+_oB~*5+=6~++LWa+<#zldxqdR99SqSPr84SLzWdacU|@>^*#J_xu~2IIAy6! zduyy+D+fM^eOAr~+>TDIWfFQH4L4hrrJ7W`R$atf0+o~{sm z$a28gvro2BY!7#F$&XF(1+Tfp{2O!&Wevh-Hxc?08aFMQxbIFD zcdRYO=KcYtvZiqsPkt=kLps^-eQ0m)%U@usytY0T^$nAHh5pgB&uUc%+^1LzhQ!s*z^A%>K&jwS#O`fKOrZ!vsAjSqw=oX zqxwdk@2{R9HTs~HvHPo>ni1>cZwhZnWZrX^H+HHO;4(&SY-(hqB2RM}BxsWpZIN%4 z(wh;cDJwlOOHjrgA$endt_vSijZ}ED=C+Q080+4i>Q6Odq=nC^X=Y{rd2s?y2zPIDZ+WsSGZEgNb)u@r-<|?m^6c0R>?G@RDvpVtnW2HcU$R4rkPE< zd_;e?EqoAn{Pijm7()F;M!}_P|3&-3Q_fQ)xwDL}Q6*ecNVL9F$X?|iw44lxc|E$#`H?2NxdLF26aA zYEW5fXn5phyX<{~-c0`Ff(`Bbil4_FbG}&mapsA;u=w+3dH$G`__f*C>OUY8wj@qm z*)Y+r4JT~N90!!&5A*+#S(*vb5r*osG>}?16+o*Nj>efq3PKZ*_@oo!)KKQTdst&x z5)$X~5j=a(juj!>QYp_gK0w*_ubf8Ztg9!uI8ifs)r0bqq-D1R zZa}Qt{}PMwg|H-fu)zgOnT84W0Kn zU!m8h)HVu?@d4WVmwN;(a(O1imIRB2vYd^Mdli!4lCWu4Z0yJuUP+Y9SBVf`7;(ko zX6ljYXGoo4gVa#A;@df;Ur!G?a^smA*ehm=mcvHqKMBRMk01J0hyQg2tWC(8Y(eV= zlb9`Qb5Q^<*|G-|gCg%>g;$dAM^0@SN8c&T1t&=C&{8Ph{Px}C4j3{tIm?E@!uVFu zYm|11u4(Ti??Zb^Zd_0JHg6bLzgx}JJ$;jN(;q-nz4_qxHTLh~t$ILS1Y$hr8P(Lf zd+X;uw5zSFBRJqi6t6y++%S>z-;DsU+>vngGEne5cK8@cugx%Xd@(&SkTDZ_HQ zk5w$>1VFqM1aiX~2zX;OZA0I$ZONFlVM-?8?CK~W{j<8DtXBZ+z7k%{>-@NBt z8F57wFuq+qJ$5`?zvpEcStfZIXE6z+ES||+x%huq5aj?z*GY4&qW|}k2SC+PSTtSW zDT(R-B%g}92W$*;q;~#c`u+DxrWcohqic(-bKn2he*lawZvpBR_&u#h|3&-te@dCI zozi`>tSa99_n!VCXZknZp8qw#Hh?$qKO((X{Qo*jY8rnK*)v}ggV0t%Us7M69>Iz{ zFx|zeWtNQ1d^kr%%P2uX@!>voR7d$Yn_pgRl3sC){K8cZGtuE4m$w&z1I49vCPa^l zo4lkGiV*Fyo|XjAwZW4w$4kXcMbC7nH@DJLtOBMqUX;^>Ue zBxCHR8DlYrte0$CNZ8GOe#)QoV_CzWLA;naCT!o=l<ol-Sw7m4--1%IUqEMl<6AUw>4G)q)xjOjllSdfYQAgU)yJ&ffC>^ z)D2SZCYtA6fZUtt?oo-P9N{ve^m}M-9iF-AR#0fv#lY{;rz7qctosAPK#(=n1j(tX zo=1~K@YUV7WIGJ$oy|22^RA!EP*9Z8x1`gO?5s$DlJ8soDUp(!yy@@!+XW9wl%17} z*|i`}39HlgFFLfzE?1tbef#P2$krs;2NHcAZG^|J?!MEM7KldIJXGoY{vUIN&WluyZ@KqfrLBZJ5-BI^+NT4IjtSI}>j(<+V+7#KTc z48vVlPHomiD>Lw0fG%6-U0CB(@k~j6QcbdztR^(K(80*noQ2|_+8Wj;Kz;52H30g; zt~&uqpZF(!PMOtukJ&V922A_J zy~+>)fSMJ!7Y3d*JkAdseXCE(;*NTDCR3KP4syA5#uef4d%P=BOkHy!PZESo|XxfviBN$Ie_m z*-SS6>?I4-1Xb(WF@gX!16Lq{baw2mLtPmPTgn%!H{V_XPQxx-aofJF302u%juQC_ zd{^nT`Z)E>*WmZ?9}#Kwzsi^pvQRcj2OOAz02@ihap1d=5Cv=`s>95A`_HZNw_|Fe zmgAR1mny5jJl!dI5c?~z6Pp~VVEFo40%*lF2Miewv^&z zP$W(`Aa0-^?ZT3~zT;lRTKKdii@^|f5imC(P3 zKo<#?du~i}_&UTey7-&`1<0ahMP-_OgWqP!-HZSL|5a#6FfGhCczxws2tdx31eE$n z=n8a?ss5tpkSjGR_OJD>9jo-y&NVJ$I5CVPkjkuouc(S!eoBzL%r5{vv31JzKF{%U zZmfi~M3j&0#$E(*S{8->y^z5ISV-G*s>f$P&`~gOdFGfq=qIVJRV^V|;HsK&7{Uo4+qSkN>uaDVx_gBHoFKx#uJVUN3A zuo#k+dS)w_3PUxckUUv`P&z2Hzwwr%VpXxB+ah{fz{SPUcjT<0&e6u6uqb>aGuvbU zYfuao+w+6f`jTVGb;3v8veEv9IN z%-6yFgO-*yETo4>FE8(TR4oWbecfK-c@$fiLY^vO06W2Hj6z(S2;J=WZc%Qp`|SXX&{0m{r@$G6ARDf}>p*3fqYsV!Y-x zMShVp?FYmDl6Yl4MMl6Atsj58z z$0a7(>rD1SS?`@C_crI2%)V=!ZkL0O91uqaC0A|vc&+%{N4#k$Z$7y7uPQX8po zJZ2iA)u1OhPD&r!dFepwu&g3~>}M|SJDfFBoF=?=@8sQpu-M}^a8S&4m73WXfwPcz z-Mt!VP@)gkG8elT|NF8@inz>5f+d0AW0c{a$2_STHEp5Z zI?8K?;G6|F^YuWIqua3)^3)^oWJ`fj>&cU^$9Q9C+DXj<|8gYsV7+ZZofY|_iFuC! z$`d1_I$y1g9SJIvSQBOSl`pn=g#5mdqFA;q$TY&S=qnt|VynAx!LCH>b$naQK~rde zGs@$mVrE=2_lfByenR80eo|t=@vn+T=+G4?BrdVXkMhcA-S>eCz0mLa=dPDLQtWqL zUKEggOSkL3xVWt=FL^@?kRIxjGv?_{0n^Xj(9LBHd$X96o(riQ?c ziQL2l?Am}Ffs0cv!A9#WNR0n!CPc!~*K=XdYns4@Fa3pRL^4u1*7_ES7Amm!A_wkR zR$qO~kKBffw2L!;v_~+QOoe9nycEL(g%%$aM7lR?@R>|nPpzjbG|IiS-?+e<4EIX; zd_Z){=6hEmSj$*2&Sk$a8ag6b#Wkf?A;EGlcKJ_>d+iJ;wQduPO!jNSMVg7zq>=sb zq^|gN$VPQ}x5E?ME0P=tV&1Ua^J!qI(ZJ*76~&v-vkas|!sqLB8b5Z=n3J1YlFsq) zJeub%82qpk^!l+l&%UxUo|{1R#uwRn)D_B*>io5E>AIAgr~AYFvc)e1Q(zw4bmt5` zxk^X(Y? z6-Nc=+Z+{On1yc~3t)9e6Lhi%cs?3k@CdBLQerAPrBoAclhW*q-Z{;%| zYR*4DoZsRyl2km~eU7qce~YWt_F*HxGKecaunx;VFdSc6ViTt*wQmCYU2x4boF@3K zy$vh{@M&c54Ds8bT`=Be{bF{#T59!seyZSLI#}weecH7_{ib5|p@0`@*Dh-N>(!!~ ziXxvOYHB=@P8(BLsN9adPBYScQ(yc3Mz?fGj`^aGa%Z(MJ!-8BI+8*BK%UB2PFa5& zORkk^Ic|{=Tg&ZXXs;R1@4SJCxZS_-;m%H6uN_yytILhjK6Y;xLbbGN1deBY1IZXh z!IMT0Y&QdRod_KYoUxcFIq@rQq@7O-RQO^;iu@r0h#NeHE%a!mNT8ygb#9koT(D(9 z1YM|u`GCTj{fxx}hcBlU4W6(2^n>H|8ZLKLuF6r$FCH67(BNW#%CVN(>6Ee2sSEpk znWzbPqIrFV-hMRRQghr|Czx1S5A7#F|Nr?iGoM*Y6&dcQlB*;P7M|lG3&88J^PIOx?FW+0|+;h3ZzPlz& zFl3oGij>hV>n{^Wps?Qtp3Qb9y}DeX-B%$eKI(8yKkNX5)=+tJ*xgSk3!DK8C&Xr} ze@omarz5mmy!mF4tgHTXAI7fVoP}?aEH{1czV>|KEZo1$2;F{;BPthu>XMe$N5YE zR(yF8>FY63sSGM4GJ@^Oi&uhqo}Ei8+zlUTujA49Q`zuef*{xbz#7;7+V1A*B+g*P zr|*cE0LyvyK+c{s|NY|G<_}M}tmrOyc+_kt7Skm?J99{rNymU-_Yd?4WPG^kJv*{} zCmi^ILLj;q_-J`xUy5)&rg7!Zi%9c5f)-rXWY?yuo#VxB8!r%~7lQAw%O5Q>^Hg3V z^FJEUvy?cQ%bq&aG;5w&cp5r)J5`_fhp?F*HSjhFTJ}oJ1wOikaG#SUm+J@Nf*G4e zvY*V`}QmR{4YB>H4c{#aN2y16G z=l+WK&&V~xJTs69}j1l6{pKbrj#;*N~f#0b{1+) zk$kMpua+s_(-ls+P9l~r%h$+rRxdbFe5NA?Db-1;Se;RN8h&w0G~KS$I#9-+Z(6@ijik z3gn!4m3@~cD*l<^3Ta<(_09?>)WSG}WR6(7W_W$l?i0!je2UEqHA2>(-Y}QQD@FyUmu~d|vHSNC7I%YZvd*qhWjQ{+fgn$` z6o)8uD%t;@Hs?MWL2fVOLY}>6*My&SG6g`$tj(3QLOY{re*wa)x-u2*(fm6ahkPN+ z%Urz|VQ0?V=1_gAr00c>R&5p|`05P2g(N?D5@Khj06H400WjDm(Qm3->(!^0BWd%e6HmNd^Y6~W+o7<*Ky@Rn z@MD7}YP-)2UiM7xR1Rkoa1N-^-9xIO**K1Rg)}?0>XsZ9s&(-i#484FFR@*9kp^~P z2h~BZjDEywL1wP|WiN`U9=3cHNUm*EJJ&2w=Y{mG>B6)_c{L8j_3CVW7Aql14)5l3 ztlgM#ee-+_aNbd|8?{^6FN%Jph#ydla!^{^7VjgFN(MO2!8QbX?ULJN% z^t-m>=C)Rg{-uMGqoid~qEXy-um}J3wXHqekqm*DLxTp80RU#dcrlQgd*Z-1MeYL5 zRmnqAV1nv{1l^Umy8w)@3mvGiS!ty6gaexn*NNScq{TX!-E=0T`JXMkuYNO&@vT`d zR5Lc6ifcNoQ2w1;bE`{fKldzV;Un~y?d_Tz<;cCg#F2#oA0H0@`aJ6r6EtVIo?bG@ z?X5OQ#Pw5i_K1KN9|U;tZ4UX`c<=X-2&8P8JuRam!lte|8uZcC!Z&=8h{rCxEER07W};aBnJjOVxUeol~dUFlsEm5DbE8XMwI0 zpFW9w-)8Xqu$%^V_^N_00O7mVS7rTCI5dQp2KZ8J+OO8sEk5+5vtIKZZO6X*0vb7C z<8oWe=FP%GLo;v=eC6cKOuYo*3(omt`*x$-h{wuyM{Rc(VYUNC7JKtz@gh25uRcxK zx^bC)oj!Q4ySAHwR}stpXfRJkj&67cF1O!`RZnCLP?CB>nmdS+7phdH;nFpX+tz-A zp5dOY9{(@@GQ&N7L`PA6>RYv$r)H>-6OH!MAl)=*fN#&g}!n8N_GM;x0iUlo_hb{tR@ zz3hdr&ddq1c;#i*jK&uoKN*jgLI|Ho@GIffrSjocvq)XiZZ9Ee5u|w-55&mbU?3oN za%jP?_gm61ek%*P+&z9ZBJOSq`e}DalOmsai?pG8z0y>Mjsg_62KnDJ=U1cMw@%zlB~pLM~E}?YL_nf7Ut}Y+Q%|-%GAyZKf#7EK$Bi!@hRLV z1`|QJnLUwd;7`qir1`4z(8x0sLrefZD^{qyBXWDYQvuB)T_dBj(^V5RIa9q=8jW4% zIbq$(zY#yBaCro&JF3tiuG^=+>ek(o5rRHBr_94+-PiMpOMpnmb+$Na9N=Ai;hx5y z0%88m!uC_$at}kmGT+~Lv#A&pGZt+IpDTE}&v?bVZWALP&J5{q^LHj0A2c^tJ{4Ui zc#v~mANb+ZWRN~I=rx&_^J>+_8Fr(t=VGR}B~%#fpkgxXr#PR(jdm7QVL zLyz@faCNbFaLbW+q9TSz<|s!N5K@%Q7$W`;wbHG>6bnH{}_3yvGR2}m$xepADLs_NuJ8_jIHhr8Ls!U+o@ z{Ztl5Q18gEJ1UXkh^pPw>Ensk-&(||qMY{wj&B3o+Y7c&!_nbF^?neZ7HnUtCX`9z zAa@baM!d~oHM`9#nADDGT5I`3=j|quvxB}X)-oab*$tKC7ws=*X42eTMV$;Eu-FWa zY#&^cv)Hvb-g8kVtl}cyYH!qe^Q#{g;R%`yP=rIv8n$-5TVxsmmiGVAP!(<BExonr10X+CQbO~v%P*&a7pcnts%(Az4U+HX zg+yz?lV4WJt#px$u(lUToos@c_h%Es7olj?W~W+*S0{2_J1p&f@qw@y$R@B;h-e)h zn((Y$+73NK5ltPntulC3?A%%KP3&4dT^Z-^?S;7y2|;B3kQvyY?YV6|x!qolpAJ)1 zvU0Ec%g=#5-H4Fkks~xZdbI;W)yf+HGMvnOydcKm|r-@;FZ0_ep zkqdI>ik<14f`^_mH`0o??Y`DJp6#bJn|*Y?K%K8_QX&eZ5({6%xg2inUS8GLcVI3K zr=o+zrGNPyTfaHwPmo(ZFg$s8ZLvZg~c~ zUPl8P_atcgfR80VdcSI6)Kl5)M;8S zCaWZljunMfQKj_{E_@j$+a1=9BLaK8hKiVH55$CKK{H01r+(26{?`MTtOK7uJg!x1 zR_JV$5H8kp8aRKZGWz2giUS}Ad9XD6S&`?%cB70}l)*uPUnK6*%J%EZyR(?jXE`S0 z1&6p^!tu5Ij34gl=w-y?iTnyf4rlq$a;BX{y}`|aXf@+5`Eviopy)O0d$X9XdrFs7 zg51SJ;0)mporqg+n-)H>HZi21uvFhCB_1h!F$JL^zQSHS zwwB5}xro|XuMQ%Z?}mGG6WL@c5L^vf2@FJELSaJK)1Fq`^`VK1AvDCQn#&T&>wC#A zC`TajImk;=*IL3Q{GR#+AMeLm}U3-p^6}~ zKCk9s<=;%M1v2TlNKJ<#Yd~i<1kvA21oQg1#p#&_+p^Vot|dfmd)}{(@Ij6%)NOuK zZASVE{uR2i55Q{2erDIOMwqfecX0h??EquEOw)5EAT>n^q^8#BjRJmreorUn5zm8t zuc0ucgrMsuhPbZro)qXY?%bQDMzf9jfs%jUb3r~_9s1dorO=Ne$S4juuR4!yk!602 zW~LQr-Tn&Fj)zBYOR67QB5t9I(Ua?Uv?HbmUu1K2$!7*Cwe(<(@!pOf4HhNn+p0JP z4cwjT#*s(DVhu-JaH!d6Y6uJzw_ShU{-s)*<-ku?&4yfo9<`fm*V10}d-?&1@QD4C zQ81r#+}Go3s*33C;BMeEcoL5KT@2sCR-ZqEc;paJGNnR3 zh#W-Ut8?H>r7W{;#;$F-q7?wu92h#Xnf`O^z^shaJgD@28AkTfi_Bn`q<^79JYhde zS;u&D7TcS^bEm)HeGu2$O$|I@?L8Quv1WaIXUcOx4#Ij+Q0M+|HZ4Gf!E{70#Rlof z=Kk?Qw z`3ffB%R3;hcD=U+km=cd5)tKO8cD+=SSMEy&Vcy9iK_9Qfy#_4?bZ4pkA*zVJX3f7 z0TwSJC-y%28gq3&b^H{A@M#&G%<0s4IA{@WM2Ct=<(q zxIjB7ik)I|LpiFdT)kBETBL&08gf3U!+>Y40IcQ$!%sha2K?6zCKk13 z@|GW0gvO)1&bc5x5tf%u<;B406dO)Yh7K+ZJ~?w1$lyHqV5oWMm94Gh?TBCROqfA^ zT`4soK?uIcqy}r$Yms%iU&prqk%-rTskBB9*!}IE^WrbN=F?qUH1`Y-u^aU6`BE=< z#oTGc{^12&!=V@;(fjw|XK2vjqLqIYax?0Z;4B#B;^ulxC=XaU$_Ru#zYwruW556m zVkHScPkl09mTsTwZXcxBCl7mrC1t~WNk{kNG>tvEy$UD4PLlu3cLHZ~u?nQ4w1wY% z9oFU}{K#_`;`0x0{(awf;C;6w^iN0o&n*1&=GQ!m%}zX;a{vC@X%iM;yTxXq%k)1Q z0}l)U{TK`m2mH@o-oO7(_y1AOKQ{Cq%K_HRf0os$kNb~P_>WWgk5l;XQ28IH@c%ET za5-yvnK_0wkrbaQ?v_H1c+Bwv@42G-86V_x&m9KBACv_RLmn9q(GR@^pY<`kj z8}+(NsQ=!o13o}*NY+mk2Qy$>ueuDk%STGxju`)ZC(JTx8>E*Ge)YW9v?k6UH+3WC z_o3UvB&p;F0EF1^*<-wL9%F2jk$yTDPOQ+fH7|JmC*&|BnH zbh4SDJY>t?)n853af1pqWCK5b49RF*RlgOHL#Dd@MSt#YqdW~EkDiQu!(KYWeURd4 z4Ef?kBDFJPTXp;)gYIyV9xU!bL=Fz07>HIRjaS-tj_onW&V!eo;=pj3*wm!@uOMRy$IjeIrb~Rt}+VM zTz`We({n7t_82w%casyM1FI|vZzULU;*rws$3SAo34oSkh0#PPcjs{5lCON$BWn-8 zojYliQ4k$~PufDDRp*^t%>8tY+Yxi?iH((ck%Y`fmhzb|$lPO=zj_He<1!p%QQy5X zPs%g>V5NR%mVVM*|Hxb9EIj6ydLoQkz7v+q^R1DZ5r#`T7D{-`-ZseCws|um)ZtLm zI4jkJ-iVIG~(B2{f=(2Em z?wG^n8VI&uDgK~CMbj6q*mks{ybda4}w)sVHIwbQQd4CZGn42&EmS_8Ql~UX2?OeHxSunIYucL2; z^QxKxrF{Qr7C2JkGQ6bE7HFeQJ7U<6#UoZ)#0A( zxV9vs71+0+A#LbX$_Ah}vMUTe$FiZw3(>QK9oM*9`8;8> z4N1bFE^fm12C!y`q}6Uo;0^nFlbaP^GHZBZ-j>jiSKXEqV<3p{Go@55g%!f=bGeOM z1y@u|JGEf7tpodn*Vm0+-%x?2eJW-!E0Z?lR2Ge2@a@W@)qH z)L?x8gGl+8K^V2_Oj2NsC4UN>EDM_ob-Q17?wBC7~D?Gy+aXhH&QeD0-73#N%tagl|L6Z-wYUvo74{b3*- zxl>3cQm%P?5BNR}SvkB_q4R`v(r7SK4cL7Z_dJ-+5cIjMFFKHxZ(G%U{lP2Q6RecV{|n7xu`EOPOR3UMX(xAB-hdt2jlF=RtBtyRRV zKGbW@hGl1dG)Bsmp+W0*zdpO>Aa6I8PH2`4#F1>u?YYH+;zJ`(Ru6sV7hLs$V91QY zt%&iMjSkn(nb3XRjiL?y2n(?4lPH zKs_hr<9qLHgX>~Jwz!9;k|Jb-0g8hdf0D9OFXQUI6>&VEU0Pj+kP3yMObNf8WJ1gv zJejbq10r)BMLaGG+}>$VzagZOvosTCI82(!N0{6M21U&|#UzKbunfBY_dQ{Y57ux% zBuN+@7C(O$S30xoAl?M#bs0{uYXF8dx0xbeS%?74?(E;iF1xwG515@NV0J*<`p4{m zLHiXsRXFz3kS|}D?kRf@bM7DY^(_5WHQw%8cXcJBul|*lq{{jr@Fr{pFs7KE7$*yl$>qtclmE0mkBS-xeVvM=(dzITy2nnbUIYTBl{np(7 zua8D-pr|GVL55hTbF{COUJN5{-UPi^=p!QXFci1v^ldYKDlbwnU%8rHO`UZmChGCU zdy0=A`(kNsp`udv1NW!3U3*n~Rkaj4?#%sVPX*5-5oA-VZGv$?5zac`Xb%~_@Y{`PG4P1Wtc|81yK^Yy{)DA(SrC(o2W zjV)a%`TaxiokTE8dLZ?yg~?{CpI(jjbRYh{y(j-iP5R#-P5AdE1kaudkSZaR5UGB1 zF%`I!Im(I}QT+RM!*i^4sUP1f_X@t#y2=nXst7d5W%s+BJ^ESbRHX8&CC(X9f1h8! z@Pj`5=HCH?-&IO2;eK8E!T5K@+xMIQ4}0$w)>PNE3qL9r6a+yw+NJ#d|%KN?h+W$V>C;!27n(JcC zQSNb%dyci3bDy5N)*>m|vhm}+4jCO8@6JTW5*O;K&SFY|ohM>kgzyHEt2sA6t{2Bp zJy`#)FP|L!qUD6^GtbryV__E1#P_dXx!UppE9gfCwR$)JhnxaY8};wwWco>svs_BZ zaA-XB&kIChM?Wir4#?a%iztc*4II`8n-V++#P>#<;&+jngIcOr-myrdza`W}6mDQ0 zIc_X*G)@oY3KSkW63z(N{PWqA#7FS2@3L@dGoJcN4L|q!dzNmus0l4DD-$sX{owr5 z%%M$9UGqDImgmBEpPxy(v6!WG$BY{Kq|aH)PE^PD&O1SAKjrQ_XiR|iUrhOakU+Ki zyJ64+cQfaii+5QcsS7EUQ;jnGrS*FS%o%+wK{to`2Qu>#-0Z5L$5&3C4GjTo@}#5a z-q=VFr@KX67ivBI?K9Q9QjMO5F3<9f+M0S?qh4yi`A+yv2J8+*qp&mSl!jz(CJ!n5LMG}{@Q zLgZvXJSTW2MKSV%$*zB9bE%t?8s_&WUPs#UfXj;?Z+p}a`i?9U%gn4fWlW76=C2ZJ zfrj^Ld*fUYTD@X&D{F{gJZoh7DZb$IWfV^%3X%Xgs&0%xgLd4sLGK;T2A^G|E#P^) zy<-vZ&#$96iOo<+?gup=A%B|+vOxy~=$-BY)f747=I!zqdYoqdh1c)sm1xEM_8;^G zW)N%^_gBgWUQ?r2!Q%Qr8$`r|8xA%(AlN!SwyZeNjL!}WvzcQB*CALhyR*}b&;A}Q zBJ4zs9@KKG#TZO%_*(6GeX8j`-#>=&tAVCp_DT`GqC~^RF$UFOn&~IQue}rn$>-&h zGFfF1tCI6{Uv#Kgr8_OZ%M4=m`_lK7P0%v5OcoXfV&(~Eidt6s-8yD}L8_|Q&>ZTe zx~x;a%KC1c%1#Nok4!J;{?|8T>81Rgfhr3p^siNL22Z$ z#zPcovHq`XV61(L<2swc-)tH7ltAweP(4I<>&o!} z0lCpO6}g%}r9pjUzM{u1Lv=8kdG9Zq4Y7i}yo#X@XXFKm&H2*ZiS~0~vc8N5I$xqO zE2B`8Jr-nEiK|``tTbl5A#M2XA?SN%>}Ad&6);^UY}^OJv@-5gX?hH&5tD^c{m^6) zHJ-!WVdOR%7&i4boF>6aLt$4lk)ELUTAs{ax7lb52&oy~6$DFVvhD}_*h}i)-#yRm zs-Oirpl)1BPbCRtsS_*i=2g)A{HsqiFR@U~*HWVUT=)Xy<-OC7vSS56gvCB*^%$cD z2jn6xDq0NVZfWZ%fyT>dY2Lb$3i4vBpi&f?26RQO2rmZ{YV_7vwnbVk!NgL@h)NPD zjabcF_i2es+YTJPM8n0Ur_wAmN>?yupbrFD0wf-gL-MW(&H&ersBQ@A&U_EGr#2K# z1s$y@u&*Zd+<{X-%w(J5sUS;mM2xXif?#}Omy5`vx}0l}syhLq<@Mu%4qdQkQGJsI z(ei*_@jQs$vohVGt+Z^mzHCar1`-qG$?3pl9zU3$S}rlX%Dpx;T1q(mEWwZ!Y{M1o9!Gn?@;dt69{v_&MKfrbCyi)5U;oZMM*}+D zd9OPsL7=B*J~uAsq|wTHT0&tw=%H)K*f~G2I=!FR?b3*LH`=QB5g1Jqo31~(DIljA z!E}tBFVSpo`Z22=2_|cCV$rIJ*2LV5FF*8bqh>hsNP1=hxcs7KWAS4N(0A^FuH_sN zTDocoeQq>THW6Wu%MGVtrDnANivZ*4s=WhA0iPck6%4}&fGq`X#C@1V^FHxa+N)~X z0_OKiN@QrIviN4G?<|P5bi#9t1L%PIuS6}dP?DfYzDBejYxe5}_Wu$>Gv2}Rt41dX zvG~tEcP@g7rIOJnY9of`T3gbyfQdViywuss3|4vTKTXkBX{I+?s?C5b0TNF?HHc=6 zGDnv50h~i#9@SA$riusKRX<0663BjDk>81cGSQDz7^K+d&by%n2;E552?(BY*2t zyJuylY#tsY+Po-^a08HZx^G&w8t&3K?ZE$+WfQFfUI}6J@t`GZ=`QybDro|0v#H~D zq8v4jml;oSb}NI++ntV#&7k>iZ}U(Uehy66a7!qnlUBwa{Xd>SX;>LCaD(H)4hr|o zplpKA_Y6EwGL-@=t*G{3dHM_JJ(`1#vr7eBVCnS7*lvI}0lgP%|Bn zl(krfoxwtxUK?w!Jxw!T=+p()5b*J6<|A1`)RqI#MDT#aH+m|Eg@su)85NT%5QRNk=oC>7vq67>IL_ct9{x1zsu@=k(`&SFf2;Ws`odK6(xWW|pVs zBnrgL_u+af$g&bsE1F%XV04*H$W5hcmQ=?f!Sj_=aW06_&A-HUX}LT& z)$e&3j5aLmfpOLljTH+*zP#853;*6tQ%*~e6%E3-|(_{MJ~0wo+Ay7uwK0K z5bS`Xx1FnEc)?`JRPO(|4OjW0ARL%y>%SSq!C&m_x^f%&+uIN_fN!r|i&Tbg>Y9TAu^_|LxXe$MCHe4zOur*1=! z(0J{_Cv71u5Me^I0`q0m;DB6|NOiv8mdTft5YTwf#Lvce6=~W^Cxk1Tx`_bxWQpu6 z10^8D_!pt?TfoFp$><>pd8m)}q7l+a`{3Js;?-p2{>p4BEG@@PQZL^G} zMYH2`v4H}O(;8BK0H6egPsp>TWDYP{UDe%fAvB>m^+W9aVk9+=505=i6{po%La^00 zd(d}?X+pmql$I{|X8JUZluOMeZW*xAumT@4n>+;LIr(K7DGxrMgBv*Nj@H02g^CAK zf}r;jC-0y1q%BY#Y;EI7E0yjudFh-W)|579htZ$|F|Q?QJ2I)-yPJhaY384P(DM2k z_;?BB7b~Y}>ZK^n%hcf)*m&usu4RMir*hFCxFfS^|GOhWGalXCT(U{qaR!R*NHfxm zM-QsS$AMcEkvllcTVP_TWOReth-;s;H?z<-C=9Z_@e#D~PsEWB-upDuU$uPrNt0t# z;>n-}5fpgYRGc3@p5p%&jQimB;0^)o@hcqqcu^2Dxo~i6{e3Z8*d5e^X1-agc2v!h zZMsX};sPq%>-+@_L;v*+M2p~)ze*r_7eAl_?P=L`=8)!Kr%im6zWodpp(z&c=%9E@ zaG(LY2GUZkaiY^U7{7slVfWs6b&3)5U)R(@so7#G!V3Nt7xuu=@3>XgeZ z^#_Tz^x$`~F+Uj1d@);R107I3DM;Y3BJps1t)V%>TaJiCJ#<$oQHHK7ZJrKHU=!2rh(?m+} zfSU$}Hr2)=IIV%#+17r!1c);N{DDXhRdGBR5R|Y6JcjYA&5MYm&Z5uq)00pPxBuJ(I zj#U30ss1}s{dc5FZC3w|RKZ^S?@0BR?Y|?{|M!uqj_C$ue?F$*mhl%6oqICClrku3 zP;Wo546eSKQ;^^kH*E+X%)cI9{|sf)l@*RM9+HC(wm9C143oWS+a$U`Z#<;u$FvF+ zlW9a!J}w+PQsvhf=f8rkl{vEThm+&_|GfSEp~P9vtD}V<$c;?os@#q`%;Jr1%`>Ri zS9KVS3jZkU0esXE`oe&-drrR#9>Yosk1x1%>Sx3isTON3m?X1qWb%v=HqUWT&wy|I zS*Wa|YDyyZn*pb!g6k6SL5wO-gi)SGD_Yxl%0)lfKNriaomT{i9gn57ivrF*pV|Nsm})$bHCZpi;u=os;Q3 z|9!>6bVv_9=S?o2_Tn4xEzk8?y&iGkuJ>3qlCEf*`A2T1U*NlHSC3%i`oSBa28}q# z#s7D^rtAEku}IP12fl*A2pmBMMR4#z{hGCwyKm*KI*5*1}V&e z8?&n89|QxxynNw-p+k9Cz%wIr1;#W32KB_Z2ksW-V{(M$|F~7~>u>KnKyicpf%^`f zV}p8TVnfc50!+?mKV$*=F&L&Khs7{1`B*+b3=tgrAQT9E!QipFm1i!rWFWPg&%TD(JFv{UK-hn=_!N-Vm!nIk-dsVyr{}J{YGdIo^8-KInW@$1nctjM1`?p>Wr5 zkvK$0ao_sN)|)8)Q`h6kqw))506+|_F_jveL#eMse3?rl$9{z$+M0<;)~DW~hE5UU zV)9DXQ6npH-L6a4@ov~H4Z{t$RjnEC>5p&nNO{9gAoH~=?YLZI$HL4iLbR=;+#oYD z|M#$4ylgJyBy{7dEnp)XXrn*GY8bFF2(a!-9tUWn{x1sr@*5+qnn=HBOoe}Cs6bv84yCblmz z<9lAD<7uB&SK!;yi2Qz`K?C54nVpu7OF5a}ql+KBxCe!wfBx+bj9-`#`z9jkE4o+!m3T@MeLHB=9@S#WtnYmbmo_vmBsAv^WkMKkilr-=_mOkP*s=NE<~wt0z1xb za#x!(qF2WZ@eTNv?7J<|#D`NdR(mTL7G_d8yZLfvWat^aYBFa=`KuQm3*kWvx-t=y zIhlW&^VXwebK~rChZ7$IPwS;V?KE-p6F>sL0O(Zy2RccQRkgmpo@jp>}THwB786pZ3CNRlCd#OH{yt+4;3 z8NHh0PzKyG^KgrDi;qjPDHD4xQ!@O8$KT$D@8(0odz{x+e@EMsh2VoEj`GGPff2nc zgm%@vB$xI<{cY||N~OZSV{W$Alv@eJ(Q)Yg!O*-c`));p8#75}kNx7}G+OlB_x9;w zH(#DgK5h(8n)!7>?Rg;6`q;#QoXjlij6Y1PIiDF(p9K3tWN&h7)oYYY=f@)xrp9%F z>?CLo*D}DLh*Ao7rb1*LPdm{eud*ioBOrP`c>`AO9pv^Hg2gdC6+e80Uw9j&XYr{t z3-~n0;j*9O3B+oSpPxgLs>=j-`J2tJhgpBne_8CUfSPu9`l{(RsCW6%E%C5>S1|UE zHSYjtzq08LGoMqK-fiI5VZ4AZ62KgOT!^xXDzF$q<<=GZa95w!#q=%mUJbFlktM4k z+G?4+RMguM;W2291!{ZuHfC(_95K_xsSQ@-1fOpkp2x3AVcNAv0N%}r%)NS#)8M|l z{}t#sx0X)Ym?Sfa)z@{bj^C`RJfU=RsA-l(hoowzzL;T)>ZSO2>6o`3XBe^zE!hYmn-#Eo62glX*aC*HhhHN;^X=6ai4QmkC%lZCeWj_#FI6i((YjKmdSunMvZz(-XBN zb>4?_qwiv!O1=ph?s1>-LAni8iEuREy>_B_Fmtcj@O_JESM6{P?>Lg33V(q$AxpxC zN1Ww0lnw;iyH@+#)OX(1oOeN7aAi&dJ=HtTR|!_SSxo<*BfEifgsp+&!GHf;Is1Pd zDb5U>0S-A~bMSwk8?G$yVkU~=3-R)?1r_D`*!q>GtXN?awwq6R4*3V&yizRIx%%7EK+67a)p0xQ)dLs8;U2*MhK&}jp z+89~HPx=!lM+a;=OBti0$j6ecW2Ub$^K8_6iu5Rw+C`bjhJ~iArtfhqSAQUy=0^GB zp)s7^JKskYiQLiaWo<`BEvBV!$q|0Xl!jk~#uk{=7G69(qIjUYH`S^A+roFNa8x{M zEK8J+PheuYG;&lVU|dDjT6H1-T9M^rQ|vsxk`;d9uC-J9!H|uSjm)WgSMNQA>P$dz z1kTWkyhB`_qqTZP{W-qCJHTZaNQN(;kRR2yn4SVB;&YbrYj7uAZg=sS5VzL(8-C(t zF1`F_bL(2JlUvu>6;5-cYtm$>V^5JCp6oduC@i?%C`QURXx?EJcC0a=bzRdhGkZEV@-(5Z#nZj$OPyWg2GdY6t8Kd{X=dwP@PWF4|-7+M#6S^sic<$g$ zOvc+9S$HaW@9oFis&e5cXRg1PY#?)PAKP61u-y0QpWx~9ZkZ7ny4ewwAEA%J3T>Ho zz#l8gjD%z&SvLEoHprs5t%!7+veW_fRyaoLb93cVLHNT$mPcKv**csxaTi+)*-n=` zU=0q!rH_{uP59p5^8wE2Mfv{HJ{CRunnIDKd|2C@QlO|X_UkE!;I7@4d#Po1*G~3X zwu`=}^K15Ti?^qzF927outlqrh&+uHTY#MER{`ZBdwMn@4(m*&iZBx`rxanG|YiPHrGcX-^tr5^a* z@BW1P!+ON(nc5w)sv`6I!!e9oJ9)cQjzJhXh8H;{BG((A_`a9k8-I`}j*1rcw-T>(Jp^u*{ML4%=GF3bV`XB2Fyx1ovPm#61mDW6M1x)*D|Mss0VYIZHEz_i}>M^PW8 z<=EL94J=swzC$9G@1;e2k#85puMj_Oj-2|SiyZR7pH&=idMrqRPmU^iBT!Ngt`0JD zUb`81@<_l@=YYNUwS&ii@83uBZ^zZmKz8466O}F;zB;e4n(v%sw1IiCyf_sb9Uc%R zC%ZkNaS&w`(>;{e3E4L4Z5`HiJA@*Jc9l+=Ps`!|HoCc9?yiy7L1$KfDJaJb$KU;y zusG@OpKP1a+`=S`na)J?9FMnQvk0`wB97-(sd|m_3YA=OYshrl{&Gg7yRaI&*ub1( zXdV74T$r+4vRfZuQdGNHL7oq=`?7tAh*aw1GT(Z>SKNz}_?;R88~}b+e&_Ye!-9%& z-lW~?)lv^M!&GF9MYi9k_^tIKqHlW})9PMGXn^0achIn3{ElaVJf_xRtcn9t>^`Rt z_iB$l3`iq}cC!vivS=NXoj=+JZ6MrEEp9 z4yuJ}a5ad^&10R2K^)$_OeJ|n^3v#b)@eZn9jLdB+Xz>T6}I+Tt;0fzCf=Fo(zFzDQoub(%fFx_-hF>y{^L9R6(95H^`SiR z$>EZ^_-Xg`uqpdXL)j^6>3YH^r{Hk!XKs9*^6ztVyW3KXA-^H`ji^o@;1goto;Hn} z#R~wFi>EpLDn(KTf0brIw!ck^L1(X{w@yB^;p)sj=HH!yA~u9FaB}RQd{l!wNSc<( zLUQl%LA*yXX%FNYwD1<2J?M%t*V&srQfK9B%5KoJFTJwhUe>xR^<8*%(vAF$bC1ik zxAI!Q|G>(UHhk;eQQg0GBSmbU=-AxSUf8FVQM65>#{%hqR1vUa)K4EVr>*Fz*6ftf z>v~w8rj88GFIx9}E}FF((o}O+%5~yX5Io9_DNtdh%yUwQ6_z(su{L`l;USx}AvZ30 z#&~nNBP_^mIV=E$^@4167|f-H2jLExY-`sKlheuOC@h>f_1Y@8Q%v}iRYA7kReM57 z=?cp6sLDQ8%6*W7Q3bOc#vto1_5H$rCM)Br(e_6|Lls^Q=l7ICH^@gk2)ft^Q%U}` zS)y?*(YY3-`t;*2$yQlS%}` zP(jO^N?$si$8A1qOvt$xj!5ld+fuWGit*QPPfs-{Y<_lA38r)`gqK33F-b}oVughd z_9g4m`QLc>(7TpVr+`X9(oXR>+gQ-S8?>ExO!!j!>2ajrW zYnb+@GI#I^Ej?o!q}^iOP(2Jeg?hu#?53qG@LvjsGf_V|03?x}4!wX^ET*)89* znLZZDaOHQ9TmdkDx8O9dd4&@zVt=QgO@agev2^NSw(W~yVhnKINaM=atUPO3b-j?< zxKZ1-phr;p9_}0=SPforP)BWp2)}VoUc1Zj>+6(;=W1>b6nEW8H|*@BCjITQ{tQaU zD)Sg3(*t(lS8=3|%Y*7K)C(TDvh5WH*OGT@bi!QLKeM8w%6h8Wv{seFA7TkH7Y+{J zOyP!-A|^J4ETemiflGN4uY{6LkCK1w1?+C^57H~s-=It__iY_$3tkn38Zho>#`vX@ zijoBnzAB!@Og2b3NHmrOqdH`7bSRDDB#&Arxqh+_H7mmFBiYh-ccLSseQ%g@xjmfvATlP_I-+JJJ$Q30n zXFL>f4mzyn-9AkKPVe3IdZ`|Do`GIXq5LWYd4H-xkus)UYs&^P$7Z}J%-84(U7JS* z99Ey)Jxnp&5HeJ7xaL;0T)OD@*;~1}Sy`d}MXYFg;L2*C-g_)DKBXjJ@!|7j<+dtT zJ=bJAu5vAJg2IRv!)Wf^b0pUO(x0DzJnA3SuyKbOucR3n5r({u^HS<&#f&i7=SVD; zJMR9ySC$$x9CR$a@WqULLvaqHsbTS@U;&xIeG?8?n27Dq#AR z=eKdxfTQ~xSd%IL%%OC%vQd4M;%q=d;UjL}KlHptYVe;3%3uCB#Vc2XmK4|uUFC?D zUxgY2_AZ4!WVLS&4H=Je+CK)T_pqC;?*Q(i5I|9-o_6IIZN&?c5t`R)#PaLp5B}tm zZ@b!QuF1Vg?4L~{(zQ!wS>FL)W@IHTnQ_(tVSnah*EV4{z^<$Y}zcxe3 z!q>>k6fSt?%P=b*jK1kVEr)QSkiAK%sh3j<%q#HgF5@-7cDr9)d>Fh;Eby7AMGgpj z(ubyV3*Or%FFWQs4z=(nvA1M=mi%~M$NxF1dIY!=%+>t2K6JJ+C#JY3VqcH=p=j-( zJK7gA+F83--VutxyQRBpN;qWIvR_{PB`MiY@JMA_dvSYOCqPdGG) z(pirFG!~-mo96r1qH|1n!^kA|4{+2Y1kTK-%SR~xp`1*yzsAYnC_PtoH)4h|>=Vf; zdvzcdLZ4jsVI=kj%rxV5_y@&w+pB>wN;;!Vb5vpLX}zRA@s)@~`q2 z#xm`$ME&k-Z^|pIcejV}z(~>3*{OcdaPwUo1q?Nl_kT^`VZ55}5^+(hF5^XtaQM)= z(bjIR-ifwUkKqqNyOP*D5omKN$TI#21{JXeE2>Tk6z2%4ZEuIzm%U$v6O>(_ymrjY zF~PPSez}|8`tH&^YJ{vTzAv{ZTP?93c+M{gTZ(1$`TMYlMe&ZQ#YU~rC`(5Tw=5F3 z@27$5uo$>vh$S8f+HvbH=VBrF_}F`Lew)IhO;f-fs{H=Wc8G6yP(lnk#<_MHx2k2lbmjt-Ke8W? zi;ByR4DOHI%b9T>TsR%&cqf+2)I!i-V%AJAriy}!PnIr= z#J()bFd?#Z#0&7>a!jn!F#_OUV*8F(&FTWL-ivZW3_D4yLw*1i)l^T9Jeyh z(WMLZ%T}jd8|#U)2&Y2@ZnYHK_A*I2xgyNB@NwffuBvp7>KK*-m&favjvCi~cet*% zM~5h0yFtcw93SGxR$g}r&2c)$lstSsf+Jy2n~eSOV&K#p-A-cWVMmpjY2X!qQck!@ zQKHecK_Gb;S^9m$9Vj_2vIL$cc$uK-C3bx}A3wMMWf*F;PdMzAmH9TFA84C zpJHeH8&z`2=Ykw=ysCG&VSam;+^NH{q)m~UjGQGb8&oF^Zk2yO$G>k2O*%!EcUSDy z0LFTvjgf^A^$j6sMs9rQ6^*ACCh-;zH#$?0x?hD*Hc8s|)a+|^Q)~Vz$aC~o4tX~g zsdtm|qH31>rm{>r59uc)j+l?eu^q7~s&FI(jb;U)pa`YP56h1-Aw^A>?buRVM%tNR zd{L|ioQF2rZE4Y(!hC=sE8C&Hfe~7lbiYQCZPo$<)habUd(e1 zTa?QEphys+>9`-wRKw3VxJ6!`S05E9UUbwhQW50oI7Pk$e|)!)MBn6q%rjO<%J4{gco!7E|p=~h5i;Erjgn9CBIS<4k-F?^x9g(k7(v7pmZp(fTqsQvQ7`d z>#d9tqE@}IMQA*S_|x>fRTW{;t9X=n-~&-qgZ2YL{soPO74H+s1Z1t{R+x^RlBF2Z z>4Dk?M)?(_ai*=13z^gTE1C<>Z!ut32a}|kc4~>IvB$-wtR0>(spc{ zLeBNcCibIp4J!aCXK=195*SnX@cDA`=sw(VI^KO0%iU%FOKuXE;ATUI3b8(@=-}8P z9&&gQehooK`%BBism1blOK^O^g~7-|Ja7hjKA<08<1?}Z=`Kx|JpTuV@A7PFD&9W1 z8WUnbY&h`bnP2kk^N^bM9{Io&Y?!2C(&D;&%IBOx%t3~URa~4_21GRrKM6Sec z1!OECt@hng?Wx^;DK-w-K~=Sl&MaITp1VQH`X(XSb{Ri1{h8cV%$@QC#S<`%_|(Z8QW|>|5jp2FpLwi^fo5s zY+aN*V&|6U<;EhrV&cgSw8io0-#a7RQtgIpbSN(IrM5hL4SRu*>%LuL{Ehb{gJCiJ z5YhWkXfd6=uLNi}0;iI)s!b-t3q^>*k9rw;b>!o4n29rNAp+D=n77KE3k+}U-d%xs z>l~d5A5mh?S1=DuRfhT zp2X10b^}&bNVp*oHjPEli)3RvloRjJ!&_V^=zjGImzt-+hOqBT{xrG zy;m4U>5$M`UMeMf&v?Hk1#Q{r2vm``1sNU$Ly)_&koy^>20OWC|Cn=dSFe_3v^)yp zZeoMLP-6id_Y>mSNH$z5pCOkYznMv;V&0~tQw+^~Z$n2(DBT9wt@w9+LNZmJjoh}Z ze?K!~)l53(q#)~(xY%1GBBx@MU{iV~7>2jR=vgX?<1Li7C9N8iL$Jj|B>+<^Zc=B{ zqY}tMxBAr=@`I#fyS;9;s`k+{J~g?kYrs_&X#tj#Vl_C#WAyE(l_cp#+%&8(`_#M{ zgKMD<;~bMh$>U6gj`=^Mn=r}r&wmH%*lX;dcyFhRfeVThI)=8q{29?Ct8T#=XG}R@ zoC_ye*5){}zd1mWl@f#~e9@<#3SiwfnLrMma#CyPbsYJGIy$Y_OFNN*&i)@agxEzctps7}zEF|&;|NXS3avk(mrTuFvdcA z&x^fFe0LOd!e_&QYFgCrgb>{0fJYnm!?NGc6x9Hs-+sc22?1ucN>2!dQW6Am`mtXb zuN*=ju`2H4KVdpjAYCPZm(Nvwm~$^LXS*b(PZkszL0fJ*LYYbLw0Lx4M%7>J7cWg? zZk$N`hMeGg8-Vp$HooGQG^dE$+r`oK_j;s>DAkB9uI4T079(Sg@!i^viIATyx3xEj zz0ORWWoHNq~T z3~B1M_PdLWs8hjVSV%>3KC{LCsN1#zlnf3B-v(}dwGGOG-}Gfu;Avxc|B_$w!Xcts z=Sha;VKb@O>?Tsm|1@%E{PNL1gSduPXuO-Sje`F_|@9+y9=H5JtA>7*&Rw z8quM`bp(z0d=JCcN#+Ec`Bg_X5v3K`>2Z&xQLq7n=<8k`hUG0L-gzJ1sr=_86FUBRn~A)$DSZE->rzt^3Eq8gif zU6S|HARYHR%M3Pj0VbYteO`t;+ z-X*fOugv_JRE0gUWJ?V^TOfz=A>Z~0tL|IdEFBXu?R~rXK-uSV6=_$1WBU?2}TY&f?QIKC7%7JjsS$i`^soo)^?onsHDQ3g7$wVr@QmG zxJ+!h`qT4pJuvz&fyAzIyR(Q9kJPHg_m7D;6^{0f7GO?OUeB@;#h0E&L~q+cMvjz( z_$-B9a|-?uSj&eumgZE}LGNhV?=F#BCyTh0HZZG^+bX==9d{{ro|_^q8gU1^IQRHT zdDuepe%^>fXjm4Qb9|}p?ww-7=Bkqxyr=_Qz#g%-%AG+w|bLN$vdVAdlli4 zm-3C`XL=#=WMC|%fcCK&Yp-r2husH8%3BZGREvnmxAe16H{-%)HDc&ca2FmzUd|(D z0x+>uWSn9;)x}GImp|`y7CMk}4vAanbly5k@8-EkCbKM=!1AVs}@QdPJSnYO65J`wDvRTRY37 zzsp6Eth-*t0{5X&nd{|7?o92D)^BD?6ILRz`rZA^V<`{zcAi{x(Mily886kA-4_Oh zf!gU{m>(f;n~96%WnwoXZg1wmAc4zZ>C7W7-8i?nV3^=7b4m>~T@&q0@V8DfD-vlG zg&npX>qtdO)scoTJ`av+#1ZN#dv2VifxE{;NYuWgw9z0F$^l$?YAEL^J zk5r|n%H60Lqc;Dp7+a+G(Q6cT7LsW%cSQkQLM%-act2^}^r%g8G89Af`s*+RDfOki z3RUH>&nQzDh76i3hR{(=mY^Rwy$E54C?)^WozOzrMdHVq4V@f9M!zto_eVj)_Q`G6 zYEqtUQ zofI&#n?XquCqp5YO2sR=$b>~5@9!~o>D7k7?i&yWtIVWCC+i8dQn9*h=wjT|j{sy& z9o<|dw#wtCxa@umD%4z%S{bq_B)PZUfDDtHmnrE!doeZ{ZS6_5OZ^e&%MlJXjRi_V$z@G>lH2}&vFlti-v2+l#n1#-t(jd zzPIq+YUBldvIEz#x4 z#K%TqA+E9EwsMj%5TkWKjtA+m(?_#yvftlnW}Q_p-s%hq*$FSUNv`5pgftu`QprPGe{Slo_kLe_2o## za`dKPH@*(u|J1M2A~_f)(>{Ii8Va${oGd=MUC4Szbuu8RqO*ItcjuBy%QB+3_lPdv z@7?-vgQAWhl}_wt=d<}krFt`ng?|V3)ou!s6q&H-^tsZ6IKbEFMxB)SeMYP%qO1z^(4a;m*;m*>9#f?1o)w0e`|B66gKMHN9{LT(dy^rkA$Ro7` zrCw8Q;Hy!%yu^M4Lbu)t(6tyyzq!?dbV3P8zd7U-)b>zd$ zh=C;1Ls{5oqTS9mZ{(KwK0HV*klT-RTVKIdtI1z!y>II65fnvdFQgeW^&BSsHnq?q z*$>OFq|{tKb$KZeVqHO*q~`w4{#q1A^~_%(QmX1yctLYph7jU|!`6=s*8A+OqR)gv zawUcH*gt2PJjXLhyq`^Wlj07@Rp^G8h*1aM1dd$jKOs)F4f_vhJ;uCEM{+ z3T4{SGe#DQeYGx4mBhM~7nCvKcx$0LnPWRhrAq6yiOymO2NbjJtM9A*CF4sJacUr5 zfF6Mv^V-cPogdneAD^n?*fNu%ze=c07^%+8eYBzRm53j%eU;`O3_EJ@t5q0d0WVi( zwO?^pO`Y_AW?Vvq7O_upu_#}=T9Z8vlcFF7V%I-(lYI8`Rtuw|@P!R4xlu?M@OhPi z6SNWDxgyC&80vi!Z!Y8YM!R#B?$w_a<#252(A@Brpz@9h>(2|43(oQN7ZIvne*S+Xcx*d==l>oO<q#s1z*$WxV23t~7N z4*@M=-(9_uq90bw&xsu5N1q$Zj(0HppMrBe-m#tJHIT#5>k!|czeky3^=kO%7LlwX zh>PPi`it1`Q*PsHEb^74hmmvL^%znc_P*<#w`u<9+zSMJ>K1Tngnk5UG^3hvqzso6!0BMO!Y~B8`ChNc2uFleSos|Qc1tAc*`a( z(1ac_`y;L9JT~2lDp=VES5EjPivr`nj{sCHStuLQF|L1L`xyi;) zAxW4=LCd3mdRnWDptA$9xh|+0+;8Unn{+4)abW6$M}+2c1hI&{qbTMA)^QC8$sRW@ z;_Zj)F^8lNW+PFB9mq-_m`{KGZci^MF9h!7>q&lBREi-$Dm>tbp_wIN%I96@#LsZzxV~eL(paxa8!h)2#y=Ro?O<(&`OXat)M) z^f!I{VwqM>2vnigDEZ!#0^nu4zR~zQLNzY?0?D=B57SJYK0QzqY?Qd4ZMh-nyA$7u z8c`RI_|P$ZbN=(&8118uAAdWT4gF7=_7=#?91&%S5^UXNn%O4gVS}ihH%R+EeBE_Y zH+rwD0<{^e*+l9r^HWv@h8BT;@_ZJ^QN2?r(I?xAlogqi*6|7@x7pM$7xUFpH>Xm0 zz{zwr;|WZYcf2wdC%(;wJ>TB*3TUbok+HR&e`S?5OXjXUs7*-u^>i|KkD8>@h_>F0 zyPbmo?WJrdk9YwiC3HJHk9Wx0B+*)fb;seZgBBOR-n_DhLE{RS@95AEv+%3{oZHHN z;iVl8IH!D6(r-6YZfgyECI(>zwHb(&o;<1Oh7LQbkZqB9tgz}JWJ=kMiEio4=gL%v zVWX4^45ymh{R|^U9mB4RM#5Q}-NNI_u02u|10zegQ*-Rd#2>c(n#U8dh7UO$T~7{G z2-LBL!XJ(!&!KZM%9&3)P9N6k$e#PVSDrY2-@I8_Qp_#9oI7=-H+Oi1jF^x=X|St5 z9En{~JZu~<2@2?S8X4N4OtOYh@FlE7BY!;g+vu#=&W^-f7a6F*&<`K2|JB}=$3yvr zd!`X8Aqj<1L?I&y*=8bXrCntiDcMQcH8Vy@MM;tnQ`(g5Yr>F3mMFWyOj3j~wpq-2 z&#T|Pzq@?yy?@;Q?&mju%{%Y=p7T84^PKPVoO7OYCPXVyI4(ET@344e=jSZB-w_!` z#%b5-pIj_=UZ&oR%x}@76-I>Bk1L~a#8dS2(YTZGMd=6p&Ki6yQxS!eR2+4!MPQ%c z8V}|Y?2=}ByYUv5hs4S2u~hqgV@}`pgiep%^hazpJ5ZO~?qeqL034=%6OP;{LNJo8 z82SB~WoVB7*1EV@A($O`77NGs%PNGMUA+NP+SOnZxCxLM?zvOcxs3!eX7=VWxekJz zpZh?D_*Y`n^g*+!A>zVO>rB48Rl8ikPQ}M`IrPkN39#u<1wM@Z9cZ0ZJypPyLsW!& zT3Aprmy1fET~$F2bNG0n9$c+M5muS8+qx*2?u#2S!1ToqPYOmGPkq5pTAz2NHbsHV z>8NO9P}m;WdONywOK+!`UF1xUm9$}hhJSh3bfDR)+!SI*euoGON?_lj2D08n>U+Tp zk&>SN;=pC^?>96nQ$1SIh>K-vWs^OG>YStmucF2{y?5G?1*}2F%fWey%Samoobf(5 zNL7MY+EG;$5IZ%7gJIO4)wg6(fo)3t{^d@OY51{|{bk0FQ>y7jat0Pkb*SA>ScuAz z(LD7{mLUBb1}0SCO+lhSLlGDQOiB0FXSe{2bsfo(19gsi=2!PLjm2Qc=OZJvL>D}5 z*2C3A2;soRk8N(^$Uu8YI!*&%KD}JtsCEx7dW#8i$PFTAw_S8*>U;N2# zpl0@Mu)3gqzmEWIIv{+K?NB#Ya0WRnbdW&q`xtKm7nOLv+x0j-G1@pk!o=)5A-zb& zzf!;RISwBJ67iutYbKOF7DAJnB?Wh@d)2BP019XW1x^eGK}`fI`FERIZh~ZeMC^|0 z|MW9>B5MtL#F&XqvI|5)BX)%*k6KbH1SzxltB%}e!y@cDJ>!n|S(2cbe z!eHPfJHV~l{kKp06mcuOKi^sns`B)b@)W+{KVo_qF0p4e5m2;1nJNlbyJtesB3?Cc ze0R|q9Pcrc+_1R?(W2^Dt>*|%sqp>r=`df%^K2}{x@wxDw9p_i40j_fp#<|yu+?xA zn!AJ6+vm{GDuacXUlHUqA>2Ozj|jL|77VSfFsbzkca`-g-*>M{xbsllG+G3HQR_*P z$N)y3)>1-z2E7%927gP zP&BgrRK|WJ0Z6zDHbDA`*xo!NP}Z=t0t)DBL{W{e$9X~GTZ$fb`bjCyzee5W_{fjq z@i7tz6bUaO&fAcf*A9*LR-4Pof;tX?IxhYa%Lg9vu55=zu3*op^}m{v`FA&`UIM>a z!3HRc_1sd_Xd*VIf-MTc;0{nqe)>@c@~UpI2-Q;517ajI?#wJC^I_NkeUZDHrr@=t zuq()P320H6TmtBDdilbQIh27(NB30sk^yX8Gvh(;#U16^LT+AEq7UrgAs03nKt)>; z$g>ba&VyIlTn`e5s|P{toA4#woAx6zi1^tloeym^M_=ea$EQC*Z%) z`0Dei8qTZX(xMWIprJM_`(zI6%!qK(r&oHlFZkoLKR&#_L*wOu{Zb>KYr!rw$_<@U z8-XwjlI(=6vu(S#orHpwC-!Krb!ak%yZGG;I0<8aO0l_3Deg ze$)whcS!D9ttb2}Io^LG$cVena`9rYcoDr~sR6wlNKz)BjnuZmeBm)l_Uq65371et0$ zOu6aTtr;btTCKh)GpXL34MH>Y6K??7n_F(u(C?jalY1}LLbb+g)#5IjBXCeT`bbf@ zunK+#0ih}?y86P(+L@gY46h^$h|iZE?*lAGo@+1#4X+O#kh8OV3dR60BnpVSF}Gr% z0$ZW2ojXiVU55(H6cI1_u{fgxfx%4bf@BqS1kt@?&FNSX_!`Yxg71gVT0ua%wc!2> z{lcYQkP5<6kG+kzA>;cbM@5JHC0{M>{(A6}+TXnZ{Q)R)*kn;f68p0`x&PaXgRz31 zJZEy^_{7R(c`K*-?ez+%Dp0K}L9Hv_^g&W}sMiv7-8({H!a1byKEFen-_b#_Goy7e z3%pr~yp>yBQSWM_L!sJr0j}G!-Q*xZ63|J~7xJs-ny0K0oFl(U(s*`#e@e~53ttKr zX=!vPkwdT_cOKC;Sy?x#-2J<={YI%8HS_YQ8&{eY)b&&k*eR- zUjcx9ho@atGs~xjYQZyS<2^2r{mPx8eUmplma#5wjMC4D85j+wR@P>J=6)7KhKoZc zPz_9*)~1pPnoLToV{};v>ocVW(_=(F1g-N<>LpCVo@vsx6skrc=m<>E z=H8nm&#iqzM9~Zf`0%Z8- zgGIn~UCxqP=P50E{q^BIphfBbq{SIA(!GHGqRpN1c;m+uyv2O$jt!aegXuSbKI_l^ zOo^F<<@`_jjLGso;KnjSFQVquQ3jhhDB)szN^>)?ref!i{>_mT?r=)AfRW$sve@i! z5kISd|0=AS%zJ;a<>59Rcde3+He8srx~*pRPQWVuVj&V!Q-x@u@P{bwBvvG;H^I8~ zqi2tnhPi{eQ;<`%xezCuY9P8MH2E; zdB>bR_k4C7o_jbYM`Z5_`5vRdv^SC3b!M*qe1gS8T5-E&KS?l2x`^lZ;xnozz~X^m zMp~#J*=RQW)gzGE@6o=~YO_(V_GE#ERZ>G*712;q@fp+=HUY}FU2X@u1={p4({osd z;e1QED#*Kc{7j3*A0`J9-6_W?u|s z;yE(B0Ni}K?Z?!-9tE)CR}(h!5pNgv&f!+)K_ocsew50smqwX$zascwW$}+QvU>5{ za=gyw>9<#rYj_y$K<|OZxd{i7DY+u>N0iO@9o2MpCadaINgGNykD_DtCv0Tfn|!}M zwW~ec&WqxtM_K$5YIjxn`Cd401SuHlDmzKeIhDKOsWL~;$RWp6d4={|EU;nqXHU!^ zlGg-1S@ZPv6`)tEwE!Y;jG+pN!g>5%iLJK^j+oJ_<~3cqL#_0LoF6E`kN%%27*zwZ z(9XKB@fJVO;d6Iy8QI^_(-C!=qq>F{F;HjE`)D6u&~{}OH3_e)U=pOSx@t!j@f(o1 z?ZxYOw#tEfnDr=L{c-Luw_ci*4ef357ww&Hwf)T`?7SpSLv2B8=u;0`OK-TQ>E#q0*xPFD5Q!1YrFd*G@>ML{h6;)?qsQ)Dt{gs^crEf(vqC<9MxKC~h&z%nidAPSXYcLgq4OzK~f?8Y1CQ zqj3){XeFI{IXGZyJEZubh3tINycwyJsPLWrBcZ)!K7)QixJVSH{yw!FuLRPdl-HI% za>|`7*z)OrMQG0zyS0n?jjEAT`)W{gi3#z#+;|Ujbu(bQwhy}%D$@{^+9XDgV}dUJ z#~tIleLYyJ4a_Bp!SBZKyPHgJYjx>j9q=3LkeMjPaa6K%&{rFEJ+EVCQsu1F_pD~G zY_B3zdA#rq8L1jE4ifbjp2v7tOrEI=F2S9Q#>mNX1QjgPce385Pi0NdJp);FFLi`p zGKFt$34`u$p%{v~Y*9$l+MSTKYDpvgwV1bbz!LEdQ8>s$od&+b@mqrthz|@2nuw+^ z>g>&3)((!FAI%k0@-ZaKFvbZ7zs8-1n}1<`KlJR}Lb%!~?~3X8&7X8(Rr1`di2?6^ zKAb8h@~1i|`?WF*OX4k0bMq{%HXSe5dK@wFnzO4<W&2499784TNqd`${+gyvjAu259fMJvJ#2sHl3!ce&N{ih5yz}+EQd@Z zy7{vkiH14&nugK!&sNXRHt+^V`4VzOi9cR;ev?;Pdq5y6eB?ufcNc&#qyn8Ci z)kvdPPUeA>R=z9kJx@|nkhPIkBP0iq_!1kORocr*d@@Ppj9t>UhhCtca+@lf-NE`0 z<9>deG4N#WgA=GkYGI>l3lD|AT#e^7;*|^ekVAOki^205>XXgwJevIWcb~HBk6nsi z2V#S7TQ0OhVfoDiV6so%I0M89TV*}x2)@bDLaBf->q}M^KRF44@r1qb2Osa>h_~k? z4S^+sj#x{>V^(R@ZKTKCx7@dzp8%StU(`AER`E>epu+a6(vpHCd&}_0j(o~$OExv} zQ7}HTCPve6)%Mo>SMBRJKYa&RKFB&7LzNy93T6}V=A)mwC|=_=^W7j(?`Q0)$&b6o z;rI7SvA1dVDh7`?uH#~XvnV{%f%q@6Boszz!-a7e-pHX4tE4CIU>&;ic0ng+-;6yQ zBTE?%-m?JV1hFsS7d)&%$0ZT_`yi&-&`0=uT|Emdk;|>rEIk6a3uSn`+P`fJ+3G{p ziaNw?$9i6lXXOiZj8DXxJ^jq0lxp7#d=QMddoq^V{K%z56bKBJl*ERh&`KX{R57l* zeH3yHG&x>cBF`B2!+5X23U(k`JE$FJNq_qJ=bW2wT6^Vyl6P7z$}p8|LSC#Yn@-1o?R>{DCW!6aN}-QpM#qj*IS%c>f)P@i-F>8K{PRTu@AuyZxsRLfZ3$eUOjK0-aH!0!MS*0%!7?A%KuIlTo0(B zDb_fy6m)d1wKJdHgK90L1D{`hceHv%op5l>GW26!X2lVk<0@nG*w*ch4~$gObmvxL z*dIDLOP2POx(V+&hchr(Q3=fxxLN_P6fM6L(+q^hkoL{!q&!Xiu=!2dfOk&eYusWB z#&T25Lenk_7r%$3WF3dQw03^BQvc39PCI%hFEmuhiEwCuv`?arp?=`&r0Wg~9I>WcjsARmqT z$UK=JkvthOm7`i723#gfE50j9^{&at&8dfu{z`A>3lp%uAL$eUjiSo4oNfbgvVKvX z;$UE-iggYkXSb6qBSZN4FVcsH?Y}6k&jG_18BaJEOsId0k^`bDKm;AKt}b8sx6*XD zY&MsQt@}B4`D>PqdJAdX2HAWn--U);ca`KnR5>;Mp8iE+W{{Xy%kk@cdH9T=U1+f& zNb|{4n%%$s=a_l{)42xZ7F&!UiAZdw;aiLY3qM(o)2Z;6j~0%^Ay*Gr@@DF-w{GA} zZwm--X{z+d2<~xB1yNzpXlR4^=dxdKI+9k;RT&m-rnp_cb2N65?S}IQ_NOV%0n=n^ zt~S8_Y}Ns|(Q``>=TMQAFiu%{^|nU=&ie(W7;dSoEaQf8)kY9Ip1-7meeF?80>cF5 zGe}g)*@We-D@#;D`kr>=;qIBV=0B5^m~R^hWq5332Y=HrY}$+03vbv)zJ2W&gcuuykwX$%QQUza&4_{Egn=bq~% zJ`Dk}{_+%j@B888p%Aj4dX8sF?IcFXNetGQ4&GE7@bqc-n(MDJLefZm)N0LnE}tUg z%aU!hbak;Q$9tkN*zv^6c2%7GG(HwM_g2*~DnTHFzje`KjebzeHIfVPH#iz_KD$ZK zXpG74Fv#;-8=Lu3CQU_Hj}R0%`p%qvU@S#z?|nVeqpmrxwPx)+5{&dc5-d66wRu8K z&EBlAH+?sFk0!z>z~8Hwk1q}HyFo;KQm#Q28u7kbGAPwLe1p6LJSOdiwL+SnT5tw9ZZ?eyw zg(h++ac6Ioo!;-G@lPAsUb~!2F_l4H`k~OcWToHaXd>q!jkuUf-0CzPzvGLgp)y26!BL*|c5*0S%>Pwn+uQH%r zIGxeeUO}f1SDO{m*-zUF+tp_pjjF zZW%T7larzZ(n*&LIkgTC!ei+R$CnAYAkE7KrXn2?7fZb3xcu5~*%USV6=#0bBoqs0 zO{+T}YT0MTR}V%y5uee&5K$QOh=uWzycP<1J+}&m_uXT@1*!J~;U|1f3bg0(xvUnN zzu8RVfwJ=QxEzQ4Ow&A07}BYtgS{&H@=U$(RtqCwuwoX^P$`!(k7W9GHN3`;{T}GS zg-z@&VXS0o#ntGUj8tca4m1|L)TjKnocUQ(zVheYMnDVw~Qt|V@+BWHlAwU2|Ihdj+U+zDY78VfF8FA5q z8NOW5mj`AS9!S615PFN3y2GQHtZj+qoRDn=$TyG72}~Suw1Lu*ss3WQF{FQI1(qAK zm;moq6E?(xR!9Lp_T3dZZcW&%+v1^X`^zN^b1x3(6%R|Nm*vtZm-CYR0^SQGWz_Vg zMG1J-=APYAXr!2OlaYO7)pB}Uy7ABcu1MCjygku!+i-QH!$+O($5JG6+leS-{_2|t znFtil=_9{yHjQ*f*Y7TN-4CbD>&h7ovSHd*-|K4@Wt>$$*EX0AJq|T${l> zS?S5RcRcp&`8n?q@96RX%DTYG{pN=H%s4QhOkOveu=;gNm2(OfwJIRkAUMA>Q$!Tj z27}>?6EKjRrBTcJU;j4LKtIufOcD98m44x(i7hFV;)&QIF2KSG5 zdhLrs+rzs)XC5kP(?GkP1BUcrJok|ZA#bJ0JsM{f*%AgnCf4=&#BLf;ze87T#+b`a z2ACXQ*(H4;;qKj+)3(+?nxLa<6K>UZA%PqG