/* Ċ Ġ* ĠCopyright Ġ 2 0 1 9 ĠSquare ĠInc . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ @ file : Suppress (" EXPERIMENT AL _ API _ USAGE ") Ċ Ċ package Ġcom . squareup . workflow Ċ Ċ import Ġcom . squareup . workflow . Worker . Output Or Finished Ċ import Ġcom . squareup . workflow . Worker . Output Or Finished . Finished Ċ import Ġcom . squareup . workflow . Worker . Output Or Finished . Output Ċ import Ġcom . squareup . workflow . Workflow Action . Companion . no Action Ċ Ċ /** Ċ Ġ* ĠFac ilities Ġfor Ġa Ġ[ Workflow ] Ġto Ġinteract Ġwith Ġother Ġ[ Workflow ] s Ġand Ġthe Ġoutside Ġworld Ġfrom Ġinside Ċ Ġ* Ġa Ġ` render ` Ġfunction . Ċ Ġ* Ċ Ġ* Ġ## ĠHandling ĠEvents Ċ Ġ* Ċ Ġ* ĠSee Ġ[ on Event ]. Ċ Ġ* Ċ Ġ* Ġ## ĠPerform ing ĠAs ynchronous ĠWork Ċ Ġ* Ċ Ġ* ĠSee Ġ[ on Worker Output ], Ġ[ on Worker Output Or Finished ], Ġand Ġ[ running Worker ]. Ċ Ġ* Ċ Ġ* Ġ## ĠComp osing ĠChildren Ċ Ġ* Ċ Ġ* ĠSee Ġ[ render Child ]. Ċ Ġ*/ Ċ interface ĠRender Context < State T , Ġin ĠOutput T Ġ: ĠAny > Ġ{ ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠGiven Ġa Ġfunction Ġthat Ġtakes Ġan Ġ[ event ][ Event T ] Ġand Ġcan Ġmutate Ġthe Ġstate Ġor Ġemit Ġan Ġoutput , ĊĠĠ Ġ* Ġreturns Ġa Ġfunction Ġthat Ġwill Ġperform Ġthat Ġworkflow Ġupdate Ġwhen Ġcalled Ġwith Ġan Ġevent . ĊĠĠ Ġ* ĠThe Ġreturned Ġfunction Ġis Ġvalid Ġuntil Ġthe Ġnext Ġrender Ġpass . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠFor Ġexample , Ġif Ġyou Ġhave Ġa Ġrendering Ġtype Ġof Ġ` Screen `: ĊĠĠ Ġ* ĊĠĠ Ġ* ĠĠĠ Ġdata Ġclass ĠScreen ( ĊĠĠ Ġ* ĠĠĠĠĠ Ġval Ġlabel : ĠString , ĊĠĠ Ġ* ĠĠĠĠĠ Ġval ĠonClick : Ġ() Ġ-> ĠUnit ĊĠĠ Ġ* ĠĠĠ Ġ) ĊĠĠ Ġ* ĊĠĠ Ġ* ĠThen , Ġfrom Ġyour Ġ` render ` Ġmethod , Ġconstruct Ġthe Ġscreen Ġlike Ġthis : ĊĠĠ Ġ* ĊĠĠ Ġ* ĠĠĠ Ġreturn ĠScreen ( ĊĠĠ Ġ* ĠĠĠĠĠ Ġbutton 1 Label Ġ= Ġ" Hello ", ĊĠĠ Ġ* ĠĠĠĠĠ Ġbutton 2 Label Ġ= Ġ" World ", ĊĠĠ Ġ* ĠĠĠĠĠ ĠonClick Ġ= Ġcontext . on Event Ġ{ Ġbutton Index Ġ-> ĊĠĠ Ġ* ĠĠĠĠĠĠĠ Ġemit Output (" Button Ġ$ button Index Ġclicked !") ĊĠĠ Ġ* ĠĠĠĠĠ Ġ} ĊĠĠ Ġ* ĠĠĠ Ġ) ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ## ĠE quivalence Ġ& ĠTesting ĊĠĠ Ġ* ĊĠĠ Ġ* ĠIt Ġis Ġcommon Ġin Ġunit Ġtests Ġto Ġget Ġa Ġrendering Ġfrom Ġa Ġworkflow , Ġthen Ġ( since Ġrender ings Ġshould Ġbe ĊĠĠ Ġ* Ġvalue Ġtypes ) Ġcreate Ġthe Ġexpected Ġrendering Ġinstance Ġand Ġcompare Ġthem . ĠHowever , Ġwhen Ġcomparing ĊĠĠ Ġ* Ġrender ings Ġthere Ġis Ġno Ġmeaningful Ġway Ġto Ġcompare Ġevent Ġhandlers Ġ( other Ġthan Ġa Ġnull Ġcheck Ġif ĊĠĠ Ġ* Ġthey 're Ġnullable ), Ġand Ġso Ġtwo Ġrender ings Ġthat Ġare Ġidentical Ġbut Ġhave Ġdifferent Ġevent Ġhandler ĊĠĠ Ġ* Ġfunctions Ġshould Ġstill Ġbe Ġconsidered Ġequal . ĠIn Ġorder Ġto Ġsupport Ġthis Ġpattern , Ġthe Ġfunctions ĊĠĠ Ġ* Ġreturned Ġby Ġthis Ġmethod Ġare Ġall Ġconsidered Ġequal : Ġ` foo Ġ== Ġbar ` Ġwhenever Ġ` foo ` Ġand Ġ` bar ` Ġare ĊĠĠ Ġ* Ġvalues Ġreturned Ġby Ġthis Ġmethod . ĠMore Ġprecise ly , Ġthis Ġfunction Ġreturns Ġinstances Ġof ĊĠĠ Ġ* Ġ[ EventHandler ], Ġand Ġall Ġ[ EventHandler ] Ġinstances Ġare Ġconsidered Ġequal . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠHowever , Ġsince Ġevent Ġhandling Ġfunctions Ġare Ġalways Ġvalid Ġonly Ġfor Ġthe Ġrendering Ġfor Ġwhich Ġthey ĊĠĠ Ġ* Ġwere Ġcreated , Ġthis Ġmeans Ġthat Ġyou Ġcan 't Ġde dup Ġevent Ġhandlers Ġin Ġproduction Ġ( e . g . Ġwith Ġsomething ĊĠĠ Ġ* Ġlike ĠRx Java 's Ġ` distinct Until Changed `). ĠEvent Ġhandlers Ġmust Ġ_ always _ Ġbe Ġupdated , Ġand Ġif Ġyou ĊĠĠ Ġ* Ġneed Ġto Ġde - dup Ġother Ġview Ġdata , Ġyou Ġmust Ġdo Ġit Ġat Ġa Ġmore Ġgran ular Ġlevel . ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ@ param Ġhandler ĠA Ġfunction Ġthat Ġreturns Ġthe Ġ[ Workflow Action ] Ġto Ġperform Ġwhen Ġthe Ġevent Ġhandler ĊĠĠ Ġ* Ġis Ġinvoked . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġ< Event T Ġ: ĠAny > Ġon Event ( ĊĠĠĠ Ġhandler : Ġ( Event T ) Ġ-> ĠWorkflow Action < State T , ĠOutput T > ĊĠ Ġ): Ġ( Event T ) Ġ-> ĠUnit ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠEns ures Ġ[ child ] Ġis Ġrunning Ġas Ġa Ġchild Ġof Ġthis Ġworkflow , Ġand Ġreturns Ġthe Ġresult Ġof Ġits ĊĠĠ Ġ* Ġ` render ` Ġmethod . ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ** Never Ġcall Ġ[ State ful Workflow . render ] Ġor Ġ[ State less Workflow . render ] Ġdirectly , Ġalways Ġdo Ġit ĊĠĠ Ġ* Ġthrough Ġthis Ġcontext Ġmethod .** ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ 1 . ĠIf Ġthe Ġchild Ġ_ was n 't _ Ġalready Ġrunning , Ġit Ġwill Ġbe Ġstarted Ġeither Ġfrom ĊĠĠ Ġ* ĠĠĠ Ġ[ initialState ][ Workflow . initialState ] Ġor Ġits Ġsnapshot . ĊĠĠ Ġ* Ġ 2 . ĠIf Ġthe Ġchild Ġ_ was _ Ġalready Ġrunning , ĠThe Ġworkflow 's ĊĠĠ Ġ* ĠĠĠ Ġ[ on Input Changed ][ State ful Workflow . on Input Changed ] Ġmethod Ġis Ġinvoked Ġwith Ġthe Ġprevious Ġinput ĊĠĠ Ġ* ĠĠĠ Ġand Ġthis Ġone . ĊĠĠ Ġ* Ġ 3 . ĠThe Ġchild 's Ġ` render ` Ġmethod Ġis Ġinvoked Ġwith Ġ` input ` Ġand Ġthe Ġchild 's Ġstate . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠAfter Ġthis Ġmethod Ġreturns , Ġif Ġsomething Ġhappens Ġthat Ġtrigger 's Ġone Ġof Ġ` child `' s Ġhandlers , Ġand ĊĠĠ Ġ* Ġthat Ġhandler Ġemits Ġan Ġoutput , Ġthe Ġfunction Ġpassed Ġas Ġ[ handler ] Ġwill Ġbe Ġinvoked Ġwith Ġthat ĊĠĠ Ġ* Ġoutput . ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ@ param Ġkey ĠAn Ġoptional Ġstring Ġkey Ġthat Ġis Ġused Ġto Ġdistinguish Ġbetween Ġworkflows Ġof Ġthe Ġsame ĊĠĠ Ġ* Ġtype . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġ< Child Input T , ĠChild Output T Ġ: ĠAny , ĠChild Rendering T > Ġrender Child ( ĊĠĠĠ Ġchild : ĠWorkflow < Child Input T , ĠChild Output T , ĠChild Rendering T >, ĊĠĠĠ Ġinput : ĠChild Input T , ĊĠĠĠ Ġkey : ĠString Ġ= Ġ"", ĊĠĠĠ Ġhandler : Ġ( Child Output T ) Ġ-> ĠWorkflow Action < State T , ĠOutput T > ĊĠ Ġ): ĠChild Rendering T ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠEns ures Ġ[ worker ] Ġis Ġrunning . ĠWhen Ġthe Ġ[ Worker ] Ġemits Ġan Ġoutput Ġor Ġfinishes , Ġ[ handler ] Ġis Ġcalled ĊĠĠ Ġ* Ġto Ġdetermine Ġthe Ġ[ Workflow Action ] Ġto Ġtake . ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ@ param Ġkey ĠAn Ġoptional Ġstring Ġkey Ġthat Ġis Ġused Ġto Ġdistinguish Ġbetween Ġidentical Ġ[ Worker ] s . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġ< T > Ġon Worker Output Or Finished ( ĊĠĠĠ Ġworker : ĠWorker < T >, ĊĠĠĠ Ġkey : ĠString Ġ= Ġ"", ĊĠĠĠ Ġhandler : Ġ( Output Or Finished < T >) Ġ-> ĠWorkflow Action < State T , ĠOutput T > ĊĠ Ġ) Ċ } Ċ Ċ /** Ċ Ġ* ĠConvenience Ġalias Ġof Ġ[ Render Context . render Child ] Ġfor Ġworkflows Ġthat Ġdon 't Ġtake Ġinput . Ċ Ġ*/ Ċ fun Ġ< State T , ĠOutput T Ġ: ĠAny , ĠChild Output T Ġ: ĠAny , ĠChild Rendering T > ĊĠĠĠ ĠRender Context < State T , ĠOutput T >. render Child ( Ċ // ĠInt ellij Ġref uses Ġto Ġformat Ġthis Ġparameter Ġlist Ġcorrectly Ġbecause Ġof Ġthe Ġweird Ġline Ġbreak , Ċ // Ġand Ġde te kt Ġwill Ġcompl ain Ġabout Ġit . Ċ // Ġ@ formatter : off ĊĠĠĠĠĠ Ġchild : ĠWorkflow < Unit , ĠChild Output T , ĠChild Rendering T >, ĊĠĠĠĠĠ Ġkey : ĠString Ġ= Ġ"", ĊĠĠĠĠĠ Ġhandler : Ġ( Child Output T ) Ġ-> ĠWorkflow Action < State T , ĠOutput T > ĊĠĠĠ Ġ): ĠChild Rendering T Ġ= Ġrender Child ( child , ĠUnit , Ġkey , Ġhandler ) Ċ // Ġ@ formatter : on Ċ Ċ /** Ċ Ġ* ĠConvenience Ġalias Ġof Ġ[ Render Context . render Child ] Ġfor Ġworkflows Ġthat Ġdon 't Ġtake Ġinput Ġor Ġemit Ċ Ġ* Ġoutput . Ċ Ġ*/ Ċ fun Ġ< Input T , ĠState T , ĠOutput T Ġ: ĠAny , ĠChild Rendering T > ĊĠĠĠ ĠRender Context < State T , ĠOutput T >. render Child ( Ċ // ĠInt ellij Ġref uses Ġto Ġformat Ġthis Ġparameter Ġlist Ġcorrectly Ġbecause Ġof Ġthe Ġweird Ġline Ġbreak , Ċ // Ġand Ġde te kt Ġwill Ġcompl ain Ġabout Ġit . Ċ // Ġ@ formatter : off ĊĠĠĠĠĠ Ġchild : ĠWorkflow < Input T , ĠNothing , ĠChild Rendering T >, ĊĠĠĠĠĠ Ġinput : ĠInput T , ĊĠĠĠĠĠ Ġkey : ĠString Ġ= Ġ"" ĊĠĠĠ Ġ): ĠChild Rendering T Ġ= Ġrender Child ( child , Ġinput , Ġkey ) Ġ{ Ġno Action () Ġ} Ċ // Ġ@ formatter : on Ċ Ċ /** Ċ Ġ* ĠConvenience Ġalias Ġof Ġ[ Render Context . render Child ] Ġfor Ġworkflows Ġthat Ġdon 't Ġtake Ġinput Ġor Ġemit Ċ Ġ* Ġoutput . Ċ Ġ*/ Ċ fun Ġ< State T , ĠOutput T Ġ: ĠAny , ĠChild Rendering T > ĊĠĠĠ ĠRender Context < State T , ĠOutput T >. render Child ( Ċ // ĠInt ellij Ġref uses Ġto Ġformat Ġthis Ġparameter Ġlist Ġcorrectly Ġbecause Ġof Ġthe Ġweird Ġline Ġbreak , Ċ // Ġand Ġde te kt Ġwill Ġcompl ain Ġabout Ġit . Ċ // Ġ@ formatter : off ĊĠĠĠĠĠ Ġchild : ĠWorkflow < Unit , ĠNothing , ĠChild Rendering T >, ĊĠĠĠĠĠ Ġkey : ĠString Ġ= Ġ"" ĊĠĠĠ Ġ): ĠChild Rendering T Ġ= Ġrender Child ( child , ĠUnit , Ġkey ) Ġ{ Ġno Action () Ġ} Ċ // Ġ@ formatter : on Ċ Ċ /** Ċ Ġ* ĠEns ures Ġ[ worker ] Ġis Ġrunning . ĠWhen Ġthe Ġ[ Worker ] Ġemits Ġan Ġoutput , Ġ[ handler ] Ġis Ġcalled Ċ Ġ* Ġto Ġdetermine Ġthe Ġ[ Workflow Action ] Ġto Ġtake . ĠWhen Ġthe Ġworker Ġfinishes , Ġnothing Ġhappens Ġ( alth ough Ċ Ġ* Ġanother Ġrender Ġpass Ġmay Ġbe Ġtriggered ). Ċ Ġ* Ċ Ġ* Ġ@ param Ġkey ĠAn Ġoptional Ġstring Ġkey Ġthat Ġis Ġused Ġto Ġdistinguish Ġbetween Ġidentical Ġ[ Worker ] s . Ċ Ġ*/ Ċ fun Ġ< State T , ĠOutput T Ġ: ĠAny , ĠT > ĠRender Context < State T , ĠOutput T >. on Worker Output ( ĊĠ Ġworker : ĠWorker < T >, ĊĠ Ġkey : ĠString Ġ= Ġ"", ĊĠ Ġhandler : Ġ( T ) Ġ-> ĠWorkflow Action < State T , ĠOutput T > Ċ ) Ġ= Ġon Worker Output Or Finished ( worker , Ġkey ) Ġ{ Ġoutput Or Finished Ġ-> ĊĠ Ġwhen Ġ( output Or Finished ) Ġ{ ĊĠĠĠ Ġis ĠOutput Ġ-> Ġhandler ( output Or Finished . value ) ĊĠĠĠ ĠFinished Ġ-> Ġno Action () ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠEns ures Ġa Ġ[ Worker ] Ġthat Ġnever Ġemits Ġanything Ġis Ġrunning . ĠSince Ġ[ worker ] Ġcan 't Ġemit Ġanything , Ċ Ġ* Ġit Ġcan 't Ġtrigger Ġany Ġ[ Workflow Action ] s . Ċ Ġ* Ċ Ġ* Ġ@ param Ġkey ĠAn Ġoptional Ġstring Ġkey Ġthat Ġis Ġused Ġto Ġdistinguish Ġbetween Ġidentical Ġ[ Worker ] s . Ċ Ġ*/ Ċ fun Ġ< State T , ĠOutput T Ġ: ĠAny > ĠRender Context < State T , ĠOutput T >. running Worker ( ĊĠ Ġworker : ĠWorker < Nothing >, ĊĠ Ġkey : ĠString Ġ= Ġ"" Ċ ) Ġ= Ġon Worker Output Or Finished ( worker , Ġkey ) Ġ{ Ġthrow ĠAssertionError (" Worker < Nothing > Ġemitted Ġ$ it ") Ġ} Ċ