package Ġfragments Ċ Ċ import Ġadapters . chat . Chat Recycler Adapter Ċ import Ġandroid . app . Activity Ċ import Ġandroid . content . Content Values Ċ import Ġandroid . content . Intent Ċ import Ġandroid . content . res . Asset FileDescriptor Ċ import Ġandroid . net . Uri Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . provider . Media Store Ċ import Ġandroid . text . format . Formatter Ċ import Ġandroid . view . LayoutInflater Ċ import Ġandroid . view . View Ċ import Ġandroid . view . ViewGroup Ċ import Ġandroid . view . input method . Editor Info Ċ import Ġandroidx . activity . result . Activity Result Launcher Ċ import Ġandroidx . activity . result . contract . Activity Result Contracts Ċ import Ġandroidx . fragment . app . Fragment Ċ import Ġandroidx . fragment . app . activity ViewModels Ċ import Ġandroidx . recyclerview . widget . Linear LayoutManager Ċ import Ġcom . example . peer 2 party . databinding . Fragment Chat Binding Ċ import Ġdata . Message Ċ import Ġdata . MessageType Ċ import Ġhelpers . DateTime Helper . fetch DateTime Ċ import Ġnetwork er . helpers . Network Utilities Ċ import Ġnetwork er . messages . Message Declaration Ċ import Ġnetwork er . messages . Message Intent Ċ import Ġview models . Main ViewModel ĊĊ Ċ class ĠChat Fragment Ġ: ĠFragment () Ġ{ ĊĊĠĠĠ Ġprivate Ġval ĠviewModel Ġby Ġactivity ViewModels < Main ViewModel >() ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġchat Adapter : ĠChat Recycler Adapter ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġlayout Manager : ĠLinearLayoutManager ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġbinding : ĠFragment Chat Binding ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġfile Selector Launcher : ĠActivity Result Launcher < Intent > ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġcam Photo Launcher : ĠActivity Result Launcher < Intent > ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġcam Video Launcher : ĠActivity Result Launcher < Intent > ĊĠĠĠ Ġprivate Ġvar Ġcamera Media Uri : ĠUri Ġ= ĠUri . EMPTY ĊĊĠĠĠ Ġ// FIX ME Ġscroll Ġre cycler Ġto Ġbottom Ġon Ġapp Ġstart ĊĠĠĠ Ġprivate Ġfun Ġsetup Recycler () Ġ{ ĊĠĠĠĠĠĠĠ Ġlayout Manager Ġ= ĠLinearLayoutManager ( require Activity ()) ĊĠĠĠĠĠĠĠ Ġchat Adapter Ġ= ĠChat Recycler Adapter ( require Activity ()) ĊĠĠĠĠĠĠĠ Ġbinding . chat Recycler . layout Manager Ġ= Ġlayout Manager ĊĠĠĠĠĠĠĠ Ġbinding . chat Recycler . adapter Ġ= Ġchat Adapter ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġattach Listeners () Ġ{ ĊĠĠĠĠĠĠĠ ĠviewModel . all Messages . observe ( require Activity ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchat Adapter . set Messages ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( layout Manager . find Last Visible Item Position () Ġ== Ġit . size Ġ- Ġ 2 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlayout Manager . scrollTo Position ( it . size Ġ- Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġbinding . button Send . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsend Text () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġbinding . select Operation . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvisibility Ġ= Ġbinding . operations Layout . visibility ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( visibility Ġ!= ĠView . VISIBLE ) Ġbinding . operations Layout . visibility Ġ= ĠView . VISIBLE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġbinding . operations Layout . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// cause Ġandroid . ĊĠĠĠĠĠĠĠ Ġbinding . textInput . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . operations Layout . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġbinding . textInput . setOn Focus ChangeListener Ġ{ Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . operations Layout . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġbinding . textInput . setOn Editor ActionListener Ġ{ Ġ_, Ġaction Id , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ setOn Editor ActionListener Ġwhen Ġ( action Id ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEditor Info . IME _ ACTION _ SEND Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend Text () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġbinding . select File . setOnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( Intent . ACTION _ OPEN _ DOCUMENT ). also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . add Category ( Intent . CATEGORY _ OP ENABLE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . type Ġ= Ġ"* /* " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// it . putExtra ( Intent . EXTRA _ ALLOW _ MULTIPLE , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . add Flags ( Intent . FLAG _ GRANT _ PER SIST ABLE _ URI _ PERMISSION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . add Flags ( Intent . FLAG _ GRANT _ READ _ URI _ PERMISSION ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . add Flags ( Intent . FLAG _ GRANT _ WRITE _ URI _ PERMISSION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfile Selector Launcher . launch ( intent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . operations Layout . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġbinding . open Cam Photo . setOnClickListener Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcamera Media Uri Ġ= Ġrequire Context (). content Resolver . insert ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMedia Store . Images . Media . EXTERNAL _ CONTENT _ URI , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContent Values () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) !! ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( Media Store . ACTION _ IMAGE _ CAPTURE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġintent . putExtra ( Media Store . EXTRA _ OUTPUT , Ġcamera Media Uri ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcam Photo Launcher . launch ( intent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . operations Layout . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġbinding . open Cam Video . setOnClickListener Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcamera Media Uri Ġ= Ġrequire Context (). content Resolver . insert ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMedia Store . Video . Media . EXTERNAL _ CONTENT _ URI , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContent Values () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) !! ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( Media Store . ACTION _ VIDEO _ CAPTURE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġintent . putExtra ( Media Store . EXTRA _ OUTPUT , Ġcamera Media Uri ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcam Video Launcher . launch ( intent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . operations Layout . visibility Ġ= ĠView . GONE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Activity Launch ers () Ġ{ ĊĠĠĠĠĠĠĠ Ġfile Selector Launcher Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġregister For Activity Result ( Activity Result Contracts . Start Activity For Result ()) Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . result Code Ġ== ĠActivity . RESULT _ OK ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata : ĠIntent ? Ġ= Ġresult . data ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparsed Uri Ġ= ĠUri . parse ( data !!. data String ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcontent Resolver Ġ= Ġrequire Context (). content Resolver ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontent Resolver . take Persist able Uri Permission ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparsed Uri !! , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠIntent . FLAG _ GRANT _ READ _ URI _ PERMISSION ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtype Ġ= Ġcontent Resolver . getType ( parsed Uri ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(" image " Ġin Ġtype !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend Image ( parsed Uri ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// TODO Ġsave Ġimages Ġ? Ġ( fetch Ġstate Ġfrom Ġsettings Ġactivity ) ĊĠĠĠĠĠĠĠ Ġcam Photo Launcher Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġregister For Activity Result ( Activity Result Contracts . Start Activity For Result ()) Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . result Code Ġ== ĠActivity . RESULT _ OK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend Image ( camera Media Uri ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcam Video Launcher Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġregister For Activity Result ( Activity Result Contracts . Start Activity For Result ()) Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . result Code Ġ== ĠActivity . RESULT _ OK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// send Video ( camera Media Uri ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsend Text () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtext ToSend Ġ= Ġbinding . textInput . text . toString () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( text ToSend . isNotBlank () Ġ&& Ġtext ToSend . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsize Ġ= ĠNetwork Utilities . convert UTF 8 StringTo Bytes ( text ToSend ). size ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Intent Ġ= ĠMessage Intent ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . our self , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . room Wrapper . get Enabled Users () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Intent . addMessage Declaration ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMessage Declaration ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"", Ġtext ToSend , Ġnull , Ġ 0 , Ġsize , Ġnetwork er . messages . MessageType . TEXT ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel . send ( message Intent ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġbinding . textInput . setText ("") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsend Image ( uri : ĠUri ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġfd : ĠAsset FileDescriptor Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequire Context (). content Resolver . open Asset FileDescriptor ( uri , Ġ" r ") !! ĊĊĠĠĠĠĠĠĠ Ġval Ġsize Ġ= ĠFormatter . format FileSize ( require Context (), Ġfd . length ) ĊĊĠĠĠĠĠĠĠ ĠviewModel . insert Entity ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMessage ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMessageType . IMAGE _ SEND , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuri . toString (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfetch DateTime (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsize . toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate View ( ĊĠĠĠĠĠĠĠ Ġinflater : ĠLayoutInflater , Ġcontainer : ĠViewGroup ?, ĊĠĠĠĠĠĠĠ ĠsavedInstanceState : ĠBundle ? ĊĠĠĠ Ġ): ĠView Ġ{ ĊĠĠĠĠĠĠĠ Ġbinding Ġ= ĠFragment Chat Binding . inflate ( in flater , Ġcontainer , Ġfalse ) ĊĊĠĠĠĠĠĠĠ Ġsetup Activity Launch ers () ĊĠĠĠĠĠĠĠ Ġreturn Ġbinding . root ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon View Created ( view : ĠView , ĠsavedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on View Created ( view , ĠsavedInstanceState ) ĊĊĠĠĠĠĠĠĠ Ġsetup Recycler () ĊĠĠĠĠĠĠĠ Ġattach Listeners () ĊĠĠĠ Ġ} Ċ }