package Ġio . case y . mus ik cube . remote . ui . model Ċ Ċ import Ġandroid . support . v 7 . widget . RecyclerView Ċ import Ġandroid . view . Motion Event Ċ import Ġandroid . view . View Ċ import Ġcom . plus cub ed . recycler fast scroll . Recycler Fast Scroller Ċ import Ġio . case y . mus ik cube . remote . websocket . Messages Ċ import Ġio . case y . mus ik cube . remote . websocket . Socket Message Ċ import Ġio . case y . mus ik cube . remote . websocket . WebSocket Service Ċ import Ġorg . json . JSONObject Ċ import Ġjava . util .* Ċ Ċ class ĠTrack List Sl iding Window ( private Ġval Ġre cyclerView : ĠRecyclerView , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġfast Scroller : ĠRe cycler Fast Scroller , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġw ss : ĠWebSocket Service , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġquery Factory : ĠTrack List Sl iding Window . Query Factory ) Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġscroll State Ġ= ĠRecyclerView . SCROLL _ STATE _ IDLE ĊĠĠĠ Ġprivate Ġvar Ġfast Scroller Active Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġquery Offset Ġ= Ġ- 1 ĊĠĠĠ Ġprivate Ġvar Ġquery Limit Ġ= Ġ- 1 ĊĠĠĠ Ġprivate Ġvar Ġinitial Position Ġ= Ġ- 1 ĊĠĠĠ Ġprivate Ġvar Ġwindow Size Ġ= ĠDEFAULT _ WINDOW _ SIZE ĊĠĠĠ Ġprivate Ġvar Ġloaded Listener : ĠOn Metadata Loaded Listener ? Ġ= Ġnull ĊĠĠĠ Ġinternal Ġvar Ġconnected Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġclass ĠCache Entry Ġ{ ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġvalue : ĠJSONObject ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġdirty : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġcache Ġ= Ġobject Ġ: ĠLinkedHashMap < Int , ĠCache Entry >() Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġremove El dest Entry ( el dest : ĠMutable Map . Mutable Entry < Int , ĠCache Entry >): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġsize Ġ>= ĠMAX _ SIZE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinterface ĠOn Metadata Loaded Listener Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġon Metadata Loaded ( offset : ĠInt , Ġcount : ĠInt ) ĊĠĠĠĠĠĠĠ Ġfun Ġon Re loaded ( count : ĠInt ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġabstract Ġclass ĠQuery Factory Ġ{ ĊĠĠĠĠĠĠĠ Ġabstract Ġfun Ġget Re query Message (): ĠSocket Message ? ĊĠĠĠĠĠĠĠ Ġabstract Ġfun Ġget Page Around Message ( offset : ĠInt , Ġlimit : ĠInt ): ĠSocket Message ? ĊĊĠĠĠĠĠĠĠ Ġopen Ġfun Ġconnection Required (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar Ġcount Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġset ( count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfield Ġ= Ġcount ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinvalidate Cache () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcancel Messages () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Adapter Changed () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Metadata Loaded ( 0 , Ġ 0 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġfast Scroller Touch Ġby Ġlazy Ġ{ ĊĠĠĠĠĠĠĠ ĠView . On Touch Listener Ġ{ Ġ_, Ġevent Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( event Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtype Ġ= Ġevent . action Mask ed ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type Ġ== ĠMotion Event . ACTION _ DOWN ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfast Scroller Active Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġif Ġ( type Ġ== ĠMotion Event . ACTION _ UP ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfast Scroller Active Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġre query () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġre query () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġconnection Required Ġ= Ġquery Factory . connection Required () ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! connection Required Ġ|| Ġconnected ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcancel Messages () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġqueried Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġquery Factory . get Re query Message () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( message Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġw ss . send ( message , Ġ_ client ) Ġ{ Ġresponse : ĠSocket Message Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcount Ġ= Ġresponse . getInt Option ( Messages . Key . COUNT , Ġ 0 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( initial Position Ġ!= Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġre cyclerView . scrollTo Position ( initial Position ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinitial Position Ġ= Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġloaded Listener ?. on Re loaded ( count ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġqueried Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! quer ied ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcount Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġloaded Listener ?. on Re loaded ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġpause () Ġ{ ĊĠĠĠĠĠĠĠ Ġconnected Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġw ss . remove Client (_ client ) ĊĠĠĠĠĠĠĠ Ġre cyclerView . remove On Scroll Listener (_ scroll Listener ) ĊĠĠĠĠĠĠĠ Ġfast Scroller . setOn Handle Touch Listener ( null ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġresume () Ġ{ ĊĠĠĠĠĠĠĠ Ġre cyclerView . add On Scroll Listener (_ scroll Listener ) ĊĠĠĠĠĠĠĠ Ġfast Scroller . setOn Handle Touch Listener ( fast Scroller Touch ) ĊĠĠĠĠĠĠĠ Ġw ss . add Client (_ client ) ĊĠĠĠĠĠĠĠ Ġconnected Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġfast Scroller Active Ġ= Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġset Initial Position ( initial Index : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinitial Position Ġ= Ġinitial Index ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġset On Metadata Loaded Listener ( loaded Listener : ĠOn Metadata Loaded Listener ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . loaded Listener Ġ= Ġloaded Listener ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġset Window Size ( window Size : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . window Size Ġ= Ġwindow Size ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Track ( index : ĠInt ): ĠJSONObject ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtrack Ġ= Ġcache [ index ] ĊĊĠĠĠĠĠĠĠ Ġif Ġ( track ?. dirty Ġ?: Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( scroll State Ġ== ĠRecyclerView . SCROLL _ STATE _ IDLE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget Page Around ( index ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrack ?. value ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinvalidate Cache () Ġ{ ĊĠĠĠĠĠĠĠ Ġfor Ġ( entry Ġin Ġcache . values ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . dirty Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcancel Messages () Ġ{ ĊĠĠĠĠĠĠĠ Ġquery Limit Ġ= Ġ- 1 ĊĠĠĠĠĠĠĠ Ġquery Offset Ġ= Ġquery Limit ĊĠĠĠĠĠĠĠ Ġw ss . cancel Messages (_ client ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Page Around ( index : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! connected Ġ|| Ġscrolling ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( index Ġ>= Ġquery Offset Ġ&& Ġindex Ġ<= Ġquery Offset Ġ+ Ġquery Limit ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ Ġ/* Ġalready Ġin Ġflight Ġ*/ ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġoffset Ġ= ĠMath . max ( 0 , Ġindex Ġ- Ġ 1 0 ) Ġ/* Ġsn ag Ġa Ġcouple Ġbefore Ġ*/ ĊĠĠĠĠĠĠĠ Ġval Ġlimit Ġ= Ġwindow Size ĊĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= Ġquery Factory . getPage Around Message ( offset , Ġlimit ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( request Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcancel Messages () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery Offset Ġ= Ġoffset ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery Limit Ġ= Ġlimit ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġw ss . send ( request , Ġ_ client ) Ġ{ Ġresponse : ĠSocket Message Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġquery Limit Ġ= Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġquery Offset Ġ= Ġquery Limit ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġresponse . get JsonArray Option ( Messages . Key . DATA ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Offset Ġ= Ġresponse . getInt Option ( Messages . Key . OFFSET ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( data Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. data . length () Ġ- Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtrack Ġ= Ġdata . opt JSONObject ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( track Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentry Ġ= ĠCache Entry () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . dirty Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . value Ġ= Ġtrack ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcache . put ( response Offset Ġ+ Ġi , Ġentry ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Adapter Changed () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Metadata Loaded ( response Offset , Ġdata . length ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġnotify Adapter Changed () Ġ{ ĊĠĠĠĠĠĠĠ Ġre cyclerView . adapter . notify DataSet Changed () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġnotify Metadata Loaded ( offset : ĠInt , Ġcount : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġloaded Listener ?. on Metadata Loaded ( offset , Ġcount ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġscrolling (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġscroll State Ġ!= ĠRecyclerView . SCROLL _ STATE _ IDLE Ġ|| Ġfast Scroller Active ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġ_ scroll Listener Ġ= Ġobject Ġ: ĠRecyclerView . On Scroll Listener () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Scroll StateChanged ( re cyclerView : ĠRecyclerView ?, ĠnewState : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscroll State Ġ= ĠnewState ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! scroll ing ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotify Adapter Changed () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġ_ client Ġ= Ġobject Ġ: ĠWebSocket Service . Client Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon StateChanged ( newState : ĠWebSocket Service . State , Ġold State : ĠWebSocket Service . State ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Message Received ( message : ĠSocket Message ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( message . type Ġ== ĠSocket Message . Type . Broadcast ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Messages . Broadcast . Play Queue Changed . matches ( message . name )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġre query () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Invalid Password () Ġ{} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠMAX _ SIZE Ġ= Ġ 1 5 0 ĊĠĠĠĠĠĠĠ Ġval ĠDEFAULT _ WINDOW _ SIZE Ġ= Ġ 7 5 ĊĠĠĠ Ġ} Ċ } Ċ