/* Ċ Ġ* ĠCopyright Ġ 2 0 2 0 ĠRe think DNS Ġand Ġits Ġauthors Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . cel zero . br aved ns . ui Ċ Ċ import Ġandroid . icu . text . Compact Decimal Format Ċ import Ġandroid . os . Build Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . view . View Ċ import Ġandroidx . appcompat . app . AlertDialog Ċ import Ġandroidx . appcompat . widget . Search View Ċ import Ġandroidx . fragment . app . Fragment Ċ import Ġandroidx . lifecycle . lifecycle Scope Ċ import Ġandroidx . recyclerview . widget . Linear LayoutManager Ċ import Ġandroidx . recyclerview . widget . RecyclerView Ċ import Ġby . kir ich 1 4 0 9 . view binding delegate . view Binding Ċ import Ġcom . cel zero . br aved ns . R Ċ import Ġcom . cel zero . br aved ns . adapter . DNS Query Adapter Ċ import Ġcom . cel zero . br aved ns . data . AppConfig Ċ import Ġcom . cel zero . br aved ns . database . DNS Log Repository Ċ import Ġcom . cel zero . br aved ns . databinding . Activity Query Detail Binding Ċ import Ġcom . cel zero . br aved ns . databinding . Query List Scroll List Binding Ċ import Ġcom . cel zero . br aved ns . glide . G lide App Ċ import Ġcom . cel zero . br aved ns . service . Persistent State Ċ import Ġcom . cel zero . br aved ns . view model . DNS Log ViewModel Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġorg . k oin . android . ext . android . inject Ċ import Ġorg . k oin . android x . view model . ext . android . viewModel Ċ import Ġjava . util .* Ċ Ċ class ĠDNS Log Fragment Ġ: ĠFragment ( R . layout . activity _ query _ detail ), ĠSearch View . On Query Text Listener Ġ{ ĊĠĠĠ Ġprivate Ġval Ġb Ġby Ġview Binding ( Activity Query Detail Binding :: bind ) ĊĊĠĠĠ Ġprivate Ġvar Ġlayout Manager : ĠRecyclerView . LayoutManager ? Ġ= Ġnull ĊĊĠĠĠ Ġprivate Ġval ĠviewModel : ĠDNS Log ViewModel Ġby ĠviewModel () ĊĠĠĠ Ġprivate Ġvar Ġchecked Item Ġ= Ġ 1 ĊĠĠĠ Ġprivate Ġvar Ġfilter Value : ĠString Ġ= Ġ"" ĊĊĠĠĠ Ġprivate Ġval Ġdns Log Repository Ġby Ġinject < DNS Log Repository >() ĊĠĠĠ Ġprivate Ġval Ġpersistent State Ġby Ġinject < Persistent State >() ĊĠĠĠ Ġprivate Ġval Ġapp Config Ġby Ġinject < AppConfig >() ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġnew Instance () Ġ= ĠDNS Log Fragment () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon View Created ( view : ĠView , ĠsavedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on View Created ( view , ĠsavedInstanceState ) ĊĠĠĠĠĠĠĠ Ġinit View () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinit View () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinclude View Ġ= Ġb . query List Scroll List ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! persistent State . logs Enabled ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinclude View . query List Logs Disabled Tv . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinclude View . query List Card View Top . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġdisplay Per Dns Ui ( include View ) ĊĠĠĠĠĠĠĠ Ġsetup Click Listeners ( include View ) ĊĠĠĠĠĠĠĠ Ġobserve Dns Stats () ĊĠĠĠĠĠĠĠ Ġobserve Dn sc rypt Status () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Click Listeners ( include View : ĠQuery List Scroll List Binding ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinclude View . query List Search . setOn Query Text Listener ( this ) ĊĠĠĠĠĠĠĠ Ġinclude View . query List Search . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinclude View . query List Search . request Focus () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinclude View . query List Search . on Action View Expanded () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġinclude View . query List Filter Icon . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshow Dns Logs Filter Dialog () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġinclude View . query List Delete Icon . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshow Dns Logs Delete Dialog () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġdisplay Per Dns Ui ( include View : ĠQuery List Scroll List Binding ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinclude View . query List Logs Disabled Tv . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġinclude View . query List Card View Top . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠ Ġinclude View . recycler Query . set Has Fixed Size ( true ) ĊĠĠĠĠĠĠĠ Ġlayout Manager Ġ= ĠLinearLayoutManager ( require Context ()) ĊĠĠĠĠĠĠĠ Ġinclude View . recycler Query . layout Manager Ġ= Ġlayout Manager ĊĊĠĠĠĠĠĠĠ Ġval Ġre cycler Adapter Ġ= ĠDNS Query Adapter ( require Context (), Ġpersistent State . fetch Fav Icon ) ĊĠĠĠĠĠĠĠ ĠviewModel . dns Logs List . observe ( view Lifecycle Owner , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġandroidx . lifecycle . Observer ( recycler Adapter :: submit List )) ĊĠĠĠĠĠĠĠ Ġinclude View . recycler Query . adapter Ġ= Ġre cycler Adapter ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġobserve Dns Stats () Ġ{ ĊĠĠĠĠĠĠĠ Ġpersistent State . dns Requests Count LiveData . observe ( view Lifecycle Owner , Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlife Time Conversion Ġ= Ġformat Decimal ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġb . total Queries Txt . text Ġ= ĠgetString ( R . string . dns _ logs _ lifetime _ queries , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlife Time Conversion ) ĊĠĠĠĠĠĠĠ Ġ}) ĊĊĠĠĠĠĠĠĠ Ġpersistent State . dns Blocked Count LiveData . observe ( view Lifecycle Owner , Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblocked Ġ= Ġformat Decimal ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġb . latency Txt . text Ġ= ĠgetString ( R . string . dns _ logs _ blocked _ queries , Ġblocked ) ĊĠĠĠĠĠĠĠ Ġ}) ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġformat Decimal ( i : ĠLong ?): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . N ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠComp act Decimal Format . getInstance ( Locale . US , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠComp act Decimal Format . Compact Style . SHORT ). format ( i ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġi . toString () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Resume () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Resume () ĊĠĠĠĠĠĠĠ Ġupdate Connected Status () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Connected Status () Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( app Config . get Dns Type ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp Config . Dns Type . DO H Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . connected Status Title Url . text Ġ= Ġresources . getString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠR . string . configure _ dns _ connected _ do h _ status ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . connected Status Title . text Ġ= Ġresources . getString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠR . string . configure _ dns _ connection _ name , Ġapp Config . get Connected DNS ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . query List Scroll List . recycler Query . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . query List Scroll List . dns Log No Log Text . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp Config . Dns Type . DN SCR YPT Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . connected Status Title Url . text Ġ= Ġresources . getString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠR . string . configure _ dns _ connected _ dns _ crypt _ status ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . query List Scroll List . recycler Query . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . query List Scroll List . dns Log No Log Text . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp Config . Dns Type . DNS _ PROXY Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . connected Status Title Url . text Ġ= Ġresources . getString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠR . string . configure _ dns _ connected _ dns _ proxy _ status ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . connected Status Title . text Ġ= Ġresources . getString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠR . string . configure _ dns _ connection _ name , Ġapp Config . get Connected DNS ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . query List Scroll List . recycler Query . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( persistent State . logs Enabled ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġb . query List Scroll List . dns Log No Log Text . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ/* ĠNo Ġop Ġ*/ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAs Ġof Ġnow , Ġthe Ġlogs Ġare Ġnot Ġshown Ġwhen Ġthe ĠDNS Ġmode Ġis Ġin ĠDNS Proxy . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSo Ġwhen Ġpx oxy Ġmode Ġis Ġchanged , Ġonly Ġon Resume () Ġwill Ġbe Ġcalled Ġas Ġit ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġis Ġsharing Ġthe Ġsame Ġactivity . Ġ( The Ġproxy Ġmode Ġchanges Ġdone Ġin Ġthe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠConfigure DNS Fragment ). ĠOther Ġlogs Ġenabled Ġstates Ġare Ġhandled Ġin Ġon View Created (). ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠFIXME : ĠCreate Ġcommon Ġobserver Ġfor Ġdns Ġinstead Ġof Ġseparate Ġob servers ĊĠĠĠ Ġprivate Ġfun Ġobserve Dn sc rypt Status () Ġ{ ĊĠĠĠĠĠĠĠ Ġapp Config . get Dn sc rypt Count Observer (). observe ( view Lifecycle Owner , Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( app Config . get Dns Type () Ġ!= ĠApp Config . Dns Type . DN SCR YPT ) Ġreturn @ observe ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġconnected Crypt Ġ= ĠgetString ( R . string . configure _ dns _ crypt , Ġit . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġb . connected Status Title . text Ġ= Ġconnected Crypt ĊĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Dns Logs Filter Dialog () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġitems Ġ= ĠarrayOf ( getString ( R . string . filter _ dns _ blocked _ connections ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetString ( R . string . filter _ dns _ all _ connections )) ĊĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= ĠAlertDialog . Builder ( require Context ()) ĊĠĠĠĠĠĠĠ Ġbuilder . setTitle ( getString ( R . string . dns _ log _ dialog _ title )) ĊĊĠĠĠĠĠĠĠ Ġ// ĠSingle - choice Ġitems Ġ( initialized Ġwith Ġchecked Ġitem ) ĊĠĠĠĠĠĠĠ Ġbuilder . set Single Choice Items ( items , Ġchecked Item ) Ġ{ Ġdialog , Ġwhich Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠRespond Ġto Ġitem Ġchosen ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠFIXME : ĠRemove Ġthe Ġis Filter Ġconstants Ġwith Ġintroduction Ġof Ġnew Ġfilter Ġoptions . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfilter Value Ġ= Ġif Ġ( which Ġ== Ġ 0 ) Ġ": is Filter " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchecked Item Ġ= Ġwhich ĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . set Filter Blocked ( filter Value ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . dismiss () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġbuilder . show () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Dns Logs Delete Dialog () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= ĠAlertDialog . Builder ( require Context ()) ĊĠĠĠĠĠĠĠ Ġbuilder . setTitle ( R . string . dns _ query _ clear _ logs _ title ) ĊĠĠĠĠĠĠĠ Ġbuilder . setMessage ( R . string . dns _ query _ clear _ logs _ message ) ĊĠĠĠĠĠĠĠ Ġbuilder . set Cancel able ( true ) ĊĠĠĠĠĠĠĠ Ġbuilder . set Positive Button ( getString ( R . string . dns _ log _ dialog _ positive )) Ġ{ Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgo Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠG lide App . get ( require Activity ()). clear Disk Cache () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdns Log Repository . clear All Data () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġbuilder . set Negative Button ( getString ( R . string . dns _ log _ dialog _ negative )) Ġ{ Ġ_, Ġ_ Ġ-> Ġ} ĊĠĠĠĠĠĠĠ Ġbuilder . create (). show () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Query Text Submit ( query : ĠString ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ ĠviewModel . set Filter ( query , Ġfilter Value ) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Query Text Change ( query : ĠString ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ ĠviewModel . set Filter ( query , Ġfilter Value ) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġgo ( f : Ġsuspend Ġ() Ġ-> ĠUnit ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġf () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ