/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 8 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* Ġ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 Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// 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 . example . android . code labs . paging . data Ċ Ċ import Ġandroid . util . Log Ċ import Ġcom . example . android . code labs . paging . api . Github Service Ċ import Ġcom . example . android . code labs . paging . api . IN _ QUAL IFIER Ċ import Ġcom . example . android . code labs . paging . model . Repo Ċ import Ġcom . example . android . code labs . paging . model . Repo SearchResult Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . flow . Mutable Shared Flow Ċ import Ġretrofit 2 . HttpException Ċ import Ġjava . io . IOException Ċ Ċ // ĠGitHub Ġpage ĠAPI Ġis Ġ 1 Ġbased : Ġhttps :// developer . github . com / v 3 /# pagination Ċ private Ġconst Ġval ĠG ITHUB _ START ING _ PAGE _ INDEX Ġ= Ġ 1 Ċ Ċ /** Ċ Ġ* ĠRepository Ġclass Ġthat Ġworks Ġwith Ġlocal Ġand Ġremote Ġdata Ġsources . Ċ Ġ*/ Ċ class ĠGithub Repository ( private Ġval Ġservice : ĠGithub Service ) Ġ{ ĊĊĠĠĠ Ġ// Ġkeep Ġthe Ġlist Ġof Ġall Ġresults Ġreceived ĊĠĠĠ Ġprivate Ġval Ġin Memory Cache Ġ= Ġmutable ListOf < Repo >() ĊĊĠĠĠ Ġ// Ġshared Ġflow Ġof Ġresults , Ġwhich Ġallows Ġus Ġto Ġbroadcast Ġupdates Ġso ĊĠĠĠ Ġ// Ġthe Ġsubscriber Ġwill Ġhave Ġthe Ġlatest Ġdata ĊĠĠĠ Ġprivate Ġval Ġsearch Results Ġ= ĠMutable Shared Flow < Repo SearchResult >( replay Ġ= Ġ 1 ) ĊĊĠĠĠ Ġ// Ġkeep Ġthe Ġlast Ġrequested Ġpage . ĠWhen Ġthe Ġrequest Ġis Ġsuccessful , Ġincrement Ġthe Ġpage Ġnumber . ĊĠĠĠ Ġprivate Ġvar Ġlast Requested Page Ġ= ĠG ITHUB _ START ING _ PAGE _ INDEX ĊĊĠĠĠ Ġ// Ġavoid Ġtriggering Ġmultiple Ġrequests Ġin Ġthe Ġsame Ġtime ĊĠĠĠ Ġprivate Ġvar Ġis Request InProgress Ġ= Ġfalse ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSearch Ġrepositories Ġwhose Ġnames Ġmatch Ġthe Ġquery , Ġexposed Ġas Ġa Ġstream Ġof Ġdata Ġthat Ġwill Ġemit ĊĠĠĠĠ Ġ* Ġevery Ġtime Ġwe Ġget Ġmore Ġdata Ġfrom Ġthe Ġnetwork . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġsuspend Ġfun Ġget SearchResult Stream ( query : ĠString ): ĠFlow < Repo SearchResult > Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d (" Github Repository ", Ġ" New Ġquery : Ġ$ query ") ĊĠĠĠĠĠĠĠ Ġlast Requested Page Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġin Memory Cache . clear () ĊĠĠĠĠĠĠĠ Ġrequest And SaveData ( query ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsearch Results ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġrequest More ( query : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( is Request InProgress ) Ġreturn ĊĠĠĠĠĠĠĠ Ġval Ġsuccessful Ġ= Ġrequest And SaveData ( query ) ĊĠĠĠĠĠĠĠ Ġif Ġ( successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlast Requested Page ++ ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġretry ( query : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( is Request InProgress ) Ġreturn ĊĠĠĠĠĠĠĠ Ġrequest And SaveData ( query ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġrequest And SaveData ( query : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġis Request InProgress Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġvar Ġsuccessful Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġval Ġapi Query Ġ= Ġquery Ġ+ ĠIN _ QUAL IFIER ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġservice . search Repos ( api Query , Ġlast Requested Page , ĠNET WORK _ PAGE _ SIZE ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" Github Repository ", Ġ" response Ġ$ response ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrepos Ġ= Ġresponse . items Ġ?: Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġin Memory Cache . addAll ( repos ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrepos ByName Ġ= Ġrepos ByName ( query ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsearch Results . emit ( Repo SearchResult . Success ( repos ByName )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsuccessful Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( exception : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsearch Results . emit ( Repo SearchResult . Error ( exception )) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( exception : ĠHttp Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsearch Results . emit ( Repo SearchResult . Error ( exception )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġis Request InProgress Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġreturn Ġsuccessful ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrepos ByName ( query : ĠString ): ĠList < Repo > Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġfrom Ġthe Ġin Ġmemory Ġcache Ġselect Ġonly Ġthe Ġrepos Ġwhose Ġname Ġor Ġdescription Ġmatches ĊĠĠĠĠĠĠĠ Ġ// Ġthe Ġquery . ĠThen Ġorder Ġthe Ġresults . ĊĠĠĠĠĠĠĠ Ġreturn Ġin Memory Cache . filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . name . contains ( query , Ġtrue ) Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( it . description Ġ!= Ġnull Ġ&& Ġit . description . contains ( query , Ġtrue )) ĊĠĠĠĠĠĠĠ Ġ}. sorted With ( compare By Descending < Repo > Ġ{ Ġit . stars Ġ}. then By Ġ{ Ġit . name Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠNET WORK _ PAGE _ SIZE Ġ= Ġ 5 0 ĊĠĠĠ Ġ} Ċ } Ċ