package Ġcom . be et le stance . smart caller . data . repository Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . database . Cursor Ċ import Ġandroid . provider . Call Log . Calls Ċ import Ġandroid . provider . Contacts Contract . Common Data Kinds . Phone Ċ import Ġandroid . util . Log Ċ import Ġandroidx . paging . Paging Source Ċ import Ġcom . be et le stance . smart caller . data . datasource . store . Blocked Contacts Store Ċ import Ġcom . be et le stance . smart caller . data . entities . Blocked Contact Ċ import Ġcom . be et le stance . smart caller . data . states . Call Log Ċ import Ġcom . be et le stance . smart caller . data . states . Contact Ċ import Ġcom . be et le stance . smart caller . di . App Coroutine Dispatch ers Ċ import Ġcom . be et le stance . smart caller . di . ApplicationContext Ċ import Ġcom . be et le stance . smart caller . utils . Cursor Paging Source Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġjavax . inject . Inject Ċ Ċ class ĠContact s Repository Impl Ġ@ Inject Ġconstructor ( ĊĠĠĠ Ġ@ ApplicationContext Ġprivate Ġval Ġapplication Context : ĠContext , ĊĠĠĠ Ġprivate Ġval Ġblocked Contacts Store : ĠBlock ed Contacts Store , ĊĠĠĠ Ġprivate Ġval Ġdispatch ers : ĠApp Coroutine Dispatch ers Ċ ) Ġ: ĠContact s Repository Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġcontacts Page Source ( query : ĠString ): ĠP aging Source < Int , ĠContact > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠCursor Paging Source ( dispatch ers ) Ġ{ ĠpageSize , Ġkey Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmap Query To Contacts ( pageSize , Ġkey , Ġquery ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġcall Logs Page Source ( query : ĠString ): ĠP aging Source < Int , ĠCall Log > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠCursor Paging Source ( dispatch ers ) Ġ{ ĠpageSize , Ġkey Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmap Query To Call Logs ( pageSize , Ġkey , Ġquery ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġobserve Blocked Contacts ( query : ĠString ): ĠFlow < List < Blocked Contact >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġblocked Contacts Store . observe Contacts ( query ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun ĠaddTo Block edList ( blocked Contact : ĠBlock ed Contact ) Ġ{ ĊĠĠĠĠĠĠĠ Ġblocked Contacts Store . add Blocked Contact ( blocked Contact ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġremove From Block edList ( number : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġblocked Contacts Store . remove Blocked Contact ( number ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġmap Query To Contacts ( pageSize : ĠInt , Ġkey : ĠInt ?, Ġquery : ĠString ): ĠList < Contact > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwith Context ( dispatch ers . io ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcontacts Ġ= Ġmutable ListOf < Contact >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcursor : ĠCursor ? Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġsort Ġ= ĠPhone . DISPLAY _ NAME Ġ+ Ġ" ĠASC ĠLIMIT Ġ" Ġ+ ĠpageSize ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key Ġ!= Ġnull ) Ġsort Ġ= Ġ"$ sort ĠOFFSET Ġ$ key " ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġselection Query Ġ= Ġif Ġ( query . isNotBlank ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ Phone . NUMBER } ĠLIKE Ġ? ĠOR Ġ${ Phone . DISPLAY _ NAME } ĠLIKE Ġ? " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġselection Args Ġ= Ġif Ġ( selection Query Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ("% $ query %", Ġ"% $ query % ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcursor Ġ= Ġapplication Context . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPhone . CONTENT _ URI , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( Phone . CONTACT _ ID , ĠPhone . LOOK UP _ KEY , ĠPhone . NUMBER , ĠPhone . DISPLAY _ NAME ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselection Query , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselection Args , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsort ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcursor ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmove To First () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! is After Last ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġid : ĠInt Ġ= Ġget Int ( getColumnIndex ( Phone . CONTACT _ ID )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlookup Key : ĠString Ġ= ĠgetString ( getColumnIndex ( Phone . LOOK UP _ KEY )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnumber : ĠString Ġ= ĠgetString ( getColumnIndex ( Phone . NUMBER )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġname : ĠString Ġ= ĠgetString ( getColumnIndex ( Phone . DISPLAY _ NAME )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontacts . add ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContact ( id Ġ= Ġid , Ġname Ġ= Ġname , Ġnumber Ġ= Ġnumber , Ġlook Up Key Ġ= Ġlookup Key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmove To Next () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclose () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( java Class . simple Name , Ġe . message , Ġe . cause ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcursor ?. close () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontacts . toList () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġmap Query To Call Logs ( pageSize : ĠInt , Ġkey : ĠInt ?, Ġquery : ĠString ): ĠList < Call Log > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwith Context ( dispatch ers . io ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlogs Ġ= Ġmutable ListOf < Call Log >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcursor : ĠCursor ? Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġsort Ġ= ĠCalls . DATE Ġ+ Ġ" ĠDESC Ġ${ Calls . LIMIT _ PARAM _ KEY } Ġ" Ġ+ ĠpageSize ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( key Ġ!= Ġnull ) Ġsort Ġ= Ġ"$ sort Ġ${ Calls . OFFSET _ PARAM _ KEY } Ġ$ key " ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġselection Query Ġ= Ġif Ġ( query . isNotBlank ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ Calls . NUMBER } ĠLIKE Ġ? ĠOR Ġ${ Calls . C ACHED _ NAME } ĠLIKE Ġ? " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġselection Args Ġ= Ġif Ġ( selection Query Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ("% $ query %", Ġ"% $ query % ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcursor Ġ= Ġapplication Context . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCalls . CONTENT _ URI , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( Calls . C ACHED _ NAME , ĠCalls . TYPE , ĠCalls . NUMBER ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselection Query , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselection Args , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsort ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcursor ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmove To First () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! is After Last ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnumber : ĠString Ġ= ĠgetString ( getColumnIndex ( Calls . NUMBER )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġname : ĠString ? Ġ= ĠgetString ( getColumnIndex ( Calls . C ACHED _ NAME )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcall Type : ĠInt Ġ= Ġget Int ( getColumnIndex ( Calls . TYPE )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogs . add ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCall Log ( name Ġ= Ġname Ġ?: Ġnumber , Ġnumber Ġ= Ġnumber , Ġcall Type Ġ= Ġcall Type ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmove To Next () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclose () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( java Class . simple Name , Ġe . message , Ġe . cause ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcursor ?. close () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogs . toList () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }