/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 ĠGoogle ĠLLC Ċ Ġ* Ċ Ġ* Ġ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 . google . samples . apps . ios ched . shared . data . user event Ċ Ċ import Ġandroidx . annotation . MainThread Ċ import Ġcom . google . android . gms . tasks . Tasks Ċ import Ġcom . google . firebase . firestore . Firebase Fire store Ċ import Ġcom . google . firebase . firestore . Set Options Ċ import Ġcom . google . samples . apps . ios ched . model . SessionId Ċ import Ġcom . google . samples . apps . ios ched . model . userdata . User Event Ċ import Ġcom . google . samples . apps . ios ched . shared . domain . users . Star Updated Status Ċ import Ġcom . google . samples . apps . ios ched . shared . result . Result Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . channels . await Close Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . flow . channel Flow Ċ import Ġkotlinx . coroutines . flow . flow Ċ import Ġkotlinx . coroutines . flow . flow On Ċ import Ġkotlinx . coroutines . suspend C ancellable Coroutine Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġtim ber . log . Tim ber Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjavax . inject . Inject Ċ import Ġkotlin . coroutines . resume Ċ import Ġkotlin . coroutines . resume With Exception Ċ Ċ /** Ċ Ġ* ĠThe Ġdata Ġsource Ġfor Ġuser Ġdata Ġstored Ġin Ġfire store . ĠIt Ġob serves Ġuser Ġdata Ġand Ġalso Ġupdates Ċ Ġ* Ġstars Ġand Ġre servations . Ċ Ġ*/ Ċ class ĠFire store User Event DataSource Ġ@ Inject Ġconstructor ( ĊĠĠĠ Ġval Ġfire store : ĠFirebase Fire store Ċ ) Ġ: ĠUser Event DataSource Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠFire store Ġconstants . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠUSER S _ COLLECTION Ġ= Ġ" users " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠEVENT S _ COLLECTION Ġ= Ġ" events " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠID Ġ= Ġ" id " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠIS _ STAR RED Ġ= Ġ" is Star red " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠAs ynchronous Ġmethod Ġto Ġget Ġthe Ġuser Ġevents . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġmethod Ġgenerates Ġimportant Ġmessages Ġto Ġthe Ġuser Ġif Ġa Ġreservation Ġis Ġconfirmed Ġor ĊĠĠĠĠ Ġ* Ġwait listed . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġget Observable User Events ( userId : ĠString ): ĠFlow < User Events Result > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( userId . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġflow Ġ{ Ġemit ( User Events Result ( emptyList ())) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( channel Flow Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġevents Collection Ġ= Ġfire store . collection ( USERS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( userId ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection ( EVENTS _ COLLECTION ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠFlow Ġrefactor Ġcheck Ġadd Snapshot Listener Ġdocumentation Ġ( null Ġvalue ?) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsubscription Ġ= Ġevents Collection . add Snapshot Listener Ġ{ Ġsnapshot , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( snapshot Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ add Snapshot Listener ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Events Ġchanges Ġdetected : Ġ${ snapshot . document Changes . size }") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠGenerate Ġimportant Ġuser Ġmessages , Ġlike Ġnew Ġre servations , Ġif Ġany . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser Events Result Ġ= ĠUser Events Result ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuser Events Ġ= Ġsnapshot . documents . map Ġ{ Ġparse User Event ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoffer ( user Events Result ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġcallback Ġinside Ġawait Close Ġwill Ġbe Ġexecuted Ġwhen Ġthe Ġchannel Ġis ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġeither Ġclosed Ġor Ġcancelled ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġawait Close Ġ{ Ġsubscription . remove () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}). flow On ( Dispatch ers . Main ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Observable User Event ( userId : ĠString , Ġevent Id : ĠSession Id ): ĠFlow < User Event Result > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( userId . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġflow Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( User Event Result ( user Event Ġ= Ġnull )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( channel Flow < User Event Result > Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġevent Document Ġ= Ġfire store . collection ( USERS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( userId ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection ( EVENTS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( eventId ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsubscription Ġ= Ġevent Document . add Snapshot Listener Ġ{ Ġsnapshot , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( snapshot Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ add Snapshot Listener ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Event Ġchanges Ġdetected Ġon Ġsession : Ġ$ eventId ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser Event Ġ= Ġif Ġ( snapshot . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparse User Event ( snapshot ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser Event Result Ġ= ĠUser Event Result ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuser Event Ġ= Ġuser Event ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . offer ( user Event Result ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġcallback Ġinside Ġawait Close Ġwill Ġbe Ġexecuted Ġwhen Ġthe Ġchannel Ġis ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġeither Ġclosed Ġor Ġcancelled ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġawait Close Ġ{ Ġsubscription . remove () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}). flow On ( Dispatch ers . Main ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ MainThread Ġ// ĠFire store Ġlimitation Ġb / 1 1 6 7 8 4 1 1 7 ĊĠĠĠ Ġoverride Ġfun ĠgetUser Events ( userId : ĠString ): ĠList < User Event > Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( userId . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġempty List () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġtask Ġ= Ġfire store . collection ( USERS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( userId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection ( EVENTS _ COLLECTION ). get () ĊĠĠĠĠĠĠĠ Ġval Ġsnapshot Ġ= ĠTasks . await ( task , Ġ 2 0 , ĠTimeUnit . SECONDS ) ĊĠĠĠĠĠĠĠ Ġreturn Ġsnapshot . documents . map Ġ{ Ġparse User Event ( it ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetUser Event ( userId : ĠString , Ġevent Id : ĠSession Id ): ĠUser Event ? Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( userId . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġtask Ġ= Ġfire store . collection ( USERS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( userId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection ( EVENTS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( eventId ). get () ĊĠĠĠĠĠĠĠ Ġval Ġsnapshot Ġ= ĠTasks . await ( task , Ġ 2 0 , ĠTimeUnit . SECONDS ) ĊĠĠĠĠĠĠĠ Ġreturn Ġparse User Event ( snapshot ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSt ars Ġor Ġun stars Ġan Ġevent . ĠThis Ġhas Ġto Ġbe Ġrun Ġon Ġthe ĠMain Ġthread Ġbecause Ġof ĠFire store ĊĠĠĠĠ Ġ* Ġlimitations . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġstar Event ( ĊĠĠĠĠĠĠĠ ĠuserId : ĠString , ĊĠĠĠĠĠĠĠ Ġuser Event : ĠUser Event ĊĠĠĠ Ġ): ĠResult < Star Updated Status > Ġ= Ġwith Context ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠThe Ġsuspend C ancellable Coroutine Ġmethod Ġsus p ends Ġa Ġcoroutine Ġmanually . ĠWith Ġthe ĊĠĠĠĠĠĠĠ Ġ// Ġcontinuation Ġobject Ġyou Ġreceive Ġin Ġthe Ġlambda , Ġyou Ġcan Ġresume Ġthe Ġcoroutine ĊĠĠĠĠĠĠĠ Ġ// Ġafter Ġthe Ġwork Ġis Ġdone . ĊĠĠĠĠĠĠĠ Ġsuspend C ancellable Coroutine < Result < Star Updated Status >> Ġ{ Ġcontinuation Ġ-> ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġmap Of ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠID Ġto Ġuser Event . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠIS _ STAR RED Ġto Ġuser Event . is Star red ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfire store . collection ( USERS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( userId ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection ( EVENTS _ COLLECTION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( user Event . id ). set ( data , ĠSet Options . merge ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Complete Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! continu ation . isActive ) Ġreturn @ add On Complete Listener ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . is Successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinuation . resume ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Success ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( user Event . is Star red ) ĠStar Updated Status . STAR RED ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠStar Updated Status . UN STAR RED ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinuation . resume ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Error ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . exception Ġ?: ĠRuntimeException (" Error Ġupdating Ġstar .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. add On Failure Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! continu ation . isActive ) Ġreturn @ add On Failure Listener ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinuation . resume With Exception ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ