package Ġcom . z ach ary _ m oo re . mood lights . data Ċ Ċ import Ġandroid . app . Activity Ċ import Ġandroid . app . AlertDialog Ċ import Ġandroid . content . Activity NotFoundException Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Intent Ċ import Ġandroid . graphics . Bitmap Ċ import Ġandroid . net . Uri Ċ import Ġandroid . util . Log Ċ import Ġandroidx . lifecycle . LiveData Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġandroidx . lifecycle . Observer Ċ import Ġandroidx . lifecycle . Transform ations Ċ import Ġcom . spotify . android . app remote . api . Connection Params Ċ import Ġcom . spotify . android . app remote . api . Connector Ċ import Ġcom . spotify . android . app remote . api . Spot ify App Remote Ċ import Ġcom . spotify . android . app remote . api . error . Could Not Find Spot ify App Ċ import Ġcom . spotify . android . app remote . api . error . Not LoggedIn Exception Ċ import Ġcom . spotify . protocol . types . Image Uri Ċ import Ġcom . spotify . protocol . types . Track Ċ import Ġcom . z ach ary _ m oo re . mood lights . Build Config Ċ import Ġcom . z ach ary _ m oo re . mood lights . R ĊĊ Ċ class ĠSpotify Feature Ġ{ ĊĠĠĠ Ġprivate Ġval Ġapp Remote : ĠMutable LiveData < Spot ify App Remote > Ġ= ĠMutable LiveData () ĊĠĠĠ Ġprivate Ġval Ġis Paused : ĠMutable LiveData < Boolean > Ġ= ĠMutable LiveData () ĊĠĠĠ Ġprivate Ġval Ġcurrent Track : ĠMutable LiveData < Track > Ġ= ĠMutable LiveData () ĊĠĠĠ Ġprivate Ġval Ġcurrent Playing Album Bitmap : ĠMutable LiveData < Bitmap > Ġ= ĠMutable LiveData () ĊĊĠĠĠ Ġ// ĠEx pose Ġdirect Ġmaps Ġsince Ġthey Ġare Ġimmutable ĊĠĠĠ Ġprivate Ġval Ġcurrent Playing Album Image Ġ= ĠTransform ations . distinct Until Changed ( ĊĠĠĠĠĠĠĠ ĠTransform ations . map ( current Track ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . image Uri ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ) ĊĠĠĠ Ġval Ġcurrent Track Name Ġ= ĠTransform ations . distinct Until Changed ( ĊĠĠĠĠĠĠĠ ĠTransform ations . map ( current Track ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . name ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ) ĊĠĠĠ Ġval Ġcurrent Artist Name Ġ= ĠTransform ations . distinct Until Changed ( ĊĠĠĠĠĠĠĠ ĠTransform ations . map ( current Track ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . artist . name ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ) ĊĠĠĠ Ġval Ġcurrent Album Name Ġ= ĠTransform ations . distinct Until Changed ( ĊĠĠĠĠĠĠĠ ĠTransform ations . map ( current Track ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . album . name ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġprivate Ġval Ġconnection Params Ġ= ĠConnection Params . Builder ( Build Config . spotify ClientId ) ĊĠĠĠĠĠĠĠ Ġ. set Redirect Uri ( Build Config . spotify Redirect Uri ) ĊĠĠĠĠĠĠĠ Ġ. show Auth View ( true ) ĊĠĠĠĠĠĠĠ Ġ. build () ĊĊĠĠĠ Ġprivate Ġval Ġapp Remote Observer : ĠObserver < Spot ify App Remote > Ġ= Ġget Spot ify App Remote Observer () ĊĠĠĠ Ġprivate Ġval Ġcurrent Album Image Observer : ĠObserver < Image Uri > Ġ= ĊĠĠĠĠĠĠĠ ĠgetCurrent Playing Album Image Observer () ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġapp Remote . observe Fore ver ( app Remote Observer ) ĊĠĠĠĠĠĠĠ Ġcurrent Playing Album Image . observe Fore ver ( current Album Image Observer ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġcleanup () Ġ{ ĊĠĠĠĠĠĠĠ Ġapp Remote . remove Observer ( app Remote Observer ) ĊĠĠĠĠĠĠĠ Ġcurrent Playing Album Image . remove Observer ( current Album Image Observer ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġis Paused (): ĠLive Data < Boolean > Ġ= ĠTransform ations . distinct Until Changed ( is Paused ) ĊĊĠĠĠ Ġfun Ġcurrent Playing Album Image (): ĠLive Data < Bitmap > Ġ= ĊĠĠĠĠĠĠĠ ĠTransform ations . distinct Until Changed ( current Playing Album Bitmap ) ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠToggle Ġpause Ġ/ Ġresume ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġmethod Ġis Ġassumed Ġto Ġbe Ġcalled Ġafter Ġinitial Ġplay Ġinstantiation Ġand Ġis Ġnot Ġli ved ata ĊĠĠĠĠ Ġ* Ġaware ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġtoggle Play () Ġ{ ĊĠĠĠĠĠĠĠ Ġis Paused . value ?. let Ġ{ Ġis Paused Value Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠcheckNotNull ( app Remote . value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" At tempting Ġto Ġaccess ĠApp Remote Ġbefore Ġit Ġexists " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. let Ġ{ Ġapp Remote Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Paused Value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapp Remote . player Api . resume () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapp Remote . player Api . pause () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStart Ġnext Ġsong ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġmethod Ġis Ġassumed Ġto Ġbe Ġcalled Ġafter Ġinitial Ġplay Ġinstantiation Ġand Ġis Ġnot Ġli ved ata ĊĠĠĠĠ Ġ* Ġaware ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġnext () Ġ{ ĊĠĠĠĠĠĠĠ ĠcheckNotNull ( app Remote . value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" At tempting Ġto Ġaccess ĠApp Remote Ġbefore Ġit Ġexists " ĊĠĠĠĠĠĠĠ Ġ}. player Api . skip Next () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStart Ġprevious Ġsong ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġmethod Ġis Ġassumed Ġto Ġbe Ġcalled Ġafter Ġinitial Ġplay Ġinstantiation Ġand Ġis Ġnot Ġli ved ata ĊĠĠĠĠ Ġ* Ġaware ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġprevious () Ġ{ ĊĠĠĠĠĠĠĠ ĠcheckNotNull ( app Remote . value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" At tempting Ġto Ġaccess ĠApp Remote Ġbefore Ġit Ġexists " ĊĠĠĠĠĠĠĠ Ġ}. player Api . skip Previous () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠInitialize ĠSpotify Ġremote Ġand Ġsetup Ġconnector Ġcallback ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġinitialize Remote ( activity : ĠActivity ) Ġ{ ĊĠĠĠĠĠĠĠ ĠSpotify App Remote . connect ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactivity , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconnection Params , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġobject Ġ: ĠConnector . Connection Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Failure ( throwable : ĠThrowable ?) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrowable ?. message , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrowable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Spot ify Error ( throwable , Ġactivity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Connected ( app Remote : ĠSpotify App Remote ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ Spot ify Feature . app Remote . post Value ( app Remote ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġdisconnect Remote () Ġ{ ĊĠĠĠĠĠĠĠ Ġapp Remote . value ?. let ( Spot ify App Remote :: disconnect ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠObserver Ġfor Ġa Ġ[ Spot ify App Remote ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġwill Ġsubscribe Ġto Ġthe Ġspot ify Ġplayer Ġapi , Ġand Ġon Ġstate Ġchanged Ġdispatch Ġupdates Ġto ĊĠĠĠĠ Ġ* Ġ[ is Paused ] Ġfor Ġcurrent Ġpause Ġstate Ġof Ġuser Ġand Ġ[ current Track ] Ġfor Ġthe Ġuser 's ĊĠĠĠĠ Ġ* Ġcurrent Ġplaying Ġtrack . Ġ ĠThis Ġwill Ġtrigger Ġa Ġbunch Ġof Ġside Ġtransformations Ġto Ġhappen Ġon ĊĠĠĠĠ Ġ* Ġchained Ġli ved at as ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġget Spot ify App Remote Observer () Ġ= ĠObserver < Spot ify App Remote > Ġ{ Ġapp Remote Ġ-> ĊĠĠĠĠĠĠĠ Ġapp Remote ?. player Api ?. subscribe To Player State ()?. set Event Callback Ġ{ Ġplayer State Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġare Ġon Ġa Ġbackground Ġthread , Ġneed Ġto Ġpost Ġvalues ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Paused . post Value ( player State . is Paused ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplayer State . track ?. let Ġ{ Ġcurrent Track . post Value ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠObserver Ġfor Ġcurrent Ġplaying Ġalbum Ġimage . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġwill Ġrequest Ġdown Ġand Ġget Ġa Ġbitmap Ġbased Ġoff Ġof Ġthe Ġuri . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġfunction Ġassumes Ġapp Ġremote Ġhas Ġa Ġvalue Ġrather Ġthan Ġmedi ating Ġwith Ġit ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun ĠgetCurrent Playing Album Image Observer () Ġ= ĊĠĠĠĠĠĠĠ ĠObserver < Image Uri > Ġ{ Ġcurrent Playing Album Image Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠcheckNotNull ( app Remote . value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" App Ġremote Ġdoesn 't Ġexist Ġafter Ġtrack Ġfound Ġwhile Ġtrying Ġto Ġget Ġbitmap Ġfor Ġalbum Ġimage " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . images Api . getImage ( current Playing Album Image ). set Result Callback Ġ{ Ġresult Bitmap Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Playing Album Bitmap . post Value ( result Bitmap ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Spot ify Feature " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval Ġapp PackageName Ġ= Ġ" com . spotify . music " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval Ġref errer Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" adjust _ campaign = PACKAGE _ NAME & adjust _ tracker = nd j cz k & utm _ source = adjust _ pre install " ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġprompt Spot ify Download ( context : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuri : ĠUri Ġ= ĠUri . parse (" market :// details ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build Up on () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append QueryParameter (" id ", Ġapp PackageName ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append QueryParameter (" referrer ", Ġref errer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . startActivity ( Intent ( Intent . ACTION _ VIEW , Ġuri )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignored : ĠActivity NotFoundException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuri : ĠUri Ġ= ĠUri . parse (" https :// play . google . com / store / apps / details ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build Up on () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append QueryParameter (" id ", Ġapp PackageName ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. append QueryParameter (" referrer ", Ġref errer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . startActivity ( Intent ( Intent . ACTION _ VIEW , Ġuri )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġlaunch Spot ify For Login ( context : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuri : ĠUri Ġ= ĠUri . parse (" spotify :") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build Up on () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . startActivity ( Intent ( Intent . ACTION _ VIEW , Ġuri ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput Extra ( Intent . EXTRA _ REF ERR ER , Ġcontext . packageName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġhandle Spot ify Error ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrowable : ĠThrowable ?, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactivity : ĠActivity ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( throwable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠCould Not Find Spot ify App Ġ-> ĠAlertDialog . Builder ( activity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setTitle ( R . string . mood light _ could _ not _ find _ spotify _ title ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setMessage ( R . string . mood light _ could _ not _ find _ spotify _ description ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Positive Button ( R . string . mood light _ could _ not _ find _ spotify _ go _ to _ download ) Ġ{ Ġdialog , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . dismiss () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprompt Spot ify Download ( activity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Negative Button ( R . string . mood light _ could _ not _ find _ spotify _ cancel ) Ġ{ Ġdialog , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . dismiss () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. show () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠNot LoggedIn Exception Ġ-> ĠAlertDialog . Builder ( activity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setTitle ( R . string . mood light _ spotify _ login _ fail _ title ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setMessage ( R . string . mood light _ spotify _ login _ fail _ description ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Positive Button ( R . string . mood light _ spotify _ login _ fail _ launch _ spotify ) Ġ{ Ġdialog , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . dismiss () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch Spot ify For Login ( activity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Negative Button ( R . string . mood light _ spotify _ login _ fail _ cancel ) Ġ{ Ġdialog , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . dismiss () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. show () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }