package Ġcom . ash devtools . app Ċ Ċ import Ġandroid . app . Notification Channel Ċ import Ġandroid . app . Notification Manager Ċ import Ġandroid . content . Context Ċ import Ġandroid . net . Uri Ċ import Ġandroid . os . Build Ċ import Ġandroid . util . Log Ċ import Ġandroidx . core . app . Notification Compat Ċ import Ġandroidx . work .* Ċ import Ġcom . google . firebase . auth . Firebase Auth Ċ import Ġcom . google . firebase . firestore . Collection Reference Ċ import Ġcom . google . firebase . firestore . Document Reference Ċ import Ġcom . google . firebase . firestore . Firebase Fire store Ċ import Ġcom . google . firebase . storage . Firebase Storage Ċ import Ġcom . google . firebase . storage . Storage Reference Ċ import Ġio . flutter . plugin . common . MethodCall Ċ import Ġkotlinx . coroutines . coroutine Scope Ċ import Ġjava . io . File Ċ import Ġjava . util .* Ċ import Ġkotlin . coroutines . resume Ċ import Ġkotlin . coroutines . suspend Coroutine ĊĊ Ċ const Ġval ĠCHAN NEL _ ID Ġ= Ġ" tim y . uploads " Ċ const Ġval ĠTAG Ġ= Ġ" Upload Platform " Ċ Ċ /** Ċ Ġ* ĠLa unches Ġan Ġupload Ġmedia Ġtask . Ċ Ġ* Ċ Ġ* ĠReads Ġthe Ġ* groupId *, Ġ* channelId * Ġand Ġ* file Paths * Ġfrom ĠFlutter 's Ġ[ MethodCall ] Ċ Ġ* Ġand Ġthen Ġla unches Ġa Ġbackground Ġtask Ġ[ Upload Worker ] Ġthat : Ċ Ġ* Ċ Ġ* Ġ 1 . ĠDisplays Ġa Ġ' progress Ġbar ' Ġnotification Ġindicating Ġthat Ġfiles Ġare Ġbeing Ġuploaded . Ċ Ġ* Ġ 2 . ĠCreates Ġan Ġempty Ġmessage Ġon ĠFire store Ġwith Ġthe Ġstatus Ġ' upload ing '. Ċ Ġ* Ġ 3 . ĠUp loads Ġimages Ġone Ġby Ġone . Ċ Ġ* Ġ 4 . ĠUpdates Ġthe Ġmessage Ġwith Ġthe Ġremote Ġurls Ġfor Ġthe Ġimages . Ċ Ġ* Ġ 5 . ĠH ides Ġthe Ġnotification . Ċ Ġ* Ċ Ġ* Ġ@ param Ġcall ĠContains Ġthe Ġargument Ġdata Ġpassed Ġfrom ĠFlutter . Ċ Ġ* Ġ@ param Ġapplication Context ĠNe cessary Ġto Ġdisplay Ġnotifications Ġand Ġread Ġtranslations . Ċ Ġ*/ Ċ fun Ġupload Files Task ( call : ĠMethod Call , Ġapplication Context : ĠContext ) Ġ{ ĊĠĠĠ Ġ// ĠLoad Ġarguments Ġfrom Ġthe ĠFlutter Ġplatform Ġcall ĊĠĠĠ Ġval ĠgroupId Ġ= Ġcall . argument < String >(" groupId ") ĊĠĠĠ Ġval Ġchannel Id Ġ= Ġcall . argument < String >(" channelId ") ĊĠĠĠ Ġval Ġpaths Ġ= Ġcall . argument < List < String >> (" file Paths ") !! ĊĊĠĠĠ ĠLog . d (" Upload Platform ", Ġ" groupId : Ġ$ groupId ") ĊĠĠĠ ĠLog . d (" Upload Platform ", Ġ" channelId : Ġ$ channelId ") ĊĠĠĠ ĠLog . d (" Upload Platform ", Ġ" file Paths : Ġ$ paths ") ĊĊĠĠĠ Ġ// ĠCreate Ġand Ġlaunch Ġthe Ġbackground Ġjob ĊĠĠĠ Ġval Ġupload Work Request Ġ= ĠOne Time Work RequestBuilder < Upload Worker >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set InputData ( Data . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. putString (" groupId ", ĠgroupId ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. putString (" channelId ", Ġchannel Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. putString Array (" file Paths ", Ġpaths . to Typed Array ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ ĠWork Manager . getInstance ( application Context ). enqueue ( upload Work Request ) Ċ } Ċ Ċ /** Ċ Ġ* ĠUpload Ġworker Ġthat Ġperforms Ġthe Ġupload Ġtask Ġin Ġthe Ġbackground . Ċ Ġ* Ċ Ġ* ĠThis Ġupload Ġprocess Ġruns Ġin Ġa ĠKotlin Ġcoroutine Ġbackground Ġthread . Ċ Ġ* ĠCor outines : Ġhttps :// kotlin lang . org / docs / reference / coroutines / basics . html Ċ Ġ* Ċ Ġ* ĠWork Manager Ġtakes Ġcare Ġof Ġcontinuing Ġthe Ġtask Ġeven Ġwhen Ġthe Ġsystem Ġmay Ġdestroy / re create Ġthe Ċ Ġ* Ġapp Ġwhile Ġit Ġis Ġin Ġthe Ġbackground . Ċ Ġ* Ċ Ġ* Ġ@ param Ġapp Context ĠRequired Ġapplication Ġ[ Context ] Ġto Ġlaunch Ġthe Ġtask Ċ Ġ* Ġ@ param Ġworker Params ĠWorker Ġparameters Ġthat Ġinclude Ġ* groupId *, Ġ* channelId * Ġand Ġ* file Paths * Ċ Ġ*/ Ċ class ĠUpload Worker ( app Context : ĠContext , Ġworker Params : ĠWorker Parameters ) ĊĠĠĠ Ġ: ĠCor outine Worker ( app Context , Ġworker Params ) Ġ{ ĊĊĠĠĠ Ġ// ĠBackground Ġtask Ġthat Ġruns Ġin Ġa Ġcoroutine Ġworker Ġ( thread ) ĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġdo Work (): ĠResult Ġ= Ġcoroutine Scope Ġ{ ĊĠĠĠĠĠĠĠ Ġvar ĠgroupId : ĠString ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġvar Ġchannel Id : ĠString ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġvar ĠmessageId : ĠString ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Started Ġbackground Ġupload Ġtask ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreate Notification Channel ( application Context ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠLoad Ġpassed Ġarguments Ġto Ġworker ĊĠĠĠĠĠĠĠĠĠĠĠ ĠgroupId Ġ= Ġinput Data . getString (" groupId ") !! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Id Ġ= Ġinput Data . getString (" channelId ") !! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpaths Ġ= Ġinput Data . getString Array (" file Paths ") !! ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠShow Ġthe Ġinitial Ġnotification Ġdisplaying Ġ' Up loading Ġfiles ' Ġand Ġ' Up loading Ġ 1 Ġof Ġx ' ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġnotification Ġcannot Ġbe Ġdis missed ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshow Notification Upload ( application Context , Ġid , Ġ 0 , Ġpaths . size ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCreate Ġan Ġempty ĠMedia Ġmessage Ġwith Ġthe Ġstatus Ġ' upload ing ' ĊĠĠĠĠĠĠĠĠĠĠĠ ĠmessageId Ġ= Ġcreate Media Message ( groupId , Ġchannel Id , Ġpaths ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUpload Ġimages , Ġone Ġby Ġone , Ġand Ġreturn Ġthe Ġremote Ġurl Ġfor Ġeach Ġof Ġthem Ġin Ġa Ġlist ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġurls Ġ= Ġupload Images ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgroupId Ġ= ĠgroupId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Id Ġ= Ġchannel Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠmessageId Ġ= ĠmessageId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpaths Ġ= Ġpaths , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠtaskId Ġ= Ġid , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapplication Context Ġ= Ġapplication Context ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠGet Ġthe Ġaspect Ġratio Ġfor Ġthe Ġfirst Ġpicture , Ġnecessary Ġto Ġdisplay Ġcorrectly Ġsingle Ġimages ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġaspect Ratio : ĠString Ġ= Ġget AspectRatio From First Picture ( paths ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAdd Ġall Ġuploaded Ġurls Ġto Ġthe ĠMedia Ġmessage ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Media To Message ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgroupId Ġ= ĠgroupId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Id Ġ= Ġchannel Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠmessageId Ġ= ĠmessageId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurls Ġ= Ġurls , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaspect Ratio Ġ= Ġaspect Ratio ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Finished Ġbackground Ġupload Ġtask ") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult . success () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Upload Ġtask Ġfinished Ġwith Ġerror : Ġ$ e ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIn Ġcase Ġof Ġerror , Ġmark Ġthe Ġmedia Ġmessage Ġwith Ġthe Ġerror Ġstatus ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmark Message WithError ( groupId , Ġchannel Id , ĠmessageId ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult . failure () ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWh atever Ġthe Ġfinal Ġresult Ġwas : ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠHide Ġthe Ġupload Ġprogress Ġnotification ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhide Notification ( application Context , Ġid ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠCreates Ġan Ġempty Ġmedia Ġmessage Ġwith Ġstatus ĠUP LOADING Ċ Ġ* Ċ Ġ* ĠCreates Ġa Ġmessage Ġin ĠFire store Ġto Ġtempor ally Ġstore Ġthe Ġupload Ġstatus . Ċ Ġ* Ċ Ġ* ĠThe Ġmessage Ġwill Ġhave Ġthe Ġfollowing Ġfields : Ċ Ġ* Ċ Ġ* Ġ- Ġ' author ' Ġis Ġset Ġto Ġthe Ġcurrent Ġuser . Ċ Ġ* Ġ- Ġ' type ' Ġis Ġset Ġto ĠMED IA Ġ( to Ġdifferent iate Ġfrom ĠUSER Ġor ĠSYSTEM Ġmessages ) Ċ Ġ* Ġ- Ġ' timestamp ' Ġis Ġset Ġto Ġcurrent Ġtime , Ġbut Ġwill Ġbe Ġupdated Ġafter Ġupload . Ċ Ġ* Ġ- Ġ' media ' Ġcontains Ġthe Ġcurrent Ġlocal Ġpaths Ġ( to Ġbe Ġused Ġto Ġretry Ġuploads Ġif Ġit Ġfails ) Ċ Ġ* Ġ- Ġ' body ' Ġcontains Ġa Ġhardcoded Ġtext Ġfor Ġreference , Ġit Ġwon 't Ġbe Ġdisplayed Ġon Ġthe Ġapp Ċ Ġ* Ċ Ġ* Ġ@ param ĠgroupId ĠGroup Ġto Ġcreate Ġthe Ġmessage Ċ Ġ* Ġ@ param Ġchannel Id ĠChannel Ġto Ġcreate Ġthe Ġmessage Ċ Ġ* Ġ@ param Ġpaths ĠPaths Ġto Ġthe Ġlocal Ġfiles Ċ Ġ* Ġ@ return Ġthe Ġmessage Ġid Ċ Ġ*/ Ċ private Ġsuspend Ġfun Ġcreate Media Message ( groupId : ĠString , Ġchannel Id : ĠString , Ġpaths : ĠArray < String >): ĠString Ġ{ ĊĠĠĠ Ġval Ġuid Ġ= ĠgetUser Uid () ĊĠĠĠ Ġval Ġfire store Ġ= ĠFirebase Fire store . getInstance () ĊĠĠĠ Ġ// ĠA Ġsuspend Coroutine Ġwraps Ġany Ġcallback Ġinto Ġa Ġsynchronous Ġcoroutine ĊĠĠĠ Ġval Ġdoc Ref Ġ= Ġsuspend Coroutine < Document Reference > Ġ{ Ġcont Ġ-> ĊĠĠĠĠĠĠĠ Ġfire store . getMessage Collection ( groupId , Ġchannel Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add ( hash Map Of ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" author " Ġto Ġuid , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" type " Ġto Ġ" MEDIA ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" media _ status " Ġto Ġ" UPLOAD ING ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" timestamp " Ġto ĠDate (). time . toString (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠStore Ġthe Ġlocal Ġpaths Ġwhile Ġupload , Ġin Ġcase Ġwe Ġneed Ġto Ġretry ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" media " Ġto Ġpaths . toList (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" body " Ġto Ġ"[ media Ġmessage Ġuploading ]" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Success Listener Ġ{ Ġdocument Reference Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Document Snapshot Ġwritten Ġwith ĠID : Ġ${ document Reference . id }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcont . resume ( document Reference ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Failure Listener Ġ{ Ġe Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Error Ġadding Ġdocument ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġdoc Ref . id Ċ } Ċ Ċ /** Ċ Ġ* ĠMark Ġthe Ġmessage Ġas Ġfailed Ġ( error ) Ċ Ġ* Ċ Ġ* ĠChanges Ġthe Ġ' media _ status ' Ġfield Ġto ĠERROR . Ċ Ġ* ĠUse Ġwhen Ġsomething Ġgoes Ġwrong Ġduring Ġthe Ġupload Ġprocess . Ċ Ġ* ĠIf Ġany Ġparameter Ġis Ġnull , Ġthe Ġfunction Ġdoes Ġnot Ġdo Ġanything . Ċ Ġ* Ċ Ġ* Ġ@ param ĠgroupId ĠGroup Ġthat Ġcontains Ġthe Ġmessage Ċ Ġ* Ġ@ param Ġchannel Id ĠChannel Ġthat Ġcontains Ġthe Ġmessage Ċ Ġ* Ġ@ param ĠmessageId ĠThe Ġmessage Ġreference Ġid Ċ Ġ*/ Ċ private Ġsuspend Ġfun Ġmark Message WithError ( groupId : ĠString ?, Ġchannel Id : ĠString ?, ĠmessageId : ĠString ?) Ġ{ ĊĠĠĠ Ġif Ġ( groupId Ġ== Ġnull Ġ|| Ġchannel Id Ġ== Ġnull Ġ|| ĠmessageId Ġ== Ġnull ) Ġreturn ĊĠĠĠ Ġval Ġfire store Ġ= ĠFirebase Fire store . getInstance () ĊĠĠĠ Ġsuspend Coroutine < Boolean > Ġ{ Ġcont Ġ-> ĊĠĠĠĠĠĠĠ Ġfire store . getMessage Collection ( groupId , Ġchannel Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( message Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. update ( hash Map Of < String , ĠAny >( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" media _ status " Ġto Ġ" ERROR " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Complete Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcont . resume ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Failure Listener Ġ{ Ġe Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Error Ġmarking Ġdocument Ġwith Ġerror : Ġ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠExtension Ġfunction Ġto Ġthe Ġmessages Ġcollection Ġof Ġa Ġgroup Ġand Ġchannel Ċ Ġ*/ Ċ private Ġfun ĠFirebase Fire store . getMessage Collection ( groupId : ĠString , Ġchannel Id : ĠString ): ĠCollection Reference Ġ{ ĊĠĠĠ Ġreturn Ġcollection (" groups ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( groupId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection (" channels ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( channelId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. collection (" messages ") Ċ } Ċ Ċ /** Ċ Ġ* ĠUser ĠID Ġfrom ĠFirebase ĠAuth Ġ( which Ġis Ġthe Ġsame Ġin Ġour ĠFire store Ġdatabase ) Ċ Ġ*/ Ċ private Ġfun ĠgetUser Uid (): ĠString Ġ{ ĊĠĠĠ Ġval Ġfirebase Auth Ġ= ĠFirebase Auth . getInstance () ĊĠĠĠ Ġval Ġuid Ġ= Ġfirebase Auth . currentUser !!. uid ĊĠĠĠ Ġreturn Ġuid Ċ } Ċ Ċ /** Ċ Ġ* ĠAs pect Ġratio Ġfrom Ġthe Ġfirst Ġpicture Ġin Ġthe Ġlist Ġof Ġpaths . Ċ Ġ* Ċ Ġ* ĠThe Ġaspect Ġratio Ġis Ġused Ġwhen Ġwe Ġneed Ġto Ġdisplay Ġsingle Ġimages Ġ( so Ġthe Ġpaths Ġsize Ġis Ġ 1 ) Ċ Ġ*/ Ċ private Ġfun Ġget AspectRatio From First Picture ( paths : ĠArray < out ĠString >): ĠString Ġ{ ĊĠĠĠ Ġreturn Ġget AspectRatio ( paths . first ()). toString () Ċ } Ċ Ċ /** Ċ Ġ* ĠUpdates Ġthe Ġmessage Ġwith Ġthe Ġlist Ġof Ġuploaded Ġmedia ĠURLs Ċ Ġ* Ċ Ġ* ĠUpdates Ġthe Ġfollowing Ġfields : Ċ Ġ* Ċ Ġ* Ġ- Ġ' media ' Ġis Ġset Ġto Ġthe Ġlist Ġof Ġurls Ċ Ġ* Ġ- Ġ' media _ status ' Ġto ĠDONE Ċ Ġ* Ġ- Ġ' media _ aspect _ ratio ' Ġto Ġthe Ġcalculated Ġaspect Ġratio Ġfor Ġthe Ġfirst Ġpicture Ċ Ġ* Ġ- Ġ' timestamp ' Ġto Ġthe Ġtime Ġof Ġthis Ġupdate Ċ Ġ* Ġ- Ġ' body ' Ġchanged Ġto Ġa Ġdifferent Ġmessage Ġfor Ġdebug Ġpurposes Ċ Ġ* Ċ Ġ*/ Ċ private Ġsuspend Ġfun Ġadd Media To Message ( groupId : ĠString , Ġchannel Id : ĠString , ĠmessageId : ĠString , Ġurls : ĠList < String >, Ġaspect Ratio : ĠString ) Ġ{ ĊĠĠĠ Ġval Ġfire store Ġ= ĠFirebase Fire store . getInstance () ĊĠĠĠ Ġsuspend Coroutine < Boolean > Ġ{ Ġcont Ġ-> ĊĠĠĠĠĠĠĠ Ġfire store . getMessage Collection ( groupId , Ġchannel Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. document ( message Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. update ( hash Map Of ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" media " Ġto Ġurls , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" media _ status " Ġto Ġ" DONE ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" media _ aspect _ ratio " Ġto Ġaspect Ratio , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" timestamp " Ġto ĠDate (). time . toString (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" body " Ġto Ġ"[ media Ġmessage Ġdone ]" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Complete Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcont . resume ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Failure Listener Ġ{ Ġe Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Error Ġadding Ġdocument ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠPerforms Ġthe Ġresize Ġand Ġupload Ġimage Ġprocess Ċ Ġ* Ċ Ġ* ĠThe Ġupload Ġprocess Ġperforms Ġthe Ġfollowing Ġsteps Ġfor Ġevery Ġimage : Ċ Ġ* Ċ Ġ* Ġ 1 . ĠRes izes Ġthe Ġpicture Ċ Ġ* Ġ 2 . ĠCreates Ġa Ġstorage Ġreference Ġpointing Ġ/ channel / message Ġwith Ġthe Ġfollowing Ġstructure : Ċ Ġ* Ċ Ġ* Ġ"/ groups /{ groupId }/ channels /{ channelId }/ messages /{ message Id }/{ filename }" Ċ Ġ* Ċ Ġ* ĠNOTE : ĠThis Ġis Ġa ĠStorage Ġfile Ġreference Ġnot Ġa ĠFire store ĠDocument . Ċ Ġ* Ċ Ġ* Ġ 3 . ĠUp loads Ġthe Ġresized Ġfile Ġto Ġthat Ġstorage Ġreference . Ċ Ġ* Ġ 4 . ĠOb t ains Ġthe Ġpublic ĠURL Ġof Ġthe Ġfile . Ċ Ġ* Ġ 5 . ĠUpdates Ġthe Ġdisplayed Ġprogress Ġnotification . Ċ Ġ* Ċ Ġ* Ġ@ param Ġpaths Ġlist Ġof Ġlocal Ġfiles Ġto Ġupload Ċ Ġ* Ġ@ param ĠgroupId ĠGroup ĠId Ġto Ġcreate Ġthe Ġstorage Ġreference Ċ Ġ* Ġ@ param Ġchannel Id ĠChannel ĠId Ġ, Ġto Ġcreate Ġthe Ġstorage Ġreference Ċ Ġ* Ġ@ param ĠmessageId ĠMessage ĠId Ġ, Ġto Ġcreate Ġthe Ġstorage Ġreference Ċ Ġ* Ġ@ param ĠtaskId ĠUsed Ġto Ġidentify Ġthe Ġnotification Ġdisplayed Ċ Ġ* Ġ@ param Ġapplication Context ĠNe cessary Ġto Ġmodify Ġthe Ġnotification Ċ Ġ* Ġ@ return Ġthe Ġresulting ĠURLs Ċ Ġ*/ Ċ private Ġsuspend Ġfun Ġupload Images ( paths : ĠArray < String >, ĠgroupId : ĠString , Ġchannel Id : ĠString , ĠmessageId : ĠString , ĠtaskId : ĠUUID , Ġapplication Context : ĠContext ): ĠList < String > Ġ{ ĊĠĠĠ Ġval Ġstorage Ġ= ĠFirebase Storage . getInstance () ĊĠĠĠ Ġval Ġurls Ġ= Ġmutable ListOf < String >() ĊĠĠĠ Ġfor Ġ( path Ġin Ġpaths ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresized Ġ= Ġresize Image ( path , Ġapplication Context ) ĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( res ized ) ĊĠĠĠĠĠĠĠ Ġval Ġstorage Ref Ġ= Ġstorage . reference ĊĠĠĠĠĠĠĠ Ġ// ĠStore Ġimages Ġin Ġa Ġpath Ġequal Ġto Ġthe Ġmessage Ġin ĠFire store , Ġfor Ġeasier Ġreference ĊĠĠĠĠĠĠĠ Ġval Ġfile Ref Ġ= Ġstorage Ref . child ("/ groups /$ groupId / channels /$ channelId / messages /$ message Id /${ file . name }") ĊĠĠĠĠĠĠĠ Ġval Ġuri Ġ= ĠUri . from File ( file ) ĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġresult Ġ= Ġfile Ref . put File K ( uri )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠUpload Result . Error Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Error : Ġ" Ġ+ Ġresult . exception . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġresult . exception ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠUpload Result . Success Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurls . add ( result . url ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUpdate Ġthe Ġnotification Ġprocess Ġbar ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġshow Notification Upload ( application Context , ĠtaskId , Ġurls . size , Ġpaths . size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Success ! Ġ" Ġ+ Ġresult . url ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġurls Ċ } Ċ Ċ /** Ċ Ġ* ĠHelper Ġextension Ġfunction Ġto Ġhandle Ġthe Ġupload Ġprocess Ċ Ġ* Ċ Ġ* ĠFirst Ġwill Ġperform Ġthe Ġupload Ġwith Ġ[ Storage Reference . put File ] Ċ Ġ* Ġthen Ġwill Ġobtain Ġthe ĠURL Ġwith Ġ[ Storage Reference . get Download Url ] Ċ Ġ* Ċ Ġ* ĠBoth Ġactions Ġare Ġasynchronous Ġand Ġboth Ġcan Ġfail . Ċ Ġ* Ċ Ġ* Ġ@ return Ġ[ Upload Result ] Ġcontaining Ġthe Ġurl Ġif Ġsuccess Ġor Ġthe Ġexception Ġif Ġfailed Ċ Ġ*/ Ċ suspend Ġfun ĠStorage Reference . put File K ( uri : ĠUri ): ĠUpload Result Ġ= ĊĠĠĠĠĠĠĠ Ġsuspend Coroutine Ġ{ Ġcont Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġput File ( uri ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Failure Listener Ġ{ Ġcont . resume ( Upload Result . Error ( it )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Success Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdownload Url ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Failure Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcont . resume ( Upload Result . Error ( it )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add On Success Listener Ġ{ Ġuri Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcont . resume ( Upload Result . Success ( uri . toString ())) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ċ Ċ /** Ċ Ġ* Ġsealed Ġclass Ġto Ġhandle Ġthe Ġtwo Ġdifferent Ġcases Ġafter Ġan Ġupload Ċ Ġ* Ċ Ġ* Ġ[ Error ] Ġholds Ġthe Ġexception Ġin Ġcase Ġof Ġerror Ċ Ġ* Ġ[ Success ] Ġholds Ġthe ĠURL Ġin Ġcase Ġof Ġsuccess Ċ Ġ*/ Ċ sealed Ġclass ĠUpload Result Ġ{ ĊĠĠĠ Ġdata Ġclass ĠError ( val Ġexception : ĠException ) Ġ: ĠUpload Result () ĊĠĠĠ Ġdata Ġclass ĠSuccess ( val Ġurl : ĠString ) Ġ: ĠUpload Result () Ċ } Ċ Ċ /** Ċ Ġ* ĠDisplay Ġor Ġupdates Ġa Ġnotification Ġwith Ġa Ġprogress Ġindicator Ċ Ġ* Ċ Ġ* ĠEach Ġnotification Ġdisplayed Ġhas Ġa Ġunique ĠID Ġbased Ġon Ġthe Ġcurrent Ġupload Ġprocess . Ċ Ġ* Ċ Ġ* ĠThe Ġnotification Ġhas Ġthe Ġfollowing Ġproperties : Ċ Ġ* Ċ Ġ* Ġ- ĠTitle Ġis Ġlocalized Ċ Ġ* Ġ- ĠContent Ġtext Ġis Ġlocalized Ġand Ġcontains Ġthe Ġcurrent Ġtask Ġnumber Ġvs . Ġtotal Ġ( e . g . Ġ 1 Ġof Ġ 1 0 ) Ċ Ġ* Ġ- ĠApp Ġicon Ġused Ġas Ġthe Ġnotification Ġicon Ċ Ġ* Ġ- ĠSound Ġis Ġset Ġto Ġnull Ġto Ġmake Ġthe Ġnotification Ġsilent Ċ Ġ* Ġ- ĠOnly Ġalert Ġonce Ġis Ġto Ġupdate Ġthe Ġnotification Ġsilently Ġtoo Ċ Ġ* Ġ- ĠO ngo ing Ġmakes Ġthe Ġnotification Ġnot Ġdismiss ible Ċ Ġ* Ġ- ĠShows Ġa Ġbuilt - in Ġprogress Ġindicator Ċ Ġ* Ċ Ġ* ĠTODO : ĠCreate Ġa Ġproper Ġnotification Ġicon : Ġhttps :// github . com / jan ood le F TW / flutter - app / issues / 2 6 9 Ċ Ġ* Ċ Ġ* Ġ@ param Ġapplication Context ĠContext Ġrequired Ġfor Ġtranslations Ġand Ġto Ġobtain Ġthe Ġ[ Notification Manager ] Ċ Ġ* Ġ@ param ĠtaskId ĠWork Manager Ġunique Ġtask ĠID Ġused Ġto Ġidentify Ġthe Ġnotification Ċ Ġ* Ġ@ param Ġcurrent Task Count Ġcurrent Ġtask Ġcount , Ġfirst Ġshould Ġbe Ġ 0 Ċ Ġ* Ġ@ param Ġtotal Task Count Ġtotal Ġtask Ġcount Ċ Ġ*/ Ċ private Ġfun Ġshow Notification Upload ( application Context : ĠContext , ĠtaskId : ĠUUID , Ġcurrent Task Count : ĠInt , Ġtotal Task Count : ĠInt ) Ġ{ ĊĠĠĠ Ġ// ĠShow Ġa Ġnotification Ġwhile Ġwe Ġupload Ġfiles ĊĠĠĠ Ġval Ġnotification Manager Ġ= Ġapplication Context . getSystem Service ( Context . NOTIFICATION _ SERVICE ) Ġas ĠNotification Manager ĊĠĠĠ Ġval Ġb Ġ= ĠNotification Compat . Builder ( application Context , ĠCHAN NEL _ ID ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set When ( System . currentTimeMillis ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Title ( application Context . getString ( R . string . upload _ notification _ title )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Text ( application Context . getString ( R . string . upload _ notification _ text , Ġcurrent Task Count Ġ+ Ġ 1 , Ġtotal Task Count )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Small Icon ( R . mip map . ic _ launcher ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Sound ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Only Alert Once ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set O ngo ing ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Progress ( total Task Count , Ġcurrent Task Count , Ġfalse ) ĊĠĠĠ Ġnotification Manager . notify ( taskId . hashCode (), Ġb . build ()) Ċ } Ċ Ċ /** Ċ Ġ* ĠCreates Ġa ĠNotification ĠChannel Ġif Ġit Ġdoes Ġnot Ġexist Ċ Ġ* Ċ Ġ* ĠFrom ĠAndroid Ġ 8 . 0 , Ġapps Ġneed Ġto Ġdisplay Ġnotifications Ġinside ĠChannels . Ċ Ġ* ĠThis Ġmethod Ġcreates Ġa ĠNotification ĠChannel Ġfor ĠUp loads . Ċ Ġ* ĠSets Ġthis ĠChannel Ġsound Ġto Ġnull Ġto Ġmake Ġthese Ġnotifications Ġsilent . Ċ Ġ* Ċ Ġ* Ġ@ param Ġapplication Context Ġnecessary Ġapp Ġcontext Ċ Ġ*/ Ċ private Ġfun Ġcreate Notification Channel ( application Context : ĠContext ) Ġ{ ĊĠĠĠ Ġval Ġnotification Manager Ġ= Ġapplication Context . getSystem Service ( Context . NOTIFICATION _ SERVICE ) Ġas ĠNotification Manager ĊĠĠĠ Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . O ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġimportance Ġ= ĠNotification Manager . IMPORT ANCE _ LOW ĊĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= ĠNotification Channel ( CHANNEL _ ID , Ġ" Upload s ", Ġimportance ) ĊĠĠĠĠĠĠĠ Ġchannel . set Sound ( null , Ġnull ) ĊĠĠĠĠĠĠĠ Ġnotification Manager . create Notification Channel ( channel ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠH ides Ġa Ġnotification Ċ Ġ* Ċ Ġ* ĠUse Ġthis Ġwhen Ġwe Ġdon 't Ġneed Ġto Ġshow Ġthe Ġnotification Ġanymore Ġ( at Ġthe Ġend Ġof Ġthe Ġupload Ġprocess ) Ċ Ġ* Ċ Ġ* Ġ@ param Ġapplication Context Ġnecessary Ġapp Ġcontext Ċ Ġ* Ġ@ param Ġid Ġcurrent Ġtask ĠId Ġto Ġidentify Ġthe Ġnotification Ċ Ġ*/ Ċ private Ġfun Ġhide Notification ( application Context : ĠContext , Ġid : ĠUUID ) Ġ{ ĊĠĠĠ Ġval Ġnotification Manager Ġ= Ġapplication Context . getSystem Service ( Context . NOTIFICATION _ SERVICE ) Ġas ĠNotification Manager ĊĠĠĠ Ġnotification Manager . cancel ( id . hashCode ()) Ċ } ĊĊ