package Ġcom . example . android . app . ui . search Ċ Ċ import Ġandroidx . annotation . MainThread Ċ import Ġandroidx . lifecycle . ViewModel Ċ import Ġandroidx . lifecycle . viewModel Scope Ċ import Ġcom . chr yn an . inject . Inject Ċ import Ġcom . example . android . app . ui . common . Message Ċ import Ġcom . example . shared . data . repository . repo . Repo Repository Ċ import Ġcom . example . shared . data . source . local . db . Repo Ċ import Ġcom . example . shared . model . GitHub Error Ċ import Ġcom . example . shared . model . Paged Repo SearchResult Ċ import Ġcom . github . dro ib it . kom ol . K om ol Ċ import Ġdagger . h ilt . android . lifecycle . H ilt ViewModel Ċ import Ġkotlinx . coroutines . flow . Mutable State Flow Ċ import Ġkotlinx . coroutines . flow . State Flow Ċ import Ġkotlinx . coroutines . launch Ċ Ċ @ H ilt ViewModel Ċ class ĠSearch ViewModel ( ĊĠĠĠ Ġval Ġquery : ĠMutable State Flow < String >, ĊĠĠĠ Ġprivate Ġvar Ġlast Query : ĠString , ĊĠĠĠ Ġprivate Ġval Ġrepo Repository : ĠRepo Repository , ĊĠĠĠ Ġprivate Ġval Ġsearch Result Ui Model Sink : ĠMutable State Flow < SearchResult Ui Model > Ċ ) Ġ: ĠViewModel () Ġ{ ĊĊĠĠĠ Ġval Ġsearch Result Ui Model : ĠState Flow < SearchResult Ui Model > Ġget () Ġ= Ġsearch Result Ui Model Sink ĊĊĠĠĠ Ġ@ Inject ĊĠĠĠ Ġconstructor ( ĊĠĠĠĠĠĠĠ Ġrepo Repository : ĠRepo Repository , ĊĠĠĠ Ġ) Ġ: Ġthis ( ĊĠĠĠĠĠĠĠ Ġquery Ġ= ĠMutable State Flow (""), ĊĠĠĠĠĠĠĠ Ġlast Query Ġ= Ġ"", ĊĠĠĠĠĠĠĠ Ġrepo Repository Ġ= Ġrepo Repository , ĊĠĠĠĠĠĠĠ Ġsearch Result Ui Model Sink Ġ= ĠMutable State Flow ( SearchResult Ui Model ()) ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġfun Ġsearch With New Query () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( query . value Ġ== Ġlast Query ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġsearch () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ MainThread ĊĠĠĠ Ġfun Ġsearch () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( search Result Ui Model Sink . value . in Progress ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġquery Ġ= Ġthis . query . value . lowercase (). filter Not Ġ{ Ġit . is Whitespace () Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( query . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlast Query Ġ= Ġquery ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( SearchResult Ui Model ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmay Paging Ġ= Ġquery Ġ== Ġlast Query ĊĠĠĠĠĠĠĠ Ġval Ġcurrent SearchResult : ĠP aged Repo SearchResult ? Ġ= Ġif Ġ( may Paging ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsearch Result Ui Model Sink . value ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. search Result ?. take If Ġ{ Ġit . next Page Ġ!= Ġnull Ġ} Ġ?: Ġreturn ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġemit ( SearchResult Ui Model ( in Progress Ġ= Ġtrue , Ġsearch Result Ġ= Ġcurrent SearchResult )) ĊĊĠĠĠĠĠĠĠ Ġval Ġpage Ġ= Ġcurrent SearchResult ?. next Page ĊĠĠĠĠĠĠĠ ĠKom ol . d (" query =$ query , Ġpage =${ page Ġ?: Ġ" null "} ") ĊĊĠĠĠĠĠĠĠ ĠviewModel Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew SearchResult Ġ= Ġrepo Repository . search ( query , Ġpage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent Repos : ĠList < Repo > Ġ= Ġif Ġ( may Paging ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent SearchResult ?. repos Ġ?: Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Query Ġ= Ġquery ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSearch Result Ui Model ( search Result Ġ= Ġnew SearchResult . merge ( current Repos )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠGitHub Error ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSearch Result Ui Model ( error Ġ= ĠMessage ( require NotNull ( e . message ))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( result ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ MainThread ĊĠĠĠ Ġprivate Ġfun Ġemit ( ui Model : ĠSearch Result Ui Model ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsearch Result Ui Model Sink . value Ġ= Ġui Model ĊĠĠĠ Ġ} Ċ }