package Ġcom . kh me len ko . lab . var is . build details Ċ Ċ import Ġandroid . arch . lifecycle . LiveData Ċ import Ġandroid . arch . lifecycle . Mutable LiveData Ċ import Ġandroid . arch . lifecycle . ViewModel Ċ import Ġcom . kh me len ko . lab . var is . log . Logs Parser Ċ import Ġcom . kh me len ko . lab . var is . network . response . Build Details Ċ import Ġcom . kh me len ko . lab . var is . network . ret rofit . raw . Raw Client Ċ import Ġcom . kh me len ko . lab . var is . network . ret rofit . travis . Tr avis RestClient Ċ import Ġcom . kh me len ko . lab . var is . storage . AppSettings Ċ import Ġcom . kh me len ko . lab . var is . storage . Cache Storage Ċ import Ġcom . kh me len ko . lab . var is . util . StringUtils Ċ import Ġio . reactivex . Single Ċ import Ġio . reactivex . android . schedul ers . Android Schedulers Ċ import Ġio . reactivex . dis pos ables . Composite Disposable Ċ import Ġio . reactivex . schedul ers . Schedulers Ċ import Ġokhttp 3 . MediaType Ċ import Ġokhttp 3 . RequestBody Ċ import Ġretrofit 2 . HttpException Ċ import Ġjava . net . Malformed URLException Ċ import Ġjava . net . URL Ċ Ċ private Ġconst Ġval ĠLOAD _ LOG _ MAX _ AT TEMP T Ġ= Ġ 3 Ċ Ċ /** Ċ Ġ* ĠViewModel Ġfor ĠBuild Details Ċ Ġ* Ċ Ġ* Ġ@ author ĠD my tro ĠK h me len ko Ġ( d . kh me len ko @ gmail . com ) Ċ Ġ*/ Ċ class ĠBuilds Details ViewModel ( private Ġval Ġtravis RestClient : ĠTravis RestClient , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġraw Client : ĠRaw Client , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġcache : ĠCache Storage , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġapp Settings : ĠApp Settings , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġlogs Parser : ĠLogs Parser ) Ġ: ĠViewModel () Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġsubscriptions Ġ= ĠComposite Disposable () ĊĊĠĠĠ Ġprivate Ġvar Ġrepo Slug Ġ= Ġ"" ĊĠĠĠ Ġprivate Ġvar Ġbuild Id : ĠLong Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġjob Id : ĠLong Ġ= Ġ 0 ĊĊĠĠĠ Ġprivate Ġval Ġbuild State Ġ= ĠMutable LiveData < Build Details State >() ĊĊĠĠĠ Ġoverride Ġfun Ġon Cle ared () Ġ{ ĊĠĠĠĠĠĠĠ Ġsubscriptions . clear () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstate (): ĠLive Data < Build Details State > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġbuild State ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStarts Ġloading Ġlog Ġfile ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġjob Id ĠJob ĠID ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġstart Loading Log ( jobId : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . jobId Ġ= Ġjob Id ĊĠĠĠĠĠĠĠ Ġval ĠaccessToken Ġ= Ġapp Settings . accessToken ĊĠĠĠĠĠĠĠ Ġval Ġresponse Single Ġ= Ġif Ġ( StringUtils . isEmpty ( accessToken )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġraw Client . api Service . getLog ( this . jobId . toString ()) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġauth Ġ= ĠString . format (" token Ġ% 1 \$ s ", Ġapp Settings . accessToken ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġraw Client . api Service . getLog ( auth , Ġthis . jobId . toString ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġsubscription Ġ= Ġresponse Single . subscribe On ( Schedulers . io ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġraw Client . getLog Url ( this . jobId ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Resume Next Ġ{ Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġredirect Url : ĠString ? Ġ= Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( throwable Ġis ĠHttp Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġheaders Ġ= Ġthrowable . response (). headers () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( header Ġin Ġheaders . names ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( header Ġ== Ġ" Location ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġredirect Url Ġ= Ġheaders . get ( header ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSingle . just ( redirect Url !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSingle . error ( throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. retry ( LOAD _ LOG _ MAX _ AT TEMP T . to Long ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġraw Client . single String Request ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġresponse Ġ-> Ġlogs Parser . parse Log ( response . blocking Get ()) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe Ġ{ Ġlog , Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( throwable Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpost State ( Build Details State . LogEntry Loaded ( log )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpost State ( Build Details State . LogError ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Error ( throwable . message )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsubscriptions . add ( subscription ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStarts Ġloading Ġdata ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġintent Url ĠIntent ĠURL ĊĠĠĠĠ Ġ* Ġ@ param Ġrepo Slug Ġ ĠRepository Ġslug ĊĠĠĠĠ Ġ* Ġ@ param Ġbuild Id ĠĠ ĠBuild ĠID ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġstart Loading Data ( intent Url : ĠString ?, Ġrepo Slug : ĠString , Ġbuild Id : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . repo Slug Ġ= Ġrepo Slug ĊĠĠĠĠĠĠĠ Ġthis . build Id Ġ= Ġbuild Id ĊĊĠĠĠĠĠĠĠ Ġval Ġbuild Details Single : ĠSingle < Build Details > ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! StringUtils . isEmpty ( intent Url )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Details Single Ġ= Ġraw Client . single Request ( intent Url !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Success Ġ{ Ġresponse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġredirect Url : ĠString ? Ġ= Ġintent Url ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( response . is Redirect ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġredirect Url Ġ= Ġresponse . header (" Location ", Ġ"") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparse Intent Url ( redirect Url ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġtravis RestClient . api Service . get Build ( this . repo Slug , Ġthis . build Id ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Details Single Ġ= Ġtravis RestClient . api Service . get Build ( this . repo Slug , Ġthis . build Id ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġsubscription Ġ= Ġbuild Details Single . subscribe On ( Schedulers . io ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe Ġ{ Ġbuild Details , Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( throwable Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Build Details ( build Details ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Loading Failed ( throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsubscriptions . add ( subscription ) ĊĊĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Loading ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠParses Ġintent ĠURL ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġintent Url ĠIntent ĠURL ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġparse Intent Url ( intent Url : ĠString ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġowner Index Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġval Ġrepo Name Index Ġ= Ġ 2 ĊĠĠĠĠĠĠĠ Ġval Ġbuild Id Index Ġ= Ġ 4 ĊĠĠĠĠĠĠĠ Ġval Ġpath Length Ġ= Ġ 5 ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġurl Ġ= ĠURL ( intent Url ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath Ġ= Ġurl . path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġitems Ġ= Ġpath . split ("/ ". to Regex ()). drop Last While Ġ{ Ġit . isEmpty () Ġ}. to Typed Array () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( items . size Ġ>= Ġpath Length ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepo Slug Ġ= ĠString . format ("% s /% s ", Ġitems [ owner Index ], Ġitems [ repo Name Index ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Id Ġ= Ġitems [ build Id Index ]. to Long () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠMal formed URLException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . printStackTrace () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠNumber FormatException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe . printStackTrace () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRe starts Ġbuild Ġprocess ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġrestart Build () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġempty Body Ġ= ĠRequest Body . create ( MediaType . parse (" application / json "), Ġ"") ĊĠĠĠĠĠĠĠ Ġval Ġsubscription Ġ= Ġtravis RestClient . api Service ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. restart Build ( build Id , Ġempty Body ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Return Ġ{ ĠAny () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġtravis RestClient . api Service . get Build ( repo Slug , Ġbuild Id ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe On ( Schedulers . io ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe Ġ{ Ġbuild Details , Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( throwable Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Build Details ( build Details ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Loading Failed ( throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsubscriptions . add ( subscription ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCancel s Ġbuild Ġprocess ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġcancel Build () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġempty Body Ġ= ĠRequest Body . create ( MediaType . parse (" application / json "), Ġ"") ĊĠĠĠĠĠĠĠ Ġval Ġsubscription Ġ= Ġtravis RestClient . api Service ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. cancel Build ( build Id , Ġempty Body ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Return Ġ{ ĠAny () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġtravis RestClient . api Service . get Build ( repo Slug , Ġbuild Id ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe On ( Schedulers . io ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe Ġ{ Ġbuild Details , Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( throwable Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Build Details ( build Details ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Loading Failed ( throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsubscriptions . add ( subscription ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDefines Ġwhether Ġthe Ġuser Ġcan Ġcontribute Ġto Ġthe Ġrepository Ġor Ġnot ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĠTrue Ġif Ġuser Ġcan Ġcontribute Ġto Ġthe Ġrepository . ĠFalse Ġotherwise ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġcan User Contribut e To Repo (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġcan Contribut e To Repo Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġval Ġuser Repos Ġ= Ġcache . restore Repos () ĊĠĠĠĠĠĠĠ Ġfor Ġ( repo Ġin Ġuser Repos ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( repo Ġ== Ġrepo Slug ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcan Contribut e To Repo Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġcan Contribut e To Repo ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Build Details ( build Details : ĠBuild Details ) Ġ{ ĊĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Build Details Loaded ( build Details )) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( build Details . jobs . size Ġ> Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Build Jobs Loaded ( build Details . jobs )) ĊĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( build Details . jobs . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Build Logs Loaded ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjob Ġ= Ġbuild Details . jobs [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Loading Log ( job . id ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġif Ġuser Ġlogged Ġin , Ġshow Ġadditional Ġactions Ġfor Ġthe Ġrepo ĊĠĠĠĠĠĠĠ Ġval Ġapp Token Ġ= Ġapp Settings . accessToken ĊĠĠĠĠĠĠĠ Ġif Ġ(! StringUtils . isEmpty ( app Token )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Build Additional Actions Available ( build Details )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Loading Failed ( throwable : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠ Ġpost State ( Build Details State . Error ( throwable . message )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġpost State ( state : ĠBuild Details State ) Ġ{ ĊĠĠĠĠĠĠĠ Ġbuild State . value Ġ= Ġstate ĊĠĠĠ Ġ} Ċ } Ċ