From 17145ec16d5a0c161b600f1b38ad7041941151ae Mon Sep 17 00:00:00 2001 From: Brandon Evans Date: Tue, 22 Dec 2020 20:22:44 -0700 Subject: [PATCH] Elaborate in README, add DECISIONS --- DECISIONS.md | 31 +++++++++++++++++++++++++++++++ R&PLogo.png | Bin 0 -> 20599 bytes README.md | 24 +++++++++++++++++++++++- Xcodes.xcodeproj/project.pbxproj | 8 ++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 DECISIONS.md create mode 100644 R&PLogo.png diff --git a/DECISIONS.md b/DECISIONS.md new file mode 100644 index 0000000..3bbae44 --- /dev/null +++ b/DECISIONS.md @@ -0,0 +1,31 @@ +# Decisions + +This file exists to provide a historical record of the motivation for important technical decisions in the project. It's inspired by Architectural Decision Records, but the implementation is intentionally simpler than usual. When a new decision is made, append it to the end of the file with a header. Decisions can be changed later. This is a reflection of real life, not a contract that has to be followed. + +## Why Make Xcodes.app? + +[xcodes](https://github.com/RobotsAndPencils/xcodes) has been well-received within and outside of Robots and Pencils as an easy way to manage Xcode versions. A command line tool can have a familiar interface for developers, and is also easier to automate than most GUI apps. + +Not everyone wants to use a command line tool though, and there's an opportunity to create an even better developer experience with an app. This is also an opportunity for contributors to get more familiar with SwiftUI and Combine on macOS. + +## Code Organization + +To begin, we will intentionally not attempt to share code between xcodes and Xcodes.app. In the future, once we have a better idea of the two tools' functionality, we can revisit this decision. An example of code that could be shared are the two AppleAPI libraries which will likely be very similar. + +While the intent of xcodes' XcodesKit library was to potentially reuse it in a GUI context, it still makes a lot of assumptions about how the UI works that would prevent that happening immediately. As we reuse that code (by copying and pasting) and tweak it to work in Xcodes.app, we may end up with something that can work in both contexts. + +## Asynchrony + +Xcodes.app uses Combine to model asynchronous work. This is different than xcodes, which uses PromiseKit because it began prior to Combine's existence. This means that there is a migration of the existing code that has to happen, but the result is easier to use with a SwiftUI app. + +## Dependency Injection + +xcodes used Point Free's Environment type, and I'm happy with how that turned out. It looks a lot simpler to implement and grow with a codebase, but still allows setting up test double for tests. + +- https://www.pointfree.co/episodes/ep16-dependency-injection-made-easy +- https://www.pointfree.co/episodes/ep18-dependency-injection-made-comfortable +- https://vimeo.com/291588126 + +## State Management + +While I'm curious and eager to try Point Free's [Composable Architecture](https://github.com/pointfreeco/swift-composable-architecture), I'm going to avoid it at first in favour of a simpler AppState ObservableObject. My motivation for this is to try to have something more familiar to a contributor that was also new to SwiftUI, so that the codebase doesn't have too many new or unfamiliar things. If we run into performance or correctness issues in the future I think TCA should be a candidate to reconsider. diff --git a/R&PLogo.png b/R&PLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5d9645d5af0b513fb96705ede97ccaa962583e81 GIT binary patch literal 20599 zcmd3ub9W`*)3;;W#))m~#I|jF!ijB8Y}?7ib|%Thww;NsJKx`WUc~dy!RlV!y=!;x zs`}Jb9jT-si3o=W2Lb|uC@m$X0s;cc`u#f@2I~70<-R27`wP@XMN$N$c8cH>1Ox~o zEheny33{my*@Y>NE#&G!y}23ni#94BP_9Ky4FKc=z~%_S=19Q`scElC!LR`Og>##m zn>n{RUtL^p7Ee=KoA`B3(^pSh3ey)Gn@yGqlx-70B2T`Z%Yat!8&7Dok^N?G*(dkD zbx=p>AtcX;NpF-c!fSVut*e0WvAqw)lg;lPxBj;Q>i_Evz`Zt4=&TmIqV_xN`JNAG zYRkBb`yZRUYV|Zlzo3rCGev8avQoe94yEyA8lSalgU(#PFH^xBL6@*73`Qw8 z8v*g3KaTIMk1_wV5b%975W@Md=tabIZ*gK#Z?XT^$MVWz2rRnFGE&XyWmp})xzzoO zE4A;(rJ3?ltEOe;*I9JwD^VUo@fD>!M@orQVz%JvY@~tDr?zT)+Re9>1D`v=ozJXz z{AX401kd2n(FT{mDjxm`g=o|oSgxJQrZM8bOr+J}Sd&vK=IjO!DfwNlxt(ovGhJ>p zLu(`dHv>CFD}mhNiQS(XE;>CwnlD={rjipIEjzc%g+y25 zSiOHUZGTUsaUlz+P{8pVPGn_qI;>R+L8Y;K?_L2tL<)7`J;}e%4Kb1DxoyioK-g?#t{|SJz18R{rQ#QhhA=)ZCv^_ESnbd<6t^RND+6gjB6a2B9FuMt5&aDrc5!f zWTXAZwQO=9io!~NP_4vW!-qgA9ot5j}C zX$`7jO2!F2s6j{?;;F4Hw6gc@>EQCpnSvWP+9pH?lZ>n*7Q8{d3F- zi~71f=j@*a#;{?h(Ug&OcXSBpXUhQ$YcVf%;@#RC;$an(>(BzHW?ziFXIyTE_2kl0) z(o98uiMp8%I*>Fofhdp@iK%TpOwzIQ=VNwuo7NPfy-E zneXtN6yYE-OodirkX*%KsUA<0>X}-_3lqiW5jH{Q$IN}W{NdE5xAo}Mrt8@~ZUbtW zLQbi)kQ}zZ`07^UDIenL%bMaSULO66ueQB^KKsk<9EKAl*ttv|!-rytf*UjR zhD;>_;TVc}N!d>y=3ZmrfKm2C#mV)chrr~X7y=W!a&IQMrBs$Le- z=4lg)p>kI0mGY&fO&bo)Q6{-Uk`CYMnuCCE0#1TzDjc%%>#t!N(MYspUPA*Jq%dCM zI#WC}O8GsulG@2KWqwAfN%u~op;*F*7pkov+t;qM9(~M5fi)a9Mh+0*H)-cfoGe$d zP>kr>8MGBoxA1$&qw~aNUoz;FpTKY}K%3*2@N2z1RVMETws9qfCcg=}j189Ej>eN> zjs&**Kh}S|s_l)*U$M(H>*$LR&E{%DCIHYEIOV+{BMRQu5FQeup+v$6bumth4G28; zcNb9;55pz;g_gy)dyyPVm<26v&`QGC?Mfz;1I6B{LQqkmq9iKC`8)2l`l@2r(1s`O<)!G%>L_Fi{=x^3SrM@N}w_P&O z1gLYx<(-A~$s&64GZa6vqL;87qU~DyepGRx>yK`bqI=FmEwAgPs6F39F}|}J7tE`c zdN1J>Da*s?{oEFk*gv4>A0q5^xDoGpEPLyZk-vo;ajs-gPqEI{fMioXpLbGq@87J= zcI)Cwmh=9(($GjmrFEl7W$c_?wAigU4D#c?bE*+vqJ;0`{lWD58;Z+Xl2??v$iV9a zR&P!j&0=O@G;I0}3XfxYDT6u!ez9f6T$7TuiR2*MqXbV%RsJ-HPN;RiY8U9rN80T> z4vjte1ZLEd9q%wT%rlJ7o%``ck!{6gsLXc_ZdUI&`!~BqVoQ#Ey(Pvq{%V$50^Wh~ z5y{h|m+0gmf2wL8b%mu+gga~TPLM2-@^@gPU&<<*Qk25L73?F+JouqjlQ<~{Z( zHDJA8=v`M{uo(Rv1>8nZJ2njIM83jAxkG)o0QxjOuWV*rUUyDnX(dc@Rdd@)WIO&V zn^p370<+H%K6k}8UJWrny!})^6^b~QBkS>lId-ac+o(2Xl0xoR$aUeN|A+dx+NZER zzJDk$QN|k45}Xo#pv|AZci0QGiD9%dTWM!1xoL*Q2a_f+&>KeRH6N;F^Pi_evmE%- z)Ij>5hCd^Z{Q`d#%O0~`-iSwAKY1kij9v9Clv~)x_D5n|_Pp zo!-1^Sh=mGB$(bdi(jYwG(|iLEAL$mU5Wp&?Vym=YA2bRU&`V(r#TSYLLE`y@7a>yiMU4db1 zc#y{76RuDf`HR2kA~LV^c49Sls!1FQg!c!g5V3HD7V-?7r?h74xtZ0tsP%LIr!RHE zF#q2*#kB3mRjVLtR1hYE)!fbWxvKN^#pvHl(FDmD)v}uFnN5VZ zAyn@BLl1|mkL5Pcfq(s^<-lAk(#ALq!ZLY-f%jyfY&=icIM8jug1ZaXgkz5K#24$Ow za|B&iKK{%^EnRGK-Y%a7NdXOhW3-!h#DGAa`s>9gr5CSC+yv+AbCkFUE)UT>ib8}K zQEji|UpIIzo}_f-&`i78Tl|9*LQ2d*llRp|$7@=x6>1*k zX%y55RmY#l{)z3k8K8+Z+yOQb`vre+z^~f(VJqPV<6BdBY{+IsLHK2ifHj@z-oP`I ze4wbnuW8jMNK<(noAc}GmAfeKXoA1rClTiZ;J>bF^?M9d=KHL5yQ~Lb;mpU*H+}36 zIgY@1%TEeimTg;&F!he!vx;P18K%P3S^bf^unXbZgpjjNKHuEDsX{ccUw+o2E0B9))JdY(j<-#f!K~QPb;J`7x0pg36)Nf@1+_6Z{Q{MsyT*bS z1JD#HB~j0oVy<^cC`B^I>#mpZ=|}PZu*t+1m!2!-m}3PEHERVKYOi$T>lm=ZhJDWY zbq&2pTx`kKIdH|vnQ4^g?)y=bh^)DHvhh;dOkr}yt?poGgLg+^vWpvnisn=-)bp&E z5&LNS8_;O(Uq^Bh1qydCEekGq$~edJfxN|v(q=YvykBnGsu%*Wb9BFA%lMmGyd$iy zDsg0v@Nav5XWQ-kqe3ZPeSPTgK8~q}ReI{S`?YZgv0dAxp9?=deXO%LXY4V=Vk^yo zz+YwJji^H8N#IODOS#w@owF{=4?qU>Pgb6oeK#($JXLzk6c8@y{I(5Xe=9zmb(0-D9E?w|(?F!q z7c1g1d5CnuyTgg6-?@hB*U6+9J|I|7gDOrVgo!|;J{FgSnZ(~@x6PWQ{!9KNl2+)G ze$o3*KW>IS&M*Cu?eDuOk?-9HhO=F@S`8M*&t8s8lQ%g`BCq;tRKI_;>pTEI3m*^y z8V|+it>0=|ply&{3orCtv46qCxZR(qn(6N!b>lwF!F^Uqc~U?s&Cz8ivW>2WzHmp` ze*e8U;*l}zN>}A7B9hcqhx@)lPTuDUxuPxmff{)_@=CrQ0!KUzB4_zfPTV%s0caVp zN9%p6U0;b^M+Hb2>Gyv7Xkz{x*EPd0rL#iB#8{#yL}3-!=ab-42;@2z*lT%>US*fF zjiS29v+=$KjVXdv1Y%3z@A_e%$Klr?5!L0Do(Je;AwweN`=?v=d)Z`_%zY;7o+DFj8{gW^3gHmLS^nSh4+{OBG`|fo5 zrFXW)ZNh5p;6`MEc*|t>6FTOj!BBy@G+1=B|HBKY@Rud`?S9W%nSZLegh4JpQu+lP>Wdl=@oak2d79<9{OyU6~$patyR}v_Bv5fv_3y2FJWx};NiXs;@URam$S5m*6ocYCx2h-W?Jp+kg7r=RZCe+ z{6vw^%WA{@vdpQe#zTb->2Suzyn~s#LR|2<;3eY{Dj~u8r;ufCFT!F+)RZpU#)-$0 z<#x4q^TqSvW8R8!*|f5Fjz}-0e(^TL(tt@HdG*AZZUgZM_Q=k2#-2nUn*a{l|6F}N zpN%^HOxM71TU27y=wM6nny$`?&{jV7vq2epX>fD;7f5%&p5A@L3z*nr*}v4QntkWL z-(mKfDE;$nC1wS`P{Jq3KtOBeZ{`G?axxAze7OvpMSGHRHvj#x4xuAPl(3yKp||@a zcApt4K`FVGl;!Y=H1y1OX59hJGRtk@0k)cI$C1y8ou63D4)0ISOGI}wb-jNmqUjRc z>X~2`II5jaG`({Z37fVV?$&tIYPb6hC!fLvcg&?rG>YrkzGxxs38$&AjCv*01X`h`0gyI~|HsGjXy zLw=AY><08~%Kvqi3&ov#7nhayVPmHqsf`h`_%Z`o(XD)EZo{lpJ*QEIwv1KPGD2Af zDehLcfuvC_B=NP-j;C)ktUBuHfabOEH*xnmB|lXeRhqZHJyvZ3`2O-8*WR5xYhD86 z?WZb&3qe+p{VZ&R6|}RYkLqb;OsDfJi{|rqag`tD9Cbzn`da#xcUf!aKf3$9G*=)H zx6M}-7S{o5Db{?H(|}F9BPa`6{8eA*LBZCo?6jK(7RwspoAjwWoHSFf(*o z6ozd_5wh@mbkV*;q-Tpykgj%nJ^&HgGn=YC_pWn`L$}2JJ00Tb=F_^;;+b2Bi?~}C z*LknZ3>o-jMyphfNnNAzt9+7wx^ZPRJnqWCZiy=C@W)ftYQP*X*9NwGeOQkt3I%bo)}nt!terjO0lskECZqsmnGBS#l#cQLUR(jnRwiFkj||J7|1!-74#YN$*R z^Gl)dGe!Lzm+Dznh_h_-8?-1g)RQ8~&c;N!q|%a_>;hDnGmQet3ntzkC#v^3v{8I$ zd8iE_Lh4mP`{k?e40nv!HDJsQR{V8@GqtoQg8z^uXJZ-};%S1u`q!(fgU(Ib7mdvD z92qm(&qO%rcaXa>qMDyKeECWi@Ozx`2Nn-TjgfPNnF9EApMy8OpKurRx88-#-8~Qk z7>e%)>ui})bo=px4EGvWSXRMOWHGSx6~FCmV& zQ74eQ;pP2HdxozDCybx0QAly%Pd;TouBmkaqH2*Q|4gdClcCew!hWdMIS2b|cx*Wf z$1D*)k)V%`2tWGA+>xt97n=#rK&RPSwOp=MA#RCm)-BICNoVf_>hfnFJUxxv*>y^L ziIq{6BycmfRHbLKRV#QM$&3&JDiU4tlvLkXW&o-7)>#YEZIkOK<(E0h|ip^A&a$|1EJ<989WC}9iwL?uTWt_m3zPs z`GO6uE(NXKk@h=ONu5t%7#tVVwH6l0HtZ87esYXCjl?5k6?6fh+VN2>c-*3*{%jZDjNiQ6j;51*H~RM6>oj)pE0uIT@Yd_jltE4 zlxWOqLbXyFD8%S8^}OXO6+sm^!hxU(Mx{$)P+o;PAyO{{LL0Wrk`>VDP?4bsW8QQj zUS@%hZJ4fi`LS_;VA(7s5T+eck}w z{5G%|%q+t<$Rl4w6e)zciBZdUBW{d@^AG`ZZb;G}8%DLpMPsS-AG(vs+s_KL*j8Gl zuCU`n{1_(=-|+*7faV(wx{JXULN<$tGL};F56IqRgN8z7fZfn=h+le0|A#j$WiKAt zT_P=J1?hQ21xOAjki|mhEZ?iSl0DMx4+uPuNK%&fVl4VUR-7nZ(m;_Eo%4+YHYU*Zl&Ap;}kb-X?1V`uvpQ&i;H;?ZlshOCW{QD0?sj8suPS1MfGRrd>^Pd#n%H&dJ2F}trN8HN(f z4;Q3o_~`vHcqfunPOqJ{BqTSZJmwvGLo$e6ZQ$2JaHA zHNM$xni^t^d%G2E@au>g@@$BM942;W)OiH%+MTZ7ogve0LNHD~8PFOZJO6ajM}Xso4i@#AoexLl?r zeBtJ!6qNxMt~$cH-C`4}Quz&27?$+;A5toUNF$9poKCBq0wnyw9Ul?xw#9T4xRyNl z4PEc^nXb*J16dLBv#vb8WQ8&gW;TdRui{rhA&lB#6+wy~^tWFY7!X9a?Q*~DV2)aD zj{U>B$-=sjrnqd#6~F1b^}z*FT!t&g)q7UA<-qVOa|Yp5%WQesfpHX+0r8g0Gsm9( zVQg|C8MU(bhy18JWfzdpfX_Kdfte55LQP|ardnrR>&{Z6&X_7G4}X}Z$+GN6cL)B@ z#2sX@RfA2d@8oO9SyyA=jp@Qvox(!N%4w5)_n@)&^vZ&Gj9wD_Tx!);jqA36^4l7m zO(s<#Dg^YLC^#JVs(73>)idePht0ZnyRB)p01c5WG4Pl6BRr`TGst@)zVv7TgA(G)M!e=E_ddDydJ^026hiQxMZ7(a?!!2B^^pHsXvD zMyU{Y?#KNggxAMnhgz2wYJWPDW+}OFuiccR>K_KQK|CN!?3+)7(UNEqaoEmP17XRc zJo1`IHyEgw?V@i^F>tp6FMeIc{sf#_yHHCk=nMR21TsL#ldjx=x!TR))+2rGw+IQZ zj>igs3}dE(f;?7DYorZkr~rJk!|l@5yh9*ZL068>^K8k2LAD=mlvh(c(63M7qiMtJ z2r^YHH?8n_V(DjevuEDUjb^B9wL-J$J$Lh1vO+p}1q~CSb|#$YSV$;f-3;P_+H8d! zs-sjThCt>a3Lp-CS=SOiiuk-19(_4azmzNBQScn>GCBYWuT-fC7=`#=RhfNbNZJv|h>VTXM(PuV8A+CTXd?w!2xsk5oHeEkh`M z`YupFDmttwvV|JAihkQ7qRa(UvYhAEjNIzEw7fDOG52o%40hR!f9% zmnk@X?JtJ>RQ33~CeaqwM&*LKQyo#*?*$T2;PjK-I(N9PeN6&6~g5I4s&_ zs?M{%3-2|jP_j4bGc=G@53KqvlGwZxwYg@=jLC!Of7~^;sU2AGG)+kk{0ia-0Cvj> zs2OS`!%-K>3WF_cB+y`UfuOvf1CWp}o-b7A*}_U7WeH08vGPDAnDnD^xGK$*e5}CQ z%c!t9IYR)m@DxYOBZ_i5yA6iIx$uP)-HCzHW@ascpv~nOum52^Q)rGL5H$7t&%lgQ zxF=gZo(f4m(c6roxZLMRV2^IQ;HGbU`nJ!gazmx_#T=`I2hIfeP7I0dp^U`OHZ)RV zhQAT?GP*)~@G({U<)c=ob9^n!nK_6T>L5*oEa<_3cX+0DIidporu&|iO`-S8l1us# z_a=b5wk^k-ohVk%K6Q!=>R_q_qkfx^I8zRPdLpom0^?Z~bwc9K=s?#uY#DpSTkS>zprzSMG(kz{M9647^G>6r94&P8y zK$f&L$)=sn#0{PvvZxyxKa|D#LPs=y%Wmk8oDA@5)y}ALIU-{rF=MrKsc$q|avz3) zY8UKEK?kVgK6d(Sja&v*q9UH$h&a#DUL$)W)S8!;!CnP5Fn=y}syTh~SuZv;k9{j@ zt+mRPvbP%-)s85OT;|e`#kb>wvl`x8jJvDEnU;$3WRuxGHJYujTBB>x=47feG=yWn znDq^t>F0xy%e4~)pUC9xwvmyAdi!Lae?zk@tETB8Y7jAyJ}mrxy6~$9&#kR&K=HOz z2=p!t>t^|vq5Cry`GYTX@-_Q}T5GkPB1!0e`eAu$@9xCpH8a-KT$&M~=Bv3-YWH-Q zY6it=2exkIPhJR6cJ#%F1gDFOo7wZaKG`l14qZF9Oi+k(?CNl%;`-N!f)ac+)+0Zu z(icDi(=Ns?c#=E+-PMK*To=2u--lZO$pBjw=9Wh?p2nsw6oQ8C)bEqgEkl#A;ex5i$BU~b_ulVg} z6s%L8r%*t~8j5{09ku9J+Tl@Uu`!N}l42^1{!j%H`0dLeh5~h}%0>o1AR_80CNP9yFln1Iqce z`msqq`$SmCx>ZwdwO|pe_dk&b>n#gnPvS(El!MK0$eO1<8kz>U?g^}YCdbT#y zQF~G+L&My2)4<{2r)~+^_mK%sh)+G8E2WUSzWCg!r0M}rHoW|Yd>Fxl!Z;)D5*B?7 zBtaz0gMJm$rY14DpQ`I|CIDl?@KKT$^*ymyf3{1%K^aI2M4Fk-tAuuqew2SvUS2G- zo7gdi0)yJ~wz>w9v{6D*+1u9$8c%%D_n8)f6vJB4b57o@Q!2RbRWH^?&szG7u4y3r zXdY3n7duatKo98!r#OW$x^*OCpR|HX34?y~H#rEF?%V0qnxHOn;2HU>n70<6h=*)4 zNPX$tE6SqPM4E*l?yubTC0u~+-zMnjNT6v9Lo}dxU+vd=1hN>7S-LOY6n1I0KAOdX zqUgi-x@Wu9(dW}OvETgJqxJ~&ZSUuRHyTZMPR?}u`(w#(q^yQ|hwO5VaTE524%BEP z)sp-dtp{V`Xz$^b|JWG@^sq9ieWFMRiUrL}bTkaFMk(8xsNu=M_7{n?ZWsa;gx%lw znP5QOTdViLlk0Olj|3**#;ihbc8rf=2X}vWH+Y3_5T9V+l6n{XTJa7`?P0ynPTnCP zAgy= z7y>&Dd*S=_q)^*mR;<5{1$1_)NB1ZE-ByhD!~#p6EF|pIn-$$oFNH+v`3bNgbb~Sd zvbGiO#Hu~756t#`PQeU#8m;G2+<2gK2NSX-ye%cw>Qxb4?;atEM;4_Z&e@PaR=Dwz zGjgStR)b~tQ{jY3ZBWz>N5l3>FE!<4_VQ90Q$h5xjWwc+5cv=2xgO%uNZNElVcV@r z4KUm2*bivj*@Io-y#i8jDJr+$Q>apYPa#(@Na%-&%WK#puYd)Tth@eunCU9Jtd#gx z6tjRA;v^JSKrk`W^LcCVH{l_HPN~pP6^DJexdLi79DYdy3qcQi;0a41QBKi^3!ujB zlFCP5yj&eLTnkelt3Iq$A36#6V2ry8zPnMLoLA{v_}P_Ix4N zmmT5V3=EkVAPG-yrF03e&xO^(cRl&%qgPNv0hCkjS2fIY2F2a8R(eLoD z7lA$9`ox`!Zk^JiEI0~SitjIJrY_Xv+h5P7Y9~1oI*tT!;2{OVV-a>o)$RAYqd9~1 z$%E+9XK5;|;JVUEmAgCQ?C$;P~8CsU9S@ zUBd|Ofh#Q_4fZ8Jx;xq2k`xd?F;NKk;-+#WEnlADhC=JOMS7$?*k@3Xx!gc)pd&EQ zq?$q3G9^ znys=6tYflphb%GP?k3@T@BcFy<=Qp=dD@)6uM! z$*bsTDTFtIO(_JI0G0a$9QOgC@92h=CW2n^U-o~JXbYPNz5$@|7CCu0faKAKYF)Un zeQ%zWY#1RF{^-e@DVjS7jfBkGLYxHie-I+cqdUm~7s`SZVCf08uOwDTDRx{jNASGP zx_U83z}sN524J;m@-1>FWZ-uGk2eKg`~!|fAdKYa%Yc*-61|#pfIk5v3Z9ZoO>Jh<}}ehM7`b5uAs}!RhMHL zx~$w4;iE}hadm18Ts3l6zuRHdrY{uD1{$|>z9J>FPihAB^4+=|2PFLrX|mi)oSU8g z>@vHjspPcgHc)2Uwa*tVV^$OFXDq0#??7Mr{bz?{M^2o#x#TfJeoD<69y}kXBdPkA zeMeDb`m8YJ^Jefc6g?eaa-=0{1+r4NU=mNUzR}yKHw-$Fh8D&s=uOlte+;Dmb}V0w z@5X=L?uk%x(lXEQSEYarCrZm@zM51Nf)D>9c=enZ`6AhGehuCAmG1?Xy3+SXeUtZs ztpzt*ECL^9ne&?|O!-(|MjM%7#tp35pJM7kGf>|(H`)Fwof{m4^1{gMNOWemcLPMi zNQ`39bMjj~>vB%^w8Y{ul-Jy?x4=?mey(j#xP8z2*@RCNsy2%dA0-Vd0difF59sJ1?a8;!=gOiy9{OhHkh=oEtmExBTJ7TR_@erDLMEoh%<2L|?@Absi zCDCVrXuN^q`Us|~rxCD8=+jP|)2pOLTIqgRHv-cswTjgeQ~z_~kApX-&s^S)5L~TR zYR?PjI`88Q)J1}Cx9!ChFbJZ@&W0P@3A~lju&_I+Oi9O`GNF4U=|ZC-ALbg=u}2pQ zxh(06-h*vYV3v|TLhg2~p6pDvcD-OS5d-%uKN?d?Xt6TkiQT=xsZh#|1|pTkxy#&ps8cQ*ua^ z6$o`hR30)HDT^}d3-W`xw`Tv;RAoqHp{nnztov@)hW~4C^ zVPm2c!o&BneL>p;NN;ySMg$RWZFE}?2$G73+v>$x2jxds?|J!k+w%_SMDvO!%Ho~v zCS+v0y6kcXKHnJz)swKQ|2P&)tXPN>gHgcu+aE!+*)C~S`U&!7qtr_@pryN9=bu*_ zW*`80|u#>fIz5%=~n{jE+x6?+ICoU71idNg?KpdA%G_*+= zu)NXO-GQp-_U4TQ)*d`$xBULU^MwQ^={zWmNtd{1C*;19hQ;8BdOwM`J=)JV@*G-9 zhPi`$z3TJ+Mq5Ocoa}d(mp|O;{qvlBh9@5jVEgssuB@=&{J0K*G5V5(3Ods5ycxsv z;AcZE%r51qD0AXGo#sTf#|QESNVeH$8VP*_0zRdo4V74_3ZH^K%fDB|EbI5yq{QOJ z5?Pfb2}H5AZJ|3<7fNYG%+J^IUs5UYW#?oxjr38M<+b`G=I)XZF{oAvD`NCw0cDz) zoXD=>GmC-^DH2YxUx2Edt__V8SB{u55X0#UfUc!gF$ z!v1p_g^5@kZRNdPq|Q^lHZ9S6x9;wAf9;lh8u&v(TTd$8^+d}Wy^_5Bj358f8O8Kt z>*XbUYni9VvJF;f)W8k37@~H%;3_3WU)y`f4|*VM>_C#F^@ zRyLgZC-5e=C`rs-5(IgBnrS`ZG<31n&|D9~?R<;z;I5R+p={;s12h8NPO8r(KPiQ{mU&>H_mF^aF)NTPkSMu*gFricvU_ zexng#)pZn6KF&Yu8|jJUAIl+IZq7$hbUV*Vy#Hvr}ZXGbMnzzITOf7%!DU zX03m|c?1|C0x*r*{P9AhOztuK%1er46XGnzH^2w!^Bx|$M~en5RPQjH%Xu88seIul zia{-wc?}vVO{#D8a+B@y{5MZ4pO}`<`0JZ(u~psX@8y;}p2AKHMu8FaeR1{)@_#2# zT*golI++i}XS`aU?)W)>0&_)ZqEVSxL=y5xr2=s1`#{m#?`$mdo!w#&%{gsXtb&1i zLvbCpaZ&e=K(FvQvtE9>|GJSQrPavvc@ZO++n)@F&p|9$wct$vBK}A>4CY;vC5U*=p6wA@nM*y#+WokRwZ=cd`&jrq zHjlZ%)cgu`ejM(Q@(%RNp&+CCbN>R+a(adofbGFnU(JS_bxFgRG7Ijhm@uK-oQ+-l z1nUR=v)hA`DIYE;+)j!DUkDJkR{uyKAzm&Shf!(j5Y;TW3iB1W>fEalEY^ER4gR16 zQ9Ij`R<#;kVG_@tI%LpM{>HweK!!e_dkbA~K0^@`E0{PiWIw)dl)Uma`m=u&N`}uJ zEM^(5pVW6tRmEdY_Ycb&C1ct2Ak{7qNu#3Z^e3-?$uxApV4|^km3xq3XuGgL^1qcS zjC9OWRp`>c`3!b~q0CNnt6&9v_;sp(TI{KX(e6w`NjlvF-LJfhqp%W5j}E^1Cy0Ro zJQNx@rg-(5e6#TQP-!f=CL>S8;)sA|1=3sQQbLlog{V|}?kMGuVt#Zw46>~f^`|Ibntt{_3pQ1E})d*;6TF#dUPcXdS@S{soxTyRvX z9yS!oNg;p-&;|;7fAf;Kl|kU9n{z3pbmpL z6%rP9i+2`;c+YPd2A~leBtat#wO=M!zBv+oa1&2K_5;--mqD8le_VQP*B`v8q`lr>9_ro(^n|fRC2dUqmD>H>A7d3tNy!hFNXA5wh9e34JGVD zj5mZ_l2>OP_T4|CH|;QzFp9-kcv-Y@$BIrN>u{eE`Hj({nDBu0Inu0tnrfSShbGs} z@WqM=c&bbYSxGZjB0)H18{8=4V^L^C&tH#t)OJcBvylt6*_RK z@AoQ&E?VI2qvC0B&8V$V)E1dwSy;<=EqjC_9?`M9a7LL0jo8e2leNw3 z3X!wF(~kznX;WS@WY*mk1Rc`-%jtZs1ZF%L5>sJk3AkaM?X(=6*5NVt6=O`gLcLMk zkmwt-JRpP<#Xg5%DAIgb*bK+k-c>o@G z(;9nmFWm8oBw%|h3rmt{Y(W_9f85U!BA^f+e z?b}d9dvQyFD{_z4s321JpI9>x7lgcB&7xSn`HhmL5+p=~8`pOHoo51Xugrwb)m6;q zGK!l8vtN`@&4Y$ejb9fycAw24rA~INMMJZv1&b^Q=e3FaB6iw^!5~07seGuKg!S*b zFbWz`q>lB*JA}>unYe*)ft<;2X4xqUq9$nL9F3`$wOChPzVC@-VsGyp7=F#1a@fjG zgax_fgB-)q5@+c9EeORi)Ex$ zVTU6_zqX+ZMT*1FE>;4T(AMmSG7!_OA-VGt0=m4Zf}V=wetI6!lbWkcR3jJYl*!-e zTzOBv*I#|U>b^cngxuD*#OH}9XtN!h(|(w-rgG?__aV;iYP-DO*Vm1YMfLTc1@CIngYw#GkW-u= zV8Zok%xFt!eV4eEL=-gJ@+&;IlgsxjD*$m84)yti9fnHPNF#2%YDPqPg2VS^L?46g zkjCO>4m7Nu9*}oLB&fmvO4XteEF_4176MVkmSOV~qFd@elJf!L+LU#_u0p$nWZ(nU znOju(W=Z6}ocQ6eKD#fyV}9Grlch(hai`oB(`m?2f_GS$75UKxC}JX*Rj84sI}{>g zc&J|=zkt7aN6@HX=F>qIV;~eWnQwuYGiI9(?>>W3tr!t9E~-nZlJsWACY^pGW2b48 zk$^!3G1Bg)7JP8n;l`)AnE4J^x&H1)dvK+)rI5M{HVGszH zL`I<>mS$0`VQH?`w1Ap zYuip8Y?AteP~=jOaI2#FP8V(MytB7E{)RiEk4I1$P@%oTaBF&L}B10B$x747Mz9oERlPk<{CYaofj3LAn z&XcwiJ*M7T>$IiCvvl-1iiTKe&xTUfb@*7ZMwd_p1?Tj)Bf;-5n$7cxsb(r?z)cpb zNwfAh&5tb}Q)z5y=q*>E6)y$Y^C-INIc5tE4`LzNoZwgQIzZBWodEEKbVTnbE*=t2y067(f3OgCDvQO{=w#!mO2#ieX?z?6Nr#NIuP1bw=WCQhSF!gnq;pIePsXS> zSuSa74dQT#yltWJZJ7aH4WIFCvok|zO{5GOJN>K`MtHh-Idw{PL$6JFnJ5IeUx2x0 zm%>t4-)eIOQ>opM4$5AqG}0v+ zRy!nW08YqxU*1|sZFlYWQu{dAu`ep*V(o>l^=#raZuP|fIIQldTmAOTG1t4| zALSe2JZQG|ly_yzbpY66GP&Jw5{Ypk40>s258Toj&cH@8q@c=Le20nM6x8sclZX~7 zE;X@LlIbk1sb1^OWJY27*(Y@)R9&~+wH+$lbCQ^ep0x@EMTNVIwAj(YRINYrVcOF_ z^fOQ=S{xWHx3WH9IF&l)g(oqyCTmQ_a1zd}taM{mcxR%hxSp}skK4N5*nojE{tl}( zn{JL+Q{(dd9&Vfoq>Qusd$i}9N7S>9y&wJ%-k{FkuLq#`?_B_kZ?$eY*Pn22%I~3Y ztE=yH3S_M1+{LE84AeCphl$3jp6T(`3Q;>WtNh>^D}SN<8S^yF|h?((P^R_E`_>a0U#BGZY7 z{pp8*2Dls~I`hGnftf)~`0cjIeBzA!DEv)+crqjlKiaXtf`UkcBIfQjOq&D;5eMG! z$y+M8K$QFZGn3bM>@)yXdyMTC1WU|tFO_^bI~Fk{$4*d z&)0V=w*|c4{~(SbU+`8bNJp-_&AEuW6ZtTxuO(cfTbu3ID~#k^9a?re{`VfA^@c5e zBlgbn(=HTo&3#GebgeIP$BdM70bG7EwhiNPXp-J$L*y8n<|muRL3HCU1w!42Ql;98 zl0Tz5>PL-Tat9dOGu|p;P5Hi2sI2Um&1jm0493$r_KzE_eE`&Mn3NG1xb=4Jk`ldG znbi81omGqTL|2Am0p9XyKNU`fxJ-9soezpVSkIRh!_9XD@Qhz%nh{nwygz06!I%AL z22F5BkY_f3RSS7mFMUG$oF5`7825K#WmH-s&^4?r zp8__fP=`!`%>y`QcmefX6H9vhv$QY`LLmCVJFwCz&}38771ZEq1!Q$Z8<0`?Ogt+Qhvm1;? zS`p_=J*c3VocgNbvWl*c-h`H7#=P31>_5cAM6pe`OlJI`Yn-&VV~r)thypRM)UkAC zU_-H``6!h>A6!1Ebn*)e)(6T`4x(EeH^8mSeRtk#twxFGF9-{BrjU`GQ_;JBZvQd7 zMAMMeOh7#_{Q797gzvnzLE4Uv{Q0%pI_EgUWa{eejRdsxKPz=?cqv{Gd#V71)lVo~E`9egP`9~ug}JChS_*|e@}J2CIL)(OJB6Vmj=umkfRJz( zYU5dr8E|&jWA(Z7rmRQ7Ci809+t@cwx}y%pVsz(RkKe?;^!dE^_<;G$qhy)}0v5TJ zPr)^Psvg`%rZwy>FgN%1ixc5Uso1fROm>O8iW+CmCjC(rGARGsWrp9D*zt#6cQ{=n z((MC0DuTd_U6d+5**%i}_8#|Af4%jfxK+74^FBZ}?toDfgTu;df*+1LTAGg_CTukK#@1v`a?{gPYGuXwLpknqg{o zc)HDUnq}5eNB>3>+!T-U%!e``pbT4nx2ft`8&X!Y=2 zMo?BOUb6~1{;S#m@67up%t>9?0f<;8N_5?N*ux4T89Y3e7hEa*O`XFR|CkJ09m*aJ zi%FiZ^UBY4n;mNw68j#{KAWEi@fx#BF}EM{r%V}%F?R30jDr+ET?mruB9G3g-u9_; z?PB4-lQRKPp-qflh}~1QcTIdh*8|2i?{i#DQFtl^43kIykiAVO7jR0H)s)?-5WMfl zEr1B=jbY5?7D5W~$anULjIS@|bn^vQUaH4Wi8G;3JsTxK>aiz_pQhq2Fq(h{u7>5S z5RzB7L{1N@whpBDV$KV~)q9RW9pmBfiAhc+RziIU^kp^KLX#$39S(|1J$}+keVUiH z5V6R5`iK1p?DbKR+=Z$K38m^C_T#pcj%dnY@KI#YSxtZ=4 z{2Tyh&OX)wp1jPtyj6h%zbtt^FJp-m8uCdK<$t)&KSxz=?vT9uZ@RysI=#+aDo&!I z$^$FNCt%u&AQG0Ibt$Iy?4`4qKd3sRL_f+dOBZUckmp*mdh>3!?<=jb<&gxr&9%G% zFKkn}M@rH7MP+M{46yg0V(v-x6MPhv-9(Fa?0zyKI=a46lZkBG@ zt3KxA>5cXS3&>t2uPn79I1>PLKf-v0k{Ulswxznm&K*;01J0G8AiegOxXjHW&W=!b_^ zxMh<42<+(iXlK!FAGH!>QTKdPi25(Gq;{X>=He{&8Z^D9xe=KlJ?1`Y(0>anH4bW~ zVvI5g!XlC}f$Eo66OAHsn8v%4M{Nuu6DFI!PHt^!wfB9*1c3@c)OiwoiBl~&?RA(tC05pC3hJ!aY?PaGr7hNy&mtp%d_jtUYzo<9 zP8I#@Y2Kx;R^?>BO7bRfNT6YFXwvF2UMqI*JP6-B4*Xd>PmZ!6Yc5vJ*y&$okEItnvtWxQTPA> zhYU?F=pP5t+-_EQbC^;f+pUFq1d#(XJ#)rjEA`yiTTbxky#;+E^V54dEyvx5HejaP z_BfI(YA&cu!ih8E2a%iu&d}GB6%UZxUaYM_OiJupI!1-eoIFhy<4rAF-82#XN!)dI z2gT#?P`Dov;d!s+%pAo??p480Hy-ixb-!AK{C{E!G=4fQJkZBSTmS zlo~%Vn(;pD!xdX4cgR09B`qn`X%mKEP}I1(KU&Y^ByORF{r&wL$Iz@NT8mxj=Ai9Z zG|6M~E4`q>c8&ORwMOmd{)<*tE-W*R-lhT^7LC|KMGEPv0KId1L1AP4c5hV72Y!mf zc%y33*jS6`w{ZKO5O~b@RKF(b;jdfEtLzSZtBw`Z!%=NLAkg-r+0%FsUEJMX1;SP; zeKRn$%UYXHVE2w0oxJuhwk~?&klFhO(=<0qX^k=}I5792#qdV$%u#?uz3$5M;hOAp5u11;juRR;ylmwH^DvtT$)L;N?Cgg%gt=6v^V z=yX+eOvRr}9TaPBqWW4#?gp+FZ$RJ);UoC9<>gdKAy$eKr!R7QTPazuhkm|;Ui_ZR zwehOY^!}5_n-uP>+;TP5>ZEWb>yBb&2X@A#9RfSRLukJis4j6RaF?fr#vh;XOk76z zX{4EMFffuh?U74()fBgkI~X}1q^Du~DX8_6V2lx3&YIyRiB77(d{21D&B?L>0w-}A zGAXh39x z7g`R7gXd3~ejeZ`J**59SjF7>!`^Jc*KGRyGw3=y>gV0+GMZ?)Yc;@I-`&0Y2x&KN zJ&K_VxGFg8U!82#5cYE~ftYlKY!{%^tF%MQN!f4A1LM)u=upEdbBH*w5m@IXErPpC zRq>pP@!aIv3m^U_ABv9(hx4gJ@|?Nr^Cdh`e`&%@$wJ05+$KvzzN+3~!EhF-DiGn^ z&q5fk15JXWbD9>)G%eoWI891Qw6p+>&GN^(VS1KH?=PuSYa8x94n%Ii)vAlBZKOgu zcmg`UIYegj*!@iWB$D?TEaFrSF?`ahpSTn;-W%t;QCJ%3&RPud-z~KHQVq0v5Fcjq zgoj^lO zEi1UUigs0Fr)_3{@eYUKPi6LpnfI<9Wc)T$g8=S+kG$zG>$Pco4j4~Wf!hQ>OmN<< zTEpcJYH@Oa)NH6IYMyr*1GL9-vXJ@zl!x=gl8ffQfr^d}6EWd&8Q+9=|7W1Xtx{_! z5Mp{DyUuR0EjSa^_J+@mekj%!>*#}Y`L3V8?%dGs< zW;k}JQ%kv+-d>L7^sW1(rvS;hW|`i4s&R#BW;)Jo8o8Df_@C2lXiFuQw>q^&(EHwh zdb88Yt*}brza90r=C1<&ySFX?XcBravPN16LOg + +Made with ❤️ by [Robots & Pencils](http://www.robotsandpencils.com) + +[Twitter](https://twitter.com/robotsNpencils) | [GitHub](https://github.com/robotsandpencils) diff --git a/Xcodes.xcodeproj/project.pbxproj b/Xcodes.xcodeproj/project.pbxproj index c1ba851..f3a3d58 100644 --- a/Xcodes.xcodeproj/project.pbxproj +++ b/Xcodes.xcodeproj/project.pbxproj @@ -53,6 +53,10 @@ CAA1CB44255A5B60003FD669 /* SignIn2FAView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignIn2FAView.swift; sourceTree = ""; }; CAA1CB48255A5C97003FD669 /* SignInSMSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInSMSView.swift; sourceTree = ""; }; CAA1CB4C255A5CFD003FD669 /* SignInPhoneListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInPhoneListView.swift; sourceTree = ""; }; + CABFA9A02592EAF500380FEE /* R&PLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "R&PLogo.png"; sourceTree = ""; }; + CABFA9A12592EAFB00380FEE /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + CABFA9A32592ED5700380FEE /* Apple.paw */ = {isa = PBXFileReference; lastKnownFileType = file; name = Apple.paw; path = ../xcodes/Apple.paw; sourceTree = ""; }; + CABFA9D42592EF6300380FEE /* DECISIONS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = DECISIONS.md; sourceTree = ""; }; CAD2E79E2449574E00113D76 /* Xcodes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Xcodes.app; sourceTree = BUILT_PRODUCTS_DIR; }; CAD2E7A12449574E00113D76 /* XcodesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodesApp.swift; sourceTree = ""; }; CAD2E7A32449574E00113D76 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -109,6 +113,10 @@ isa = PBXGroup; children = ( CA8FB5F8256E0F9400469DA5 /* README.md */, + CABFA9D42592EF6300380FEE /* DECISIONS.md */, + CABFA9A02592EAF500380FEE /* R&PLogo.png */, + CABFA9A32592ED5700380FEE /* Apple.paw */, + CABFA9A12592EAFB00380FEE /* LICENSE */, CA8FB61C256E115700469DA5 /* .github */, CA538A0F255A4F3300E64DD7 /* XcodesKit */, CA538A0C255A4F1A00E64DD7 /* AppleAPI */,