package Ġcom . h ic zp . space engine ers . rem ot ec lient . android . binding Ċ Ċ import Ġandroid . widget . TextView Ċ import Ġandroidx . core . widget . do After TextChanged Ċ import Ġandroidx . lifecycle . Lifecycle Owner Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġandroidx . lifecycle . ViewModel Ċ import Ġandroidx . lifecycle . observe Ċ import Ġcom . h ic zp . space engine ers . rem ot ec lient . android . extension . parent Lifecycle Owner Ċ import Ġkotlin . reflect . K Property Ċ Ċ open Ġclass ĠForm ViewModel Ġ: ĠViewModel () Ġ{ ĊĠĠĠ Ġval Ġform Ġ= ĊĠĠĠĠĠĠĠ ĠLinkedHashMap < String , ĠTrip le < TextView , ĠMutable LiveData < String >, ĠValidator >>() ĊĊĠĠĠ Ġoperator Ġfun Ġget ( fieldName : ĠString ) Ġ= Ġform [ fieldName ]?. second ?. value ĊĊĠĠĠ Ġoperator Ġfun ĠgetValue ( this Ref : ĠAny ?, Ġproperty : ĠK Property <* >) Ġ= Ġget ( property . name ) !! ĊĊĠĠĠ Ġoperator Ġfun Ġset ( fieldName : ĠString , Ġvalue : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġform [ fieldName ]?. second ?. value Ġ= Ġvalue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġobserve ( ĊĠĠĠĠĠĠĠ ĠfieldName : ĠString , ĊĠĠĠĠĠĠĠ Ġowner : ĠLifecycle Owner , ĊĠĠĠĠĠĠĠ ĠonChanged : Ġ( String ) Ġ-> ĠUnit ĊĠĠĠ Ġ) Ġ= Ġform [ fieldName ] !!. second . observe ( owner , ĠonChanged ) ĊĊĠĠĠ Ġfun Ġvalidate () Ġ= Ġform . as Sequence (). map Ġ{ Ġ( fieldName , Ġtriple ) Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġ( textView , Ġlive Data , Ġvalidator ) Ġ= Ġtriple ĊĠĠĠĠĠĠĠ ĠTrip le ( fieldName , ĠtextView , Ġvalidator ( live Data . value Ġ?: Ġ"")) ĊĠĠĠ Ġ}. filter Ġ{ Ġ(_, Ġ_, Ġerror ) Ġ-> ĊĠĠĠĠĠĠĠ Ġerror Ġ!= Ġnull ĊĠĠĠ Ġ}. on Each Ġ{ Ġ(_, ĠtextView , Ġerror ) Ġ-> ĊĠĠĠĠĠĠĠ ĠtextView . error Ġ= Ġerror ĊĠĠĠ Ġ}. toList () ĊĊĠĠĠ Ġfun Ġclear () Ġ= Ġform . clear () Ċ } Ċ Ċ fun Ġ< T Ġ: ĠTextView > ĠT . bind ( ĊĠĠĠ Ġmodel : ĠForm ViewModel , ĊĠĠĠ ĠfieldName : ĠString , ĊĠĠĠ Ġinitial Value : ĠString Ġ= Ġ"", ĊĠĠĠ Ġlifecycle Owner : ĠLifecycle Owner ? Ġ= Ġnull , ĊĠĠĠ Ġreal time Validation : ĠBoolean Ġ= Ġfalse , ĊĠĠĠ Ġvalidator : ĠValidator Ġ= Ġ{ Ġnull Ġ} Ċ ) Ġ= Ġapply Ġ{ ĊĠĠĠ Ġval Ġsaved Record Ġ= Ġmodel . form [ fieldName ] ĊĠĠĠ Ġval Ġlive Data Ġ= Ġif Ġ( saved Record Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ ĠMutable LiveData ( initial Value ) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ ĠMutable LiveData ( saved Record . second . value ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġmodel . form [ fieldName ] Ġ= ĠTrip le ( ĊĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠ Ġlive Data , ĊĠĠĠĠĠĠĠ Ġvalidator ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġvar Ġinit Do Ġ= Ġtrue ĊĠĠĠ Ġvar Ġobserve Do Ġ= Ġfalse ĊĠĠĠ Ġvar Ġlistener Do Ġ= Ġfalse ĊĠĠĠ Ġ( lifecycle Owner Ġ?: Ġparent Lifecycle Owner )?. let Ġ{ Ġactual Lifecycle Owner Ġ-> ĊĠĠĠĠĠĠĠ Ġlive Data . observe ( actual Lifecycle Owner ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( init Do ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Text Keep State ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinit Do Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ observe ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! listener Do ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġobserve Do Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Text Keep State ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlistener Do Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġdo After TextChanged Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( init Do ) Ġreturn @ do After TextChanged ĊĠĠĠĠĠĠĠ Ġif Ġ(! observe Do ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlistener Do Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= Ġit . toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( realtime Validation ) Ġerror Ġ= Ġvalidator ( value ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlive Data . value Ġ= Ġvalue ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġobserve Do Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġ< T Ġ: ĠTextView > ĠT . bind ( ĊĠĠĠ Ġmodel : ĠForm ViewModel , ĊĠĠĠ ĠfieldName : ĠString , ĊĠĠĠ Ġinitial Value : ĠString Ġ= Ġ"", ĊĠĠĠ Ġvalidator : ĠValidator Ġ= Ġ{ Ġnull Ġ} Ċ ) Ġ= Ġbind ( model , ĠfieldName , Ġinitial Value , Ġnull , Ġtrue , Ġvalidator ) Ċ