package Ġcom . pr 0 gram m . app . ui . fragments Ċ Ċ import Ġandroid . annotation . Suppress Lint Ċ import Ġandroid . view . MenuItem Ċ import Ġandroid . view . View Ċ import Ġandroid . view . ViewGroup Ċ import Ġandroid . widget . ImageView Ċ import Ġandroid . widget . TextView Ċ import Ġandroidx . appcompat . widget . PopupMenu Ċ import Ġandroidx . core . view . View Compat Ċ import Ġandroidx . recyclerview . widget . RecyclerView Ċ import Ġcom . pr 0 gram m . app . Duration Ċ import Ġcom . pr 0 gram m . app . Instant Ċ import Ġcom . pr 0 gram m . app . Logger Ċ import Ġcom . pr 0 gram m . app . R Ċ import Ġcom . pr 0 gram m . app . api . pr 0 gram m . Api Ċ import Ġcom . pr 0 gram m . app . orm . Vote Ċ import Ġcom . pr 0 gram m . app . services . Theme Helper Ċ import Ġcom . pr 0 gram m . app . services . UserService Ċ import Ġcom . pr 0 gram m . app . services . config . Config Service Ċ import Ġcom . pr 0 gram m . app . ui . dialogs . ignore Error Ċ import Ġcom . pr 0 gram m . app . ui . views . Comment Score Ċ import Ġcom . pr 0 gram m . app . ui . views . Comment Spacer View Ċ import Ġcom . pr 0 gram m . app . ui . views . Sender Info View Ċ import Ġcom . pr 0 gram m . app . ui . views . Vote View Ċ import Ġcom . pr 0 gram m . app . util .* Ċ import Ġcom . pr 0 gram m . app . util . di . injector Ċ import Ġrx . Observable Ċ import Ġrx . subjects . Behavior Subject Ċ import Ġkotlin . math . absolute Value Ċ import Ġkotlin . math . sign Ċ import Ġkotlin . properties . Observable Property Ċ import Ġkotlin . reflect . K Property Ċ Ċ /** Ċ Ġ*/ Ċ abstract Ġclass ĠComment Tree Helper Ġ: ĠComment View . Listener Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlogger Ġ= ĠLogger (" Comment Tree Helper ") ĊĊĠĠĠ Ġprivate Ġvar Ġstate : ĠComment Tree . Input Ġby ĠState Property () ĊĠĠĠ Ġprivate Ġvar Ġstate Update Sync Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġval Ġsubject Ġ= ĠBehavior Subject . create < List < Comment Tree . Item >>( listOf ()) ĊĠĠĠ Ġval Ġitems Observable Ġ= Ġsubject Ġas ĠObservable < List < Comment Tree . Item >> ĊĊĠĠĠ Ġ// Ġupdate Ġthe Ġcurrently Ġselected Ġcomment ĊĠĠĠ Ġfun Ġselect Comment ( id : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( state . selected Comment Id Ġ!= Ġid ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= Ġstate . copy ( selected Comment Id Ġ= Ġid ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġuser Is Admin ( admin : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( state . isAdmin Ġ!= Ġadmin ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= Ġstate . copy ( isAdmin Ġ= Ġadmin ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġcollapse Comment ( comment : ĠApi . Comment ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstate Ġ= Ġstate . copy ( collapsed Ġ= Ġstate . collapsed Ġ+ Ġcomment . id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġexpand Comment ( comment : ĠApi . Comment ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstate Ġ= Ġstate . copy ( collapsed Ġ= Ġstate . collapsed Ġ- Ġcomment . id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate Votes ( votes : ĠLong Sparse Array < Vote >) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcurrent Votes Ġ= Ġvotes . clone () ĊĊĠĠĠĠĠĠĠ Ġ// Ġstart Ġwith Ġthe Ġcurrent Ġvotes Ġand Ġreset Ġthe Ġexisting Ġbase Ġvotes ĊĠĠĠĠĠĠĠ Ġval Ġbase Votes Ġ= Ġvotes . clone () ĊĠĠĠĠĠĠĠ Ġbase Votes . put All ( state . base Votes ) ĊĊĠĠĠĠĠĠĠ Ġstate Ġ= Ġstate . copy ( base Votes Ġ= Ġbase Votes , Ġcurrent Votes Ġ= Ġcurrent Votes ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate Comments ( comments : ĠList < Api . Comment >, Ġsynchronous : ĠBoolean Ġ= Ġfalse , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextra Changes : Ġ( Comment Tree . Input ) Ġ-> ĠComment Tree . Input ) Ġ{ ĊĊĊĠĠĠĠĠĠĠ Ġstate Update Sync Ġ= Ġsynchronous ĊĠĠĠĠĠĠĠ Ġstate Ġ= Ġextra Changes ( state . copy ( all Comments Ġ= Ġcomments . toList ())) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Visible Comments () Ġ{ ĊĠĠĠĠĠĠĠ Ġcheck MainThread () ĊĊĠĠĠĠĠĠĠ Ġval Ġtarget State Ġ= Ġstate ĊĊĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" Will Ġrun Ġan Ġupdate Ġfor Ġcurrent Ġstate Ġ${ System . identity HashCode ( target State )} Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" (${ target State . all Comments . size } Ġcomments , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" selected =${ target State . selected Comment Id })" ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġrun This Update Async Ġ= Ġ! state Update Sync Ġ&& Ġ! target State . all Comments . isEmpty () ĊĠĠĠĠĠĠĠ Ġstate Update Sync Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ ĠObservable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from Callable Ġ{ ĠComment Tree ( target State ). visible Comments Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. ignore Error () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. with If ( run This Update Async ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ Ġ" Running Ġupdate Ġin Ġbackground " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsubscribe On Background (). observe On MainThread () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe Ġ{ Ġvisible Comments Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" About Ġto Ġset Ġstate Ġ${ System . identity HashCode ( target State )} Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"( expected =${ System . identity HashCode ( state )}, Ġok =${ target State Ġ=== Ġstate })" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġverify Ġthat Ġwe Ġstill Ġgot Ġthe Ġright Ġstate ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( state Ġ=== Ġtarget State ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsubject . onNext ( visible Comments ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ Ġ" List Ġof Ġcomments Ġalready Ġstale ." Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġinner Ġclass ĠState Property Ġ: ĠObservable Property < Comment Tree . Input >( Comment Tree . Input ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġbefore Change ( property : ĠK Property <* >, ĠoldValue : ĠComment Tree . Input , ĠnewValue : ĠComment Tree . Input ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġonly Ġaccept Ġchange Ġif Ġsomething Ġreally Ġdid Ġchange . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠoldValue Ġ!= ĠnewValue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġafter Change ( property : ĠK Property <* >, ĠoldValue : ĠComment Tree . Input , ĠnewValue : ĠComment Tree . Input ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Visible Comments () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ class ĠComment View ( val Ġparent : ĠViewGroup , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġaction Listener : ĠListener ) Ġ: ĠRecyclerView . ViewHolder ( inflate Comment View Layout ( parent )) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġmax Levels Ġ= ĠConfig Service . get ( item View . context ). comments Max Levels ĊĊĠĠĠ Ġprivate Ġval Ġid Ġ= ĠLong Value Holder ( 0 L ) ĊĊĠĠĠ Ġprivate Ġval Ġvote : ĠV ote View Ġ= ĠitemView . find ( R . id . v oting ) ĊĠĠĠ Ġprivate Ġval Ġreply : ĠImageView Ġ= ĠitemView . find ( R . id . action _ reply ) ĊĠĠĠ Ġprivate Ġval Ġcontent : ĠTextView Ġ= ĠitemView . find ( R . id . comment ) ĊĠĠĠ Ġprivate Ġval Ġsender Info : ĠSender Info View Ġ= ĠitemView . find ( R . id . sender _ info ) ĊĊĠĠĠ Ġprivate Ġval Ġmore : ĠView Ġ= ĠitemView . find ( R . id . action _ more ) ĊĠĠĠ Ġprivate Ġval Ġfav : ĠImageView Ġ= ĠitemView . find ( R . id . action _ k fav ) ĊĠĠĠ Ġprivate Ġval Ġexpand : ĠTextView Ġ= ĠitemView . find ( R . id . action _ expand ) ĊĊĠĠĠ Ġprivate Ġval Ġcomment View Ġ= ĠitemView Ġas ĠComment Spacer View ĊĊĠĠĠ Ġ@ Suppress Lint (" SetText I 1 8 n ") ĊĠĠĠ Ġfun Ġset ( item : ĠComment Tree . Item ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcomment Ġ= Ġitem . comment ĊĠĠĠĠĠĠĠ Ġval Ġcontext Ġ= ĠitemView . context ĊĊĠĠĠĠĠĠĠ Ġ// Ġskip Ġanimations Ġif Ġthis Ġ Ġcomment Ġchanged ĊĠĠĠĠĠĠĠ Ġval Ġchanged Ġ= Ġid . update ( comment . id ) ĊĊĠĠĠĠĠĠĠ Ġcomment View . depth Ġ= Ġitem . depth ĊĠĠĠĠĠĠĠ Ġcomment View . spac ings Ġ= Ġitem . spac ings ĊĊĠĠĠĠĠĠĠ Ġreply . visible Ġ= Ġitem . depth Ġ< Ġmax Levels ĊĊĠĠĠĠĠĠĠ Ġsender Info . set Sender Name ( comment . name , Ġcomment . mark ) ĊĠĠĠĠĠĠĠ Ġsender Info . setOn Sender Clicked Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaction Listener . on Comment Author Clicked ( comment ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġshow Ġthe Ġpoints ĊĠĠĠĠĠĠĠ Ġval Ġscore Visible Threshold Ġ= ĠInstant . now () Ġ- ĠDuration . hours ( 1 ) ĊĠĠĠĠĠĠĠ Ġif Ġ( item . points Visible Ġ|| Ġcomment . created . is Before ( score Visible Threshold )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsender Info . set Points ( item . current Score ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsender Info . set Points Unknown () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġand Ġthe Ġdate Ġof Ġthe Ġpost ĊĠĠĠĠĠĠĠ Ġsender Info . setDate ( comment . created ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġenable Ġor Ġdisable Ġthe Ġbadge ĊĠĠĠĠĠĠĠ Ġsender Info . set Badge Op Visible ( item . has Op Badge ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġand Ġregister Ġa Ġvote Ġhandler ĊĠĠĠĠĠĠĠ Ġvote . set Vote State ( item . vote , Ġanimate Ġ= Ġ! changed ) ĊĠĠĠĠĠĠĠ Ġvote . on Vote Ġ= Ġ{ Ġvote Ġ-> Ġaction Listener . on Comment Vote Clicked ( item . comment , Ġvote ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġset Ġalpha Ġfor Ġthe Ġsub Ġviews . Ġsad ly , Ġsetting Ġalpha Ġon Ġview . item View Ġis Ġnot Ġworking ĊĠĠĠĠĠĠĠ Ġcontent . alpha Ġ= Ġif Ġ( item . vote Ġ=== ĠV ote . DOWN ) Ġ 0 . 5 f Ġelse Ġ 1 f ĊĠĠĠĠĠĠĠ Ġsender Info . alpha Ġ= Ġif Ġ( item . vote Ġ=== ĠV ote . DOWN ) Ġ 0 . 5 f Ġelse Ġ 1 f ĊĊĠĠĠĠĠĠĠ Ġreply . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaction Listener . on Reply Clicked ( comment ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( item . selected Comment ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcolor Ġ= Ġcontext . getColor Compat ( R . color . selected _ comment _ background ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠitemView . set BackgroundColor ( color ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠView Compat . setBackground ( item View , Ġnull ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfav . let Ġ{ Ġfav Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Favorite Ġ= Ġitem . vote Ġ== ĠV ote . FA V OR ITE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Vote Ġ= Ġif Ġ( is Favorite ) ĠV ote . UP Ġelse ĠV ote . FA V OR ITE ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Favorite ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcolor Ġ= Ġcontext . getColor Compat ( Theme Helper . accent Color ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfav . setColor Filter ( color ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfav . setImage Resource ( R . drawable . ic _ vote _ fav ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcolor Ġ= Ġcontext . getColor Compat ( R . color . grey _ 7 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfav . setColor Filter ( color ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfav . setImage Resource ( R . drawable . ic _ vote _ fav _ outline ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfav . visible Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfav . setOnClickListener Ġ{ Ġaction Listener . on Comment Vote Clicked ( item . comment , Ġnew Vote ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( item . is Collapsed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmore . visible Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpand . visible Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpand . text Ġ= Ġ" +" Ġ+ Ġitem . hidden Count ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpand . setOnClickListener Ġ{ Ġaction Listener . expand Comment ( comment ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpand . visible Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġmore . visible Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmore . setOnClickListener Ġ{ Ġview Ġ-> Ġshow Comment Menu ( view , Ġitem ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠLink ify . link ify Clean ( this . content , Ġcomment . content , Ġaction Listener ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Comment Menu ( view : ĠView , Ġentry : ĠComment Tree . Item ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠuserService Ġ= Ġview . context . injector . instance < UserService >() ĊĊĠĠĠĠĠĠĠ Ġval Ġpopup Ġ= ĠPopup Menu ( view . context , Ġview ) ĊĠĠĠĠĠĠĠ Ġpopup . inflate ( R . menu . menu _ comment ) ĊĊĠĠĠĠĠĠĠ Ġpopup . menu . find Item ( R . id . action _ delete _ comment )?. let Ġ{ Ġitem Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġitem . isVisible Ġ= ĠuserService . user Is Admin ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġpopup . menu . find Item ( R . id . action _ block _ user )?. let Ġ{ Ġitem Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġitem . isVisible Ġ= ĠuserService . user Is Admin ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġpopup . menu . find Item ( R . id . action _ collapse )?. let Ġ{ Ġitem Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġitem . isVisible Ġ= Ġentry . can Collapse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġpopup . setOn MenuItem ClickListener Ġ{ Ġitem Ġ-> Ġon MenuItem Clicked ( item , Ġentry ) Ġ} ĊĠĠĠĠĠĠĠ Ġpopup . show () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġon MenuItem Clicked ( item : ĠMenuItem , Ġentry : ĠComment Tree . Item ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġl Ġ= Ġaction Listener ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( item . itemId ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ copy _ link Ġ-> Ġl . on Copy Comment Link ( entry . comment ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ delete _ comment Ġ-> Ġl . onDelete Comment Clicked ( entry . comment ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ block _ user Ġ-> Ġl . on Block User Clicked ( entry . comment ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ collapse Ġ-> Ġl . collapse Comment ( entry . comment ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . id . action _ report Ġ-> Ġl . on Report Comment Clicked ( entry . comment ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinterface ĠListener Ġ: ĠLink ify . Callback Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġon Comment Vote Clicked ( comment : ĠApi . Comment , Ġvote : ĠV ote ): ĠBoolean ĊĊĠĠĠĠĠĠĠ Ġfun Ġon Reply Clicked ( comment : ĠApi . Comment ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġon Comment Author Clicked ( comment : ĠApi . Comment ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġon Copy Comment Link ( comment : ĠApi . Comment ) ĊĊĠĠĠĠĠĠĠ Ġfun ĠonDelete Comment Clicked ( comment : ĠApi . Comment ): ĠBoolean ĊĊĠĠĠĠĠĠĠ Ġfun Ġon Block User Clicked ( comment : ĠApi . Comment ): ĠBoolean ĊĊĠĠĠĠĠĠĠ Ġfun Ġon Report Comment Clicked ( comment : ĠApi . Comment ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġcollapse Comment ( comment : ĠApi . Comment ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġexpand Comment ( comment : ĠApi . Comment ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġinf late Comment View Layout ( parent : ĠViewGroup ): ĠComment Spacer View Ġ{ ĊĠĠĠ Ġreturn Ġparent . layout Inflater . inflate ( R . layout . comment _ layout , Ġparent , Ġfalse ) Ġas ĠComment Spacer View Ċ } Ċ Ċ class ĠComment Tree ( val Ġstate : ĠInput ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġby Id Ġ= Ġstate . all Comments . associate By To ( hash Map Of ()) Ġ{ Ġit . id Ġ} ĊĠĠĠ Ġprivate Ġval Ġby Parent Ġ= Ġstate . all Comments . groupBy To ( hash Map Of ()) Ġ{ Ġit . parent Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġdepth Cache Ġ= Ġmutable Map Of < Long , ĠInt >() ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ" Fl att ens " Ġa Ġlist Ġof Ġh ierarchical Ġcomments Ġto Ġa Ġsorted Ġlist Ġof Ġcomments . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġlinear ized Comments : ĠList < Api . Comment > Ġ= Ġrun Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġbring Ġop Ġcomments Ġto Ġtop , Ġthen Ġorder Ġby Ġconfidence . ĊĠĠĠĠĠĠĠ Ġval Ġordering Ġ= Ġcompare By < Api . Comment > Ġ{ Ġit . name Ġ== Ġstate . op Ġ}. then By Ġ{ Ġit . confidence Ġ} ĊĠĠĠĠĠĠĠ Ġby Parent . values . forEach Ġ{ Ġchildren Ġ-> Ġchildren . sort With ( ordering ) Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġmutable ListOf < Api . Comment >(). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstack Ġ= Ġby Parent [ 0 ]?. to Mutable List () Ġ?: Ġreturn @ apply ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( stack . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġget Ġnext Ġelement ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomment Ġ= Ġstack . remove At ( stack . last Index ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( comment . id Ġ! in Ġstate . collapsed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġand Ġadd Ġall Ġchildren Ġto Ġstack Ġif Ġthe Ġelement Ġitself Ġis Ġnot Ġcollapsed ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġby Parent [ comment . id ]?. let Ġ{ Ġstack . addAll ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġalso Ġadd Ġelement Ġto Ġresult ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd ( comment ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġvisible Comments : ĠList < Item > Ġ= Ġrun Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdepth s Ġ= ĠInt Array ( linear ized Comments . size ) ĊĠĠĠĠĠĠĠ Ġval Ġsp ac ings Ġ= ĠLong Array ( linear ized Comments . size ) ĊĊĠĠĠĠĠĠĠ Ġfor Ġ(( idx , Ġcomment ) Ġin Ġlinear ized Comments . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdepth Ġ= Ġdepth Of ( comment ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcache Ġdepth s Ġby Ġindex Ġso Ġwe Ġcan Ġeasily Ġscan Ġback Ġlater ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdepth s [ idx ] Ġ= Ġdepth ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthe Ġbit Ġwe Ġwant Ġto Ġset Ġfor Ġthis Ġcomment ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbit Ġ= Ġ 1 L Ġshl Ġdepth ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġset Ġbit Ġfor Ġthe Ġcurrent Ġcomment ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsp ac ings [ idx ] Ġ= Ġsp ac ings [ idx ] Ġor Ġbit ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġscan Ġback Ġuntil Ġwe Ġfind Ġa Ġcomment Ġwith Ġthe Ġsame Ġdepth , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġor Ġthe Ġparent Ġcomment ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( offset Ġin Ġ( 1 .. idx )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( depth s [ idx Ġ- Ġoffset ] Ġ<= Ġdepth ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsp ac ings [ idx Ġ- Ġoffset ] Ġ= Ġsp ac ings [ idx Ġ- Ġoffset ] Ġor Ġbit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlinear ized Comments . map Indexed Ġ{ Ġidx , Ġcomment Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvote Ġ= Ġcurrent Vote ( comment ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Collapsed Ġ= Ġcomment . id Ġin Ġstate . collapsed ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ map Indexed ĠItem ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomment Ġ= Ġcomment , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvote Ġ= Ġvote , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdepth Ġ= Ġdepth s [ idx ], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsp ac ings Ġ= Ġsp ac ings [ idx ], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Children Ġ= Ġcomment . id Ġin Ġby Parent , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Score Ġ= Ġcomment Score ( comment , Ġvote ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Op Badge Ġ= Ġstate . op Ġ== Ġcomment . name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhidden Count Ġ= Ġif Ġ( is Collapsed ) Ġcount Sub Tree Comments ( comment ) Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpoints Visible Ġ= Ġstate . isAdmin Ġ|| Ġstate . self Ġ== Ġcomment . name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselected Comment Ġ= Ġstate . selected Comment Id Ġ== Ġcomment . id ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcurrent Vote ( comment : ĠApi . Comment ): ĠV ote Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġstate . current Votes [ comment . id ] Ġ?: ĠV ote . NE UT R AL ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġbase Vote ( comment : ĠApi . Comment ): ĠV ote Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġstate . base Votes . get ( comment . id ) Ġ?: ĠV ote . NE UT R AL ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcomment Score ( comment : ĠApi . Comment , Ġcurrent Vote : ĠV ote ): ĠComment Score Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdelta Ġ= Ġ( current Vote . vote Value Ġ- Ġbase Vote ( comment ). vote Value ). sign ĊĊĠĠĠĠĠĠĠ Ġreturn ĠComment Score ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomment . up Ġ+ Ġdelta . coerce At Least ( 0 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomment . down Ġ+ Ġdelta . coerce At Most ( 0 ). absolute Value ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcount Sub Tree Comments ( start : ĠApi . Comment ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġcount Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġval Ġqueue Ġ= Ġmutable ListOf ( start ) ĊĠĠĠĠĠĠĠ Ġwhile Ġ( queue . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomment Ġ= Ġqueue . remove At ( queue . last Index ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġby Parent [ comment . id ]?. let Ġ{ Ġchildren Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġqueue . addAll ( children ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcount Ġ+= Ġchildren . size ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcount ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġdepth Of ( comment : ĠApi . Comment ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġdepth Cache . get Or Put ( comment . id ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcurrent Ġ= Ġcomment ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġdepth Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdepth ++ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcheck Ġif Ġparent Ġis Ġalready Ġcached , Ġthen Ġwe 'll Ġtake Ġthe Ġcached Ġvalue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdepth Cache [ current . parent ]?. let Ġ{ Ġdepth Of Parent Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ get Or Put Ġdepth Ġ+ Ġdepth Of Parent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġit Ġis Ġnot , Ġlets Ġmove Ġup Ġthe Ġtree ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Ġ= Ġby Id [ current . parent ] Ġ?: Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ get Or Put Ġdepth ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdata Ġclass ĠInput ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġall Comments : ĠList < Api . Comment > Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent Votes : ĠLong Sparse Array < Vote > Ġ= ĠLong Sparse Array ( initial Capacity Ġ= Ġ 0 ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbase Votes : ĠLong Sparse Array < Vote > Ġ= ĠLong Sparse Array ( initial Capacity Ġ= Ġ 0 ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcollapsed : ĠSet < Long > Ġ= Ġset Of (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġop : ĠString ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġself : ĠString ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Admin : ĠBoolean Ġ= Ġfalse , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġselected Comment Id : ĠLong Ġ= Ġ 0 L ) ĊĊĠĠĠ Ġdata Ġclass ĠItem ( val Ġcomment : ĠApi . Comment , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvote : ĠV ote , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdepth : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsp ac ings : ĠLong , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhas Children : ĠBoolean , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent Score : ĠComment Score , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhas Op Badge : ĠBoolean , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhidden Count : ĠInt ?, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpoints Visible : ĠBoolean , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġselected Comment : ĠBoolean ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġcomment Id : ĠLong Ġget () Ġ= Ġcomment . id ĊĠĠĠĠĠĠĠ Ġval Ġis Collapsed : ĠBoolean Ġget () Ġ= Ġhidden Count Ġ!= Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġcan Collapse : ĠBoolean Ġget () Ġ= Ġhas Children Ġ&& Ġhidden Count Ġ== Ġnull ĊĠĠĠ Ġ} Ċ } ĊĊ