package Ġsl ak . fan fi ction stories . activities Ċ Ċ import Ġandroid . content . Intent Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . os . Parcelable Ċ import Ġandroid . text . Html Ċ import Ġandroid . text . Sp anned Ċ import Ġandroid . text . Sp anned . SPAN _ EXCL USIVE _ EXCL USIVE Ċ import Ġandroid . text . style . BackgroundColor Span Ċ import Ġandroid . util . Log Ċ import Ġandroid . view . Menu Ċ import Ġandroid . view . MenuItem Ċ import Ġandroid . view . View Ċ import Ġandroid . widget . LinearLayout Ċ import Ġandroid . widget . ProgressBar Ċ import Ġandroidx . activity . view Models Ċ import Ġandroidx . annotation . Any Thread Ċ import Ġandroidx . annotation . Ui Thread Ċ import Ġandroidx . appcompat . app . AlertDialog Ċ import Ġandroidx . appcompat . widget . AppCompat TextView Ċ import Ġandroidx . core . view . View Compat Ċ import Ġandroidx . core . widget . Nested ScrollView Ċ import Ġandroidx . lifecycle . LiveData Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġandroidx . lifecycle . ViewModel Ċ import Ġcom . google . android . material . sn ackbar . Snackbar Ċ import Ġkotlinx . android . synt hetic . main . activity _ main . view .* Ċ import Ġkotlinx . android . synt hetic . main . activity _ story _ reader .* Ċ import Ġkotlinx . android . synt hetic . main . activity _ story _ reader _ content .* Ċ import Ġkotlinx . android . synt hetic . main . loading _ activity _ in determinate .* Ċ import Ġkotlinx . coroutines . Coroutine Scope Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . Dispatch ers . Main Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . run Blocking Ċ import Ġkotlinx . coroutines . sync . Mutex Ċ import Ġorg . jetbrains . ank o . content View Ċ import Ġorg . jetbrains . ank o . db . Double Parser Ċ import Ġorg . jetbrains . ank o . db . select Ċ import Ġorg . jetbrains . ank o . long Toast Ċ import Ġorg . jetbrains . ank o . startActivity Ċ import Ġorg . js oup . J soup Ċ import Ġsl ak . fan fi ction stories .* Ċ import Ġsl ak . fan fi ction stories . Notifications . Companion . default Intent Ċ import Ġsl ak . fan fi ction stories . activities . Reader ViewModel . Chapter Event .* Ċ import Ġsl ak . fan fi ction stories . activities . Reader ViewModel . Companion . UN INITIAL IZED _ CH AP TER Ċ import Ġsl ak . fan fi ction stories . data .* Ċ import Ġsl ak . fan fi ction stories . data . fetch ers .* Ċ import Ġsl ak . fan fi ction stories . data . fetch ers . Parser Utils . parse Story Model Ċ import Ġsl ak . fan fi ction stories . utility .* Ċ import Ġkotlin . coroutines . Coroutine Context Ċ Ċ /** ĠHandles Ġthe Ġdata Ġrequired Ġto Ġdisplay Ġstory Ġchapter s . Ġ*/ Ċ class ĠReader ViewModel ( s Model : ĠStory Model ) Ġ: ĠViewModel (), ĠCor outine Scope Ġ{ ĊĠ Ġoverride Ġval Ġcoroutine Context : ĠCor outine Context ĊĠĠĠ Ġget () Ġ= ĠDispatch ers . Default ĊĊĠ Ġvar Ġstory Model : ĠStory Model ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġvar Ġcurrent Chapter : ĠLong Ġ= ĠUN INITIAL IZED _ CH AP TER ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġlateinit Ġvar Ġchapter Html : ĠString ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġenum Ġclass ĠChapter Event Ġ{ ĊĠĠĠ ĠCH AP TER _ LOAD _ STARTED , ĊĠĠĠ ĠCH AP TER _ FIRST _ LOAD , ĊĠĠĠ ĠCH AP TER _ CHANGED , ĊĠĠĠ ĠCH AP TER _ RE LOADED ĊĠ Ġ} ĊĠ Ġprivate Ġvar Ġ_ chapter Events Ġ= ĠMutable LiveData < Chapter Event >() ĊĠ Ġval Ġchapter Events : ĠLive Data < Chapter Event > Ġget () Ġ= Ġ_ chapter Events ĊĊĠ Ġvar Ġsearch Query Ġ= Ġ"" ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġvar Ġsearch Matches Ġ= ĠlistOf < Area >() ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġvar Ġsearch Current Match Idx : ĠInt Ġ= Ġ 0 ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġconst Ġval ĠUN INITIAL IZED _ CH AP TER Ġ= Ġ- 4 5 4 L ĊĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Reader ViewModel " ĊĠ Ġ} ĊĊĠ Ġinit Ġ{ ĊĠĠĠ Ġstory Model Ġ= Ġs Model ĊĠ Ġ} ĊĊĠ Ġ/** ĠUpdate Ġthe Ġ[ search Matches ] Ġaccording Ġto Ġthe Ġnew Ġsearch Ġstring . Ġ*/ ĊĠ Ġ@ Any Thread ĊĠ Ġfun Ġsearch In Chapter ( chapter Sp anned : ĠSp anned , Ġsearch Query : ĠString ) Ġ{ ĊĠĠĠ Ġthis . search Query Ġ= Ġsearch Query ĊĠĠĠ Ġsearch Current Match Idx Ġ= Ġ 0 ĊĠĠĠ Ġif Ġ( search Query . isEmpty ()) Ġsearch Matches Ġ= ĠlistOf () ĊĠĠĠ Ġvar Ġstart Idx Ġ= Ġchapter Sp anned . indexOf ( search Query ) ĊĠĠĠ Ġval Ġresults Ġ= Ġmutable ListOf < Area >() ĊĠĠĠ Ġwhile Ġ( start Idx Ġ!= Ġ- 1 ) Ġ{ ĊĠĠĠĠĠ Ġval Ġp Ġ= ĠArea ( start Idx , Ġsearch Query . length ) ĊĠĠĠĠĠ Ġresults . add ( p ) ĊĠĠĠĠĠ Ġstart Idx Ġ= Ġchapter Sp anned . indexOf ( search Query , Ġp . end Position ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġsearch Matches Ġ= Ġresults ĊĠ Ġ} ĊĊĠ Ġ/** ĠLoad Ġa Ġparticular Ġchapter . Ġ*/ ĊĠ Ġ@ Any Thread ĊĠ Ġfun Ġchange Chapter ( chapter To Read : ĠLong ) Ġ= Ġlaunch ( Main ) Ġ{ ĊĠĠĠ Ġ_ chapter Events . it Ġ= ĠCH AP TER _ LOAD _ STARTED ĊĠĠĠ Ġif Ġ( chapter To Read Ġ!= Ġcurrent Chapter ) Ġchapter Html Ġ= Ġget Chapter Html ( chapter To Read ) ĊĠĠĠ Ġ_ chapter Events . it Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠ Ġcurrent Chapter Ġ== ĠUN INITIAL IZED _ CH AP TER Ġ-> ĠCH AP TER _ FIRST _ LOAD ĊĠĠĠĠĠ Ġchapter To Read Ġ== Ġcurrent Chapter Ġ-> ĠCH AP TER _ RE LOADED ĊĠĠĠĠĠ Ġelse Ġ-> ĠCH AP TER _ CHANGED ĊĠĠĠ Ġ} ĊĠĠĠ ĠLog . v ( TAG , Ġ" to Read : Ġ$ chapter To Read , Ġcurrent : Ġ$ current Chapter Ġ| Ġ${ _ chapter Events . it }") ĊĠĠĠ Ġcurrent Chapter Ġ= Ġchapter To Read ĊĠ Ġ} ĊĊĠ Ġ@ Any Thread ĊĠ Ġprivate Ġsuspend Ġfun Ġget Chapter Html ( chapter To Read : ĠLong ): ĠString Ġ{ ĊĠĠĠ Ġ// ĠIf Ġthe Ġstory Ġis Ġremote Ġand Ġit Ġgets Ġupdated , Ġthe Ġdownloaded Ġchapter s Ġmay Ġbe Ġoutdated , Ġso Ġdelete Ġand Ġre - download ĊĠĠĠ Ġif Ġ( story Model . status Ġ== ĠStory Status . REMOTE Ġ&& Ġstory Model . fragment . update Time Ġ> Ġstory Model . last Read Time Ġ?: Ġ 0 ) Ġ{ ĊĠĠĠĠĠ Ġdelete Story ( story Model . story Id ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġread Chapter ( story Model . story Id , Ġchapter To Read ). orElse Ġ{ ĊĠĠĠĠĠ Ġval Ġchapter Html Text Ġ= Ġfetch Chapter ( story Model . story Id , Ġchapter To Read ) ĊĠĠĠĠĠ Ġval Ġtext Ġ= Ġextract Chapter Text ( J soup . parse ( chapter Html Text )) ĊĠĠĠĠĠ Ġwrite Chapter ( story Model . story Id , Ġchapter To Read , Ġtext ) ĊĠĠĠĠĠ Ġ// ĠGet Ġthe Ġmodel Ġtoo Ġif Ġwe Ġneed Ġit ĊĠĠĠĠĠ Ġif Ġ( story Model . status Ġ!= ĠStory Status . LOCAL ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstory Model Ġ= Ġparse Story Model ( chapter Html Text , Ġstory Model . story Id ) ĊĠĠĠĠĠĠĠ ĠStatic . database . upsert Model ( story Model ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ// ĠIf Ġall Ġchapter s Ġare Ġon Ġdisk , Ġset Ġto Ġlocal ĊĠĠĠĠĠ Ġif Ġ( chapter Count ( story Model . story Id ) Ġ== Ġstory Model . fragment . chapter Count . toInt ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġstory Model . status Ġ= ĠStory Status . LOCAL ĊĠĠĠĠĠĠĠ ĠStatic . database . update In Story ( story Model . story Id , Ġ" status " Ġto Ġ" local ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn @ orElse Ġtext ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠIf Ġthe Ġstory Ġalready Ġexists Ġin Ġthe Ġdatabase , Ġfetch Ġit Ġand Ġreplace Ġthe Ġcurrent Ġ[ Story Model ]. ĊĠĠ Ġ* ĠThis Ġensures Ġthat Ġthe Ġ[ Story Status . TRAN SI ENT ] Ġmodels Ġget Ġreplaced Ġwith Ġreal Ġones . ĊĠĠ Ġ*/ ĊĠ Ġ@ Any Thread ĊĠ Ġfun Ġtry Loading Model From Database () Ġ= Ġlaunch ( Dispatch ers . Default ) Ġ{ ĊĠĠĠ Ġ// ĠIf Ġthe Ġstory Ġis Ġin Ġthe Ġdb , Ġuse Ġit ĊĠĠĠ Ġstory Model Ġ= ĠStatic . database . story ById ( story Model . story Id ). await (). orElse ( story Model ) ĊĠ Ġ} ĊĊĠ Ġ/** Ġ@ see Ġfetch And Write Story Ġ*/ ĊĠ Ġ@ Any Thread ĊĠ Ġfun Ġdownload Story Loc ally () Ġ= Ġlaunch ( Dispatch ers . Default ) Ġ{ ĊĠĠĠ Ġstory Model Ġ= Ġfetch And Write Story ( story Model . story Id ). orElse Ġ{ ĊĠĠĠĠĠ ĠStatic . current Activity !!. long Toast ( R . string . story _ not _ found ) ĊĠĠĠĠĠ Ġreturn @ launch ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** Ġ@ see Ġsl ak . fan fi ction stories . data . fetch ers . update Story Ġ*/ ĊĠ Ġ@ Any Thread ĊĠ Ġfun Ġupdate Story () Ġ= Ġlaunch ( Dispatch ers . Default ) Ġ{ ĊĠĠĠ ĠNotifications . UP DAT ING . show ( default Intent (), ĠR . string . checking _ one _ story , Ġstory Model . title ) ĊĠĠĠ Ġval Ġnew Model Ġ= Ġupdate Story ( story Model ) ĊĠĠĠ Ġif Ġ( new Model Ġ! is ĠEmpty ) Ġ{ ĊĠĠĠĠĠ Ġstory Model Ġ= Ġnew Model . get () ĊĠĠĠĠĠ ĠNotifications . updated St ories ( listOf ( story Model )) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠ ĠNotifications . UP DAT ING . cancel () ĊĠĠĠĠĠ ĠNotifications . updated St ories ( emptyList ()) ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** ĠShows Ġa Ġchapter Ġof Ġa Ġstory Ġfor Ġreading . Ġ*/ Ċ class ĠStory Reader Activity Ġ: ĠCor outine Scope Activity (), ĠI Search able Activity , ĠI Has Loading Bar Ġ{ ĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Story Reader Activity " ĊĠĠĠ Ġconst Ġval ĠINTENT _ ST ORY _ MODEL Ġ= Ġ" bundle " ĊĠĠĠ Ġprivate Ġconst Ġval ĠTAG _ SEARCH _ FRAGMENT Ġ= Ġ" search " ĊĠ Ġ} ĊĊĠ Ġprivate Ġlateinit Ġvar Ġstory Model : ĠStory Model ĊĠ Ġprivate Ġval ĠviewModel : ĠReader ViewModel Ġby Ġview Models Ġ{ ĠViewModel Factory ( story Model ) Ġ} ĊĠ Ġprivate Ġlateinit Ġvar Ġsearch UI : ĠSearch UI Fragment ĊĊĠ Ġoverride Ġval Ġloading : ĠProgress Bar ĊĠĠĠ Ġget () Ġ= Ġactivity ProgressBar ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠGets Ġthe Ġdata Ġrequired Ġfor Ġthe Ġ[ ViewModel ]. ĠIt Ġwill Ġload Ġfrom Ġthe Ġintent ĠURI Ġ( clicked Ġlink Ġto Ġstory ), Ġor Ġfrom Ġthe ĊĠĠ Ġ* Ġintent Ġextras Ġ( in - app Ġnavigation ). ĊĠĠ Ġ* Ġ@ returns Ġthe Ġinitial Ġchapter Ġto Ġview , Ġor Ġ[ UN INITIAL IZED _ CH AP TER ] Ġif Ġwe Ġare Ġrespon ding Ġto Ġa Ġlink , Ġand Ġthe Ġlinked ĊĠĠ Ġ* Ġstory Ġdoesn 't Ġexist ĊĠĠ Ġ*/ ĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġsuspend Ġfun Ġobtain Model (): ĠLong Ġ= Ġwhen Ġ( intent . action ) Ġ{ ĊĠĠĠ Ġ// ĠRes pon ding Ġto Ġlinks ĊĠĠĠ ĠIntent . ACTION _ VIEW Ġ-> Ġ{ ĊĠĠĠĠĠ Ġval Ġpath Segments Ġ= Ġintent . data ?. path Segments Ġ?: Ġthrow ĠIllegalArgumentException (" Intent Ġdata Ġis Ġempty ") ĊĠĠĠĠĠ Ġif Ġ( path Segments . size Ġ> Ġ 3 ) Ġtitle Ġ= Ġpath Segments [ 3 ] ĊĠĠĠĠĠ Ġstory Model Ġ= Ġfetch Story Model ( path Segments [ 1 ]. to Long ()). orElse Ġ{ ĊĠĠĠĠĠĠĠ Ġlong Toast ( R . string . story _ not _ found ) ĊĠĠĠĠĠĠĠ Ġreturn ĠUN INITIAL IZED _ CH AP TER ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġval Ġcurrent Chapter Ġ= Ġpath Segments [ 2 ]. to Long () ĊĠĠĠĠĠ ĠStatic . database . upsert Model ( story Model ) ĊĠĠĠĠĠ ĠLog . v ( TAG , Ġ" Model Ġfrom Ġlink : Ġ$ intent , Ġresolved Ġmodel : Ġ$ story Model ") ĊĠĠĠĠĠ Ġcurrent Chapter ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠIn - app Ġnavigation ĊĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠ Ġstory Model Ġ= Ġintent . get Parcelable Extra ( INT ENT _ ST ORY _ MODEL ) ĊĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠIllegalArgumentException (" Story Ġmodel Ġmissing Ġfrom Ġextras ") ĊĠĠĠĠĠ Ġval Ġcurrent Chapter Ġ= Ġif Ġ( story Model . progress . current Chapter Ġ== Ġ 0 L ) Ġ 1 L Ġelse Ġstory Model . progress . current Chapter ĊĠĠĠĠĠ ĠLog . v ( TAG , Ġ" Model Ġfrom Ġintent Ġextra : Ġ$ story Model ") ĊĠĠĠĠĠ Ġcurrent Chapter ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠInitializes Ġthe Ġ[ Search UI Fragment ] Ġfragment . Ġ*/ ĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġfun Ġinit Search () Ġ{ ĊĠĠĠ Ġval Ġold Highlight er Ġ= Ġsupport FragmentManager . find Fragment By Tag ( TAG _ SEARCH _ FRAGMENT ) Ġas ? ĠSearch UI Fragment ĊĠĠĠ Ġif Ġ( old Highlight er Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġsearch UI Ġ= Ġold Highlight er ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠ Ġsearch UI Ġ= ĠSearch UI Fragment () ĊĠĠĠĠĠ Ġsupport FragmentManager . beginTransaction (). add ( R . id . root Layout , Ġsearch UI , ĠTAG _ SEARCH _ FRAGMENT ). commit () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun ĠonCreate ( savedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠ Ġsuper . onCreate ( savedInstanceState ) ĊĠĠĠ ĠsetContentView ( R . layout . activity _ story _ reader ) ĊĠĠĠ Ġset Support ActionBar ( toolbar ) ĊĠĠĠ Ġset Loading View ( toolbar ) ĊĠĠĠ Ġsupport ActionBar ?. set Display Home As Up Enabled ( true ) ĊĊĠĠĠ Ġlaunch ( Main ) Ġ{ ĊĠĠĠĠĠ Ġval Ġinitial Chapter Ġ= Ġobtain Model () ĊĠĠĠĠĠ Ġ// ĠNo Ġstory Ġthere , Ġleave Ġactivity ĊĠĠĠĠĠ Ġif Ġ( initial Chapter Ġ== ĠUN INITIAL IZED _ CH AP TER ) Ġ{ ĊĠĠĠĠĠĠĠ Ġfinish () ĊĠĠĠĠĠĠĠ Ġreturn @ launch ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġ// ĠSetup Ġchapter Ġswitching Ġbuttons ĊĠĠĠĠĠ Ġprev Chapter Btn . setOnClickListener Ġ{ ĠviewModel . change Chapter ( viewModel . current Chapter Ġ- Ġ 1 ) Ġ} ĊĠĠĠĠĠ Ġnext Chapter Btn . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( next Chapter Btn . text Ġ== Ġstr ( R . string . next )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠviewModel . change Chapter ( viewModel . current Chapter Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠ Ġreturn @ setOnClickListener ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġmodel Ġ= Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġqueue Ġ= Ġdatabase . get Story Queue () ĊĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent Idx In Queue Ġ= Ġqueue . first Ġ{ Ġit . first Ġ== ĠviewModel . story Model . story Id Ġ}. second ĊĠĠĠĠĠĠĠĠĠ Ġval Ġnext Story Ġ= Ġqueue . first Ġ{ Ġit . second Ġ== Ġcurrent Idx In Queue Ġ+ Ġ 1 Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġdatabase . story ById ( next Story . first ). await () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. orElse Throw ( IllegalStateException (" Story Ġqueue Ġinconsistent ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( this @ Story Reader Activity , ĠStory Reader Activity :: class . java ) ĊĠĠĠĠĠĠĠ Ġintent . putExtra ( INT ENT _ ST ORY _ MODEL , Ġmodel Ġas ĠParcel able ) ĊĠĠĠĠĠĠĠ Ġintent . flags Ġ= ĠIntent . FLAG _ ACTIVITY _ CLEAR _ TOP ĊĠĠĠĠĠĠĠ ĠstartActivity ( intent ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġselect Chapter Btn . setOnClickListener Ġ{ Ġshow Chapter Select Dialog () Ġ} ĊĊĠĠĠĠĠ Ġ// ĠSave Ġstory Ġfor Ġthe Ġresume Ġbutton ĊĠĠĠĠĠ Ġ// ĠEven Ġfor Ġtransient Ġstories , Ġbecause Ġentering Ġthe Ġreader Ġmeans Ġthe Ġstory Ġbecame Ġremote ĊĠĠĠĠĠ ĠP refs . resume Story Id Ġ= ĠviewModel . story Model . story Id ĊĊĠĠĠĠĠ Ġ// ĠMagic Ġfor Ġdealing Ġwith Ġtext Ġheight ĊĠĠĠĠĠ Ġval Ġtitle TextView Ġ= Ġ( toolbar Layout . toolbar . getChild At ( 0 ) Ġas ĠAppCompat TextView ) ĊĠĠĠĠĠ Ġval Ġfake Width Ġ= Ġtitle TextView . text Size Ġ* ĠviewModel . story Model . title . length ĊĠĠĠĠĠ Ġval Ġtext Margin Ġ= Ġresources . px ( R . dim en . text _ margin ) ĊĠĠĠĠĠ Ġval Ġtext Height Ġ= Ġ( fake Width Ġ/ Ġ( toolbar Layout . width Ġ/ Ġ 2 )). coerce At Least ( 1 F ) Ġ* Ġtitle TextView . line Height ĊĠĠĠĠĠ Ġapp Bar . layout Params . height Ġ= ĊĠĠĠĠĠĠĠĠĠ Ġ( resources . px ( R . dim en . app _ bar _ height _ base ) Ġ+ Ġtext Height Ġ+ Ġtext Margin ). toInt () ĊĠĠĠĠĠ Ġtoolbar Layout . title Ġ= ĠviewModel . story Model . title ĊĊĠĠĠĠĠ Ġif Ġ( viewModel . story Model . status Ġ!= ĠStory Status . LOCAL ) Ġ{ ĊĠĠĠĠĠĠĠ ĠviewModel . try Loading Model From Database (). join () ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġif Ġ( viewModel . current Chapter Ġ== ĠUN INITIAL IZED _ CH AP TER ) ĠviewModel . change Chapter ( initial Chapter ). join () ĊĠĠĠĠĠ Ġelse ĠviewModel . change Chapter ( viewModel . current Chapter ). join () ĊĠĠĠĠĠ Ġinit Search () ĊĊĠĠĠĠĠ ĠviewModel . chapter Events . observe ( this @ Story Reader Activity , Ġ:: handle Chapter Event ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Save InstanceState ( out State : ĠBundle ) Ġ{ ĊĠĠĠ Ġsuper . on Save InstanceState ( out State ) ĊĠĠĠ Ġout State . put Parcelable ( INT ENT _ ST ORY _ MODEL , Ġstory Model ) ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Restore InstanceState ( savedInstanceState : ĠBundle ) Ġ{ ĊĠĠĠ Ġsuper . on Restore InstanceState ( savedInstanceState ) ĊĠĠĠ Ġstory Model Ġ= ĠsavedInstanceState . get Parcelable ( INT ENT _ ST ORY _ MODEL ) !! ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Pause () Ġ{ ĊĠĠĠ Ġsuper . on Pause () ĊĠĠĠ Ġif Ġ( viewModel . story Model . status Ġ== ĠStory Status . LOCAL ) Ġ{ ĊĠĠĠĠĠ Ġ// ĠUpdate Ġlast Ġtime Ġthe Ġstory Ġwas Ġread ĊĠĠĠĠĠ Ġdatabase . update In Story ( viewModel . story Model . story Id , Ġ" last Read Time " Ġto ĠSystem . currentTimeMillis ()) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġfun Ġset Chapter Meta Text () Ġ= Ġwith ( viewModel . story Model ) Ġ{ ĊĠĠĠ Ġval Ġchapter Word Count Ġ= Ġauto Suffix Number ( viewModel . chapter Html . split (" Ġ"). size ) ĊĠĠĠ Ġchapter Word Count Text . text Ġ= Ġstr ( R . string . x _ words , Ġchapter Word Count ) ĊĠĠĠ Ġcurrent Chapter Text . text Ġ= Ġstr ( R . string . chapter _ progress , ĊĠĠĠĠĠĠĠ ĠviewModel . current Chapter , Ġfragment . chapter Count ) ĊĠĠĠ Ġval Ġavg Word Count : ĠDouble Ġ= Ġfragment . word Count . toDouble () Ġ/ Ġfragment . chapter Count ĊĠĠĠ Ġval Ġwords Passed Estimate : ĠDouble Ġ= Ġ( viewModel . current Chapter Ġ- Ġ 1 ) Ġ* Ġavg Word Count ĊĠĠĠ Ġapprox Word Count Remain Text . text Ġ= Ġstr ( R . string . approx _ x _ words _ left , ĊĠĠĠĠĠĠĠ Ġauto Suffix Number ( fragment . word Count Ġ- Ġwords Passed Estimate . to Long ())) ĊĠĠĠ Ġ// ĠThis Ġdata Ġis Ġmore Ġor Ġless Ġuseless Ġwith Ġonly Ġone Ġchapter , Ġso Ġwe Ġhide Ġit ĊĠĠĠ Ġval Ġextra Data Visibility Ġ= Ġif Ġ( fragment . chapter Count Ġ== Ġ 1 L ) ĠView . GONE Ġelse ĠView . VISIBLE ĊĠĠĠ Ġchapter Word Count Text . visibility Ġ= Ġextra Data Visibility ĊĠĠĠ Ġcurrent Chapter Text . visibility Ġ= Ġextra Data Visibility ĊĠĠĠ Ġapprox Word Count Remain Text . visibility Ġ= Ġextra Data Visibility ĊĊĠĠĠ Ġ// ĠSet Ġchapter 's Ġtitle Ġ( chapter To Read Ġis Ġ 1 - indexed ) ĊĠĠĠ Ġif Ġ( fragment . chapter Count Ġ> Ġ 1 ) Ġ{ ĊĠĠĠĠĠ Ġchapter Title Text . text Ġ= Ġchapter Titles ()[ viewModel . current Chapter . toInt () Ġ- Ġ 1 ] ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠDon 't Ġshow Ġit Ġif Ġthere Ġis Ġno Ġtitle Ġ( otherwise Ġthere Ġare Ġlef to ver Ġmargins / padding ) ĊĠĠĠ Ġchapter Title Text . visibility Ġ= Ġif Ġ( chapter Title Text . text Ġ== Ġ"") ĠView . GONE Ġelse ĠView . VISIBLE ĊĠ Ġ} ĊĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġsuspend Ġfun Ġrestore Scroll Status () Ġ{ ĊĠĠĠ Ġif Ġ( chapter Text . text Layout Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Cannot Ġrestore Ġscroll Ġstatus Ġbecause Ġlayout Ġis Ġnull ") ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġscroll Abs Ġ= Ġdatabase . use Async Ġ{ ĊĠĠĠĠĠ Ġselect (" stories ", Ġ" scroll Absolute ") ĊĠĠĠĠĠĠĠĠĠ Ġ. where Simple (" story Id Ġ= Ġ?", ĠviewModel . story Model . story Id . toString ()) ĊĠĠĠĠĠĠĠĠĠ Ġ. parse Opt ( Double Parser ) ĊĠĠĠ Ġ}. await () ĊĠĠĠ Ġif Ġ( scroll Abs Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Absolute Ġscroll Ġposition Ġis Ġnull ") ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĠĠĠ Ġchapter Scroll ( chapter Text . scroll Y From Scroll State ( scroll Abs )) ĊĠ Ġ} ĊĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġfun Ġparse Chapter HTML (): ĠSp anned Ġ{ ĊĠĠĠ Ġreturn ĠHtml . from Html ( viewModel . chapter Html , ĠHtml . FROM _ HTML _ MODE _ LEG ACY , ĊĠĠĠĠĠĠĠ Ġnull , ĠH r Span . tag Handler Factory ( chapter Text . width )) ĊĠ Ġ} ĊĊĠ Ġ/** ĠReact Ġto Ġ[ Reader ViewModel . Chapter Event ] s Ġfrom Ġthe Ġmodel . Ġ*/ ĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġfun Ġhandle Chapter Event ( it : ĠReader ViewModel . Chapter Event ): ĠUnit Ġ= Ġwhen Ġ( it ) Ġ{ ĊĠĠĠ ĠCH AP TER _ LOAD _ STARTED Ġ-> Ġ{ ĊĠĠĠĠĠ Ġ// ĠShow Ġloading Ġthings Ġand Ġdisable Ġchapter Ġswitching ĊĠĠĠĠĠ Ġif Ġ( viewModel . story Model . status Ġ!= ĠStory Status . LOCAL ) Ġshow Loading () ĊĠĠĠĠĠ Ġbtn Bar Loader . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠ Ġnav Buttons . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠ Ġprev Chapter Btn . isEnabled Ġ= Ġfalse ĊĠĠĠĠĠ Ġnext Chapter Btn . isEnabled Ġ= Ġfalse ĊĠĠĠĠĠ Ġselect Chapter Btn . isEnabled Ġ= Ġfalse ĊĠĠĠĠĠ Ġinvalidate Options Menu () ĊĠĠĠ Ġ} ĊĠĠĠ ĠCH AP TER _ FIRST _ LOAD Ġ-> Ġ{ ĊĠĠĠĠĠ Ġon Chapter Load Finished ( true ) ĊĠĠĠĠĠ ĠUnit ĊĠĠĠ Ġ} ĊĠĠĠ ĠCH AP TER _ CHANGED Ġ-> Ġ{ ĊĠĠĠĠĠ Ġon Chapter Load Finished ( false ) ĊĠĠĠĠĠ ĠUnit ĊĠĠĠ Ġ} ĊĠĠĠ ĠCH AP TER _ RE LOADED Ġ-> Ġ{ ĊĠĠĠĠĠ Ġon Chapter Load Finished ( true ). invoke On Completion Ġ{ Ġerr Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ( err Ġ!= Ġnull ) Ġreturn @ invoke On Completion ĊĠĠĠĠĠĠĠ Ġval Ġis Visible Ġ= Ġsearch UI . restore State () ĊĠĠĠĠĠĠĠ Ġroot Layout . post Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġclear Highlight s () ĊĠĠĠĠĠĠĠĠĠ Ġhighlight Matches () ĊĠĠĠĠĠĠĠĠĠ Ġadjust Nav For Search ( remove Margin Ġ= Ġ! isVisible ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠUnit ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġsuspend Ġfun Ġupdate Next ButtonText () Ġ{ ĊĠĠĠ Ġif Ġ( viewModel . current Chapter Ġ== ĠviewModel . story Model . fragment . chapter Count ) Ġ{ ĊĠĠĠĠĠ Ġval Ġqueue Ġ= Ġdatabase . get Story Queue () ĊĠĠĠĠĠ Ġval Ġcurrent In Queue Ġ= Ġqueue . first OrNull Ġ{ Ġit . first Ġ== ĠviewModel . story Model . story Id Ġ} ?. second ĊĠĠĠĠĠ Ġif Ġ( current In Queue Ġ== Ġnull Ġ|| Ġcurrent In Queue . toInt () Ġ== Ġqueue . size Ġ- Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnext Chapter Btn . isEnabled Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġnext Chapter Btn . text Ġ= Ġstr ( R . string . next _ chapter _ with _ queue ) ĊĠĠĠĠĠ Ġnext Chapter Btn . isEnabled Ġ= Ġtrue ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠ Ġnext Chapter Btn . text Ġ= Ġstr ( R . string . next ) ĊĠĠĠĠĠ Ġnext Chapter Btn . isEnabled Ġ= Ġtrue ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Any Thread ĊĠ Ġprivate Ġfun Ġon Chapter Load Finished ( restore Scroll : ĠBoolean ) Ġ= Ġlaunch ( Main ) Ġ{ ĊĠĠĠ Ġ// ĠWe Ġuse Ġthe Ġwidth Ġfor Ġthe Ġ< hr > Ġelements , Ġso Ġthe Ġlayout Ġshould Ġbe Ġdone ĊĠĠĠ Ġif Ġ(! View Compat . is La id Out ( chapter Text )) Ġchapter Text . request Layout () ĊĊĠĠĠ Ġval Ġchapter Sp anned Ġ= Ġparse Chapter HTML () ĊĠĠĠ Ġchapter Text . setText ( chapter Sp anned , Ġtheme ) ĊĠĠĠ Ġif Ġ( viewModel . search Matches . isNotEmpty ()) ĠviewModel . search In Chapter ( chapter Sp anned , ĠviewModel . search Query ) ĊĊĠĠĠ Ġset Chapter Meta Text () ĊĊĠĠĠ Ġ// ĠScroll Ġto Ġwhere Ġwe Ġleft Ġoff Ġif Ġwe Ġjust Ġentered , Ġor Ġat Ġthe Ġbeginning Ġfor Ġfurther Ġnavigation ĊĠĠĠ Ġif Ġ( restore Scroll ) Ġrestore Scroll Status () ĊĠĠĠ Ġelse Ġchapter Scroll ( 0 ) ĊĊĠĠĠ Ġdatabase . update In Story ( viewModel . story Model . story Id , ĊĠĠĠĠĠĠĠ Ġ" current Chapter " Ġto ĠviewModel . current Chapter ). await () ĊĊĠĠĠ Ġ// ĠDisable Ġbuttons Ġif Ġthere Ġis Ġnow here Ġfor Ġthem Ġto Ġgo ĊĠĠĠ Ġprev Chapter Btn . isEnabled Ġ= ĠviewModel . current Chapter Ġ!= Ġ 1 L ĊĠĠĠ Ġupdate Next ButtonText () ĊĠĠĠ Ġselect Chapter Btn . isEnabled Ġ= ĠviewModel . story Model . fragment . chapter Count Ġ> Ġ 1 L ĊĊĠĠĠ Ġ// ĠT int Ġbutton Ġicons Ġgrey Ġif Ġthe Ġbuttons Ġare Ġdisabled , Ġwhite Ġif Ġnot ĊĠĠĠ Ġfun Ġget Color For ( view : ĠView ) Ġ= Ġif Ġ( view . isEnabled ) ĠR . color . white Ġelse ĠR . color . text Disabled ĊĠĠĠ Ġprev Chapter Btn . drawable Tint ( getColor For ( prev Chapter Btn ), Ġtheme , ĠDirection . LEFT ) ĊĠĠĠ Ġnext Chapter Btn . drawable Tint ( getColor For ( next Chapter Btn ), Ġtheme , ĠDirection . RIGHT ) ĊĠĠĠ Ġselect Chapter Btn . drawable Tint ( getColor For ( select Chapter Btn ), Ġtheme , ĠDirection . LEFT ) ĊĊĠĠĠ Ġ// ĠHandle Ġthe Ġnext / prev Ġbutton Ġstates / colors Ġin Ġthe Ġapp bar ĊĠĠĠ Ġinvalidate Options Menu () ĊĊĠĠĠ Ġ// ĠIf Ġthe Ġtext Ġis Ġso Ġshort Ġthe Ġsc roller Ġdoesn 't Ġneed Ġto Ġscroll , Ġmax Ġout Ġprogress Ġright Ġaway ĊĠĠĠ Ġif Ġ( nested Scroller . height Ġ> Ġchapter Text . text Layout !!. height ) Ġ{ ĊĠĠĠĠĠ Ġscroll Saver . notify Changed ( 1 0 0 . 0 , Ġ 9 9 9 9 9 9 9 9 . 0 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠRecord Ġscroll Ġstatus ĊĠĠĠ Ġnested Scroller . setOn Scroll ChangeListener Ġ{ Ġsc roller , Ġ_, Ġscroll Y : ĠInt , Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠ Ġval Ġraw Percentage Ġ= Ġscroll Y Ġ* Ġ 1 0 0 . 0 Ġ/ Ġ( scroll ing Layout . meas ured Height Ġ- Ġsc roller . bottom ) ĊĠĠĠĠĠ Ġ// ĠMake Ġsure Ġthat Ġvalues Ġ> 1 0 0 Ġget Ġclamp ed Ġto Ġ 1 0 0 ĊĠĠĠĠĠ Ġval Ġpercentage Sc rolled Ġ= Ġraw Percentage . coerce At Most ( 1 0 0 . 0 ) ĊĠĠĠĠĠ Ġval Ġscroll Abs Ġ= Ġchapter Text . scroll State From Scroll Y ( scroll Y ) ĊĠĠĠĠĠ Ġscroll Saver . notify Changed ( percentage Sc rolled , Ġscroll Abs ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠHide Ġloading Ġthings ĊĠĠĠ Ġhide Loading () ĊĠĠĠ Ġbtn Bar Loader . visibility Ġ= ĠView . GONE ĊĠĠĠ Ġnav Buttons . visibility Ġ= ĠView . VISIBLE ĊĠ Ġ} ĊĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġfun Ġchapter Scroll ( y : ĠInt ) Ġ{ ĊĠĠĠ Ġapp Bar . set Expanded ( y Ġ<= Ġresources . px ( R . dim en . app _ bar _ height )) ĊĠĠĠ Ġnested Scroller . post Ġ{ ĊĠĠĠĠĠ Ġnested Scroller . scrollTo ( 0 , Ġy ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠEn caps ulates Ġthe Ġscroll Ġstate Ġsaving Ġlogic . Ġ*/ ĊĠ Ġprivate Ġval Ġscroll Saver Ġ= Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġpercentage Sc rolled Val Ġ= Ġ 0 . 0 ĊĠĠĠ Ġprivate Ġvar Ġscroll Absolute Val Ġ= Ġ 0 . 0 ĊĠĠĠ Ġprivate Ġvar Ġsave Lock Ġ= ĠMutex () ĊĠĠĠ Ġprivate Ġvar Ġhas Changed Ġ= Ġfalse ĊĊĠĠĠ Ġ@ Any Thread ĊĠĠĠ Ġfun Ġnotify Changed ( percentage Sc rolled : ĠDouble , Ġscroll Absolute : ĠDouble ) Ġ{ ĊĠĠĠĠĠ Ġpercentage Sc rolled Val Ġ= Ġpercentage Sc rolled ĊĠĠĠĠĠ Ġscroll Absolute Val Ġ= Ġscroll Absolute ĊĠĠĠĠĠ Ġval Ġmanaged To Lock Ġ= Ġsave Lock . try Lock () ĊĠĠĠĠĠ Ġhas Changed Ġ= Ġtrue ĊĠĠĠĠĠ Ġif Ġ(! managed To Lock ) Ġreturn ĊĠĠĠĠĠ Ġlaunch ( Dispatch ers . Default ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwhile Ġ( has Changed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġhas Changed Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠ Ġdatabase . update In Story ( viewModel . story Model . story Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" scroll Progress " Ġto Ġpercentage Sc rolled Val , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" scroll Absolute " Ġto Ġscroll Absolute Val ). join () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠIf Ġthis Ġmethod Ġis Ġcalled Ġright Ġ* here * Ġon Ġanother Ġthread , Ġthat Ġcall Ġwill Ġbe Ġsw allowed ĊĠĠĠĠĠĠĠ Ġsave Lock . unlock () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Ui Thread ĊĠ Ġprivate Ġfun Ġshow Chapter Select Dialog () Ġ{ ĊĠĠĠ ĠAlertDialog . Builder ( this ) ĊĠĠĠĠĠĠĠ Ġ. setTitle ( R . string . select _ chapter ) ĊĠĠĠĠĠĠĠ Ġ. set Single Choice Items ( viewModel . story Model . chapter Titles (). map Indexed Ġ{ Ġidx , Ġchapter Title Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġ"${ idx Ġ+ Ġ 1 }. Ġ$ chapter Title " ĊĠĠĠĠĠĠĠ Ġ}. to Typed Array (), Ġ( viewModel . current Chapter Ġ- Ġ 1 ). toInt ()) Ġ{ Ġdialog , Ġwhich : ĠInt Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġdialog . dismiss () ĊĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġmeans Ġ' go Ġto Ġsame Ġchapter ', Ġso Ġdo Ġnothing ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( viewModel . current Chapter Ġ== Ġwhich Ġ+ Ġ 1 L ) Ġreturn @ set Single Choice Items ĊĠĠĠĠĠĠĠĠĠ ĠviewModel . change Chapter ( which Ġ+ Ġ 1 L ) ĊĠĠĠĠĠĠĠ Ġ}. show () ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Prepare Options Menu ( menu : ĠMenu ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ( isLoading ()) Ġreturn Ġfalse ĊĠĠĠ Ġmenu . find Item ( R . id . goTo Top ). icon Tint ( R . color . white , Ġtheme ) ĊĠĠĠ Ġmenu . find Item ( R . id . goTo Bottom ). icon Tint ( R . color . white , Ġtheme ) ĊĠĠĠ Ġmenu . find Item ( R . id . next Chapter ). isEnabled Ġ= Ġnext Chapter Btn . isEnabled ĊĠĠĠ Ġmenu . find Item ( R . id . next Chapter ). title Ġ= ĊĠĠĠĠĠĠĠ Ġif Ġ( next Chapter Btn . text Ġ== Ġstr ( R . string . next )) Ġstr ( R . string . next _ chapter ) ĊĠĠĠĠĠĠĠ Ġelse Ġstr ( R . string . next _ chapter _ with _ queue ) ĊĠĠĠ Ġmenu . find Item ( R . id . prev Chapter ). isEnabled Ġ= Ġprev Chapter Btn . isEnabled ĊĠĠĠ Ġmenu . find Item ( R . id . select Chapter ). isEnabled Ġ= Ġselect Chapter Btn . isEnabled ĊĠĠĠ Ġmenu . find Item ( R . id . download Local ). isVisible Ġ= ĠviewModel . story Model . status Ġ!= ĠStory Status . LOCAL ĊĠĠĠ Ġmenu . find Item ( R . id . check For Update ). isVisible Ġ= ĠviewModel . story Model . status Ġ== ĠStory Status . LOCAL ĊĠĠĠ Ġlaunch ( Main ) Ġ{ ĊĠĠĠĠĠ Ġval ĠisIn Queue Ġ= Ġdatabase . get Story Queue (). first OrNull Ġ{ Ġit . first Ġ== ĠviewModel . story Model . story Id Ġ} ĊĠĠĠĠĠ Ġval Ġitem Ġ= Ġmenu . find Item ( R . id . toggle Queue ) ĊĠĠĠĠĠ Ġif Ġ( isIn Queue Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġitem . isChecked Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġitem . title Ġ= Ġstr ( R . string . remove _ from _ queue ) ĊĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġitem . isChecked Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġitem . title Ġ= Ġstr ( R . string . add _ to _ queue ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġsuper . on Prepare Options Menu ( menu ) ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun ĠonCreate Options Menu ( menu : ĠMenu ): ĠBoolean Ġ{ ĊĠĠĠ Ġmenu Inflater . inflate ( R . menu . menu _ story _ reader , Ġmenu ) ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Options ItemSelected ( item : ĠMenuItem ): ĠBoolean Ġ{ ĊĠĠĠ Ġwhen Ġ( item . itemId ) Ġ{ ĊĠĠĠĠĠ ĠR . id . goTo Top Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWithout Ġthis Ġhack y Ġcall Ġto Ġfl ing , Ġwe Ġdon 't Ġscroll Ġat Ġall ĊĠĠĠĠĠĠĠ Ġnested Scroller . fl ing ( 0 ) ĊĠĠĠĠĠĠĠ Ġnested Scroller . full Scroll ( Nested ScrollView . FOCUS _ UP ) ĊĠĠĠĠĠĠĠ Ġapp Bar . set Expanded ( true ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . goTo Bottom Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġnested Scroller . full Scroll ( Nested ScrollView . FOCUS _ DOWN ) ĊĠĠĠĠĠĠĠ Ġapp Bar . set Expanded ( false ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . select Chapter Ġ-> Ġshow Chapter Select Dialog () ĊĠĠĠĠĠ ĠR . id . next Chapter Ġ-> Ġnext Chapter Btn . call OnClick () ĊĠĠĠĠĠ ĠR . id . prev Chapter Ġ-> Ġprev Chapter Btn . call OnClick () ĊĠĠĠĠĠ ĠR . id . toggle Queue Ġ-> Ġlaunch ( Main ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! item . isChecked ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġwas Added Ġ= Ġdatabase . addTo Queue ( viewModel . story Model . story Id ) ĊĠĠĠĠĠĠĠĠĠ Ġval Ġstr Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( was Added ) Ġstr ( R . string . added _ story _ from _ queue , ĠviewModel . story Model . title ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġstr ( R . string . already _ in _ queue ) ĊĠĠĠĠĠĠĠĠĠ ĠSn ackbar . make ( chapter Text , Ġstr , ĠSn ackbar . LENGTH _ LONG ). show () ĊĠĠĠĠĠĠĠĠĠ Ġitem . title Ġ= Ġstr ( R . string . remove _ from _ queue ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġdatabase . remove From Queue ( viewModel . story Model . story Id ) ĊĠĠĠĠĠĠĠĠĠ Ġval Ġstr Ġ= Ġstr ( R . string . removed _ story _ from _ queue , ĠviewModel . story Model . title ) ĊĠĠĠĠĠĠĠĠĠ ĠSn ackbar . make ( chapter Text , Ġstr , ĠSn ackbar . LENGTH _ LONG ). show () ĊĠĠĠĠĠĠĠĠĠ Ġitem . title Ġ= Ġstr ( R . string . add _ to _ queue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . set Marker Color Ġ-> Ġlaunch ( Main ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcolor Ġ= ĠStatic . database . get Marker ( viewModel . story Model . story Id ). await (). toInt () ĊĠĠĠĠĠĠĠ Ġcreate Marker Color Dialog ( color ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġdatabase . set Marker ( viewModel . story Model . story Id , Ġit ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . search Chapter Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġsearch UI . show () ĊĠĠĠĠĠĠĠ Ġroot Layout . post Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġadjust Nav For Search ( remove Margin Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . story Reviews Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠstartActivity < Reviews Activity >( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠRe views Activity . INT ENT _ ST ORY _ MODEL Ġto ĠviewModel . story Model Ġas ĠParcel able , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠRe views Activity . INT ENT _ TARGET _ CH AP TER Ġto ĠviewModel . current Chapter . toInt ()) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . view Author Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠstartActivity < Author Activity >( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠAuthor Activity . INT ENT _ AUTHOR _ ID Ġto ĠviewModel . story Model . author Id , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠAuthor Activity . INT ENT _ AUTHOR _ NAME Ġto ĠviewModel . story Model . author ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠR . id . download Local Ġ-> ĠviewModel . download Story Loc ally () ĊĠĠĠĠĠ ĠR . id . check For Update Ġ-> ĠviewModel . update Story () ĊĠĠĠĠĠ ĠR . id . delete Local Ġ-> Ġundo able Action ( content View !! , ĠR . string . data _ deleted ) Ġ{ ĊĠĠĠĠĠĠĠ Ġdelete Story ( viewModel . story Model . story Id ) ĊĠĠĠĠĠĠĠ Ġdatabase . update In Story ( viewModel . story Model . story Id , Ġ" status " Ġto Ġ" remote ") ĊĠĠĠĠĠĠĠ ĠviewModel . story Model . status Ġ= ĠStory Status . REMOTE ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġandroid . R . id . home Ġ-> Ġon Back Pressed () ĊĠĠĠĠĠ Ġelse Ġ-> Ġreturn Ġsuper . on Options ItemSelected ( item ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġget Match Count (): ĠInt Ġ= ĠviewModel . search Matches . size ĊĠ Ġoverride Ġfun ĠgetCurrent Highlight (): ĠInt Ġ= ĠviewModel . search Current Match Idx ĊĊĠ Ġoverride Ġfun Ġnavigate To Highlight ( idx : ĠInt ) Ġ{ ĊĠĠĠ Ġchapter Text . text Layout ?. iterate Displayed Lines Ġ{ Ġline Idx , Ġline Range Ġ-> ĊĠĠĠĠĠ Ġif Ġ( viewModel . search Matches [ idx ]. start Position Ġin Ġline Range ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbaseline Ġ= Ġchapter Text . text Layout !!. getLine Bounds ( line Idx , Ġnull ) ĊĠĠĠĠĠĠĠ Ġchapter Scroll ( baseline ) ĊĠĠĠĠĠĠĠ Ġreturn @ iterate Displayed Lines Ġtrue ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn @ iterate Displayed Lines Ġfalse ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġset Search Query ( query : ĠString ) Ġ= ĠviewModel . search In Chapter ( parse Chapter HTML (), Ġquery ) ĊĊĠ Ġoverride Ġfun Ġupdate Current Highlight ( idx : ĠInt ) Ġ{ ĊĠĠĠ ĠviewModel . search Current Match Idx Ġ= Ġidx ĊĠĠĠ Ġhighlight Matches () ĊĠ Ġ} ĊĊĠ Ġprivate Ġinner Ġclass ĠSearch Highlight Span ( is Current : ĠBoolean ) Ġ: ĠBackground Color Span ( ĊĠĠĠĠĠ Ġget Color ( if Ġ( is Current ) ĠR . color . text Highlight Current Ġelse ĠR . color . text Highlight Default )) ĊĠ Ġoverride Ġfun Ġhighlight Matches () Ġ{ ĊĠĠĠ ĠcheckNotNull ( chapter Text . span nable ) Ġ{ Ġ" Can 't Ġhighlight Ġmissing Ġtext " Ġ} ĊĠĠĠ ĠviewModel . search Matches . forEach Ġ{ ĊĠĠĠĠĠ Ġchapter Text . span nable !!. set Span ( Search Highlight Span ( false ), ĊĠĠĠĠĠĠĠĠĠ Ġit . start Position , Ġit . end Position , ĠSP AN _ EXCL USIVE _ EXCL USIVE ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ( viewModel . search Matches . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġval Ġcurr Ġ= ĠviewModel . search Matches [ viewModel . search Current Match Idx ] ĊĠĠĠĠĠ Ġchapter Text . span nable !!. set Span ( Search Highlight Span ( true ), ĊĠĠĠĠĠĠĠĠĠ Ġcurr . start Position , Ġcurr . end Position , ĠSP AN _ EXCL USIVE _ EXCL USIVE ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġchapter Text . invalidate () ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġclear Highlight s () Ġ{ ĊĠĠĠ Ġchapter Text . span nable ?. removeAll Spans ( Search Highlight Span :: class . java ) ĊĠĠĠ Ġchapter Text . invalidate () ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadjust Nav For Search ( remove Margin : ĠBoolean ) Ġ{ ĊĠĠĠ Ġval Ġparams Ġ= Ġnav Buttons . layout Params Ġas ĠLinearLayout . LayoutParams ĊĠĠĠ Ġparams . bottom Margin Ġ+= Ġsearch UI . view !!. meas ured Height Ġ* Ġ( if Ġ( remove Margin ) Ġ- 1 Ġelse Ġ 1 ) ĊĠĠĠ Ġnav Buttons . layout Params Ġ= Ġparams ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Hide () Ġ{ ĊĠĠĠ Ġadjust Nav For Search ( remove Margin Ġ= Ġtrue ) ĊĠ Ġ} Ċ } Ċ