/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 2 1 ĠX iz hi ĠZ hu Ċ Ġ* Ċ Ġ* Ġ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 Ġme . x iz zh u . android . j osh ua . settings Ċ Ċ import Ġandroid . app . Application Ċ import Ġandroid . net . Uri Ċ import Ġandroidx . annotation . String Res Ċ import Ġandroidx . appcompat . app . AppCompat Delegate Ċ import Ġandroidx . lifecycle . viewModel Scope Ċ import Ġdagger . h ilt . android . lifecycle . H ilt ViewModel Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . flow . Mutable State Flow Ċ import Ġkotlinx . coroutines . flow . filter NotNull Ċ import Ġkotlinx . coroutines . flow . first Ċ import Ġkotlinx . coroutines . flow . flow Ċ import Ġkotlinx . coroutines . flow . flow On Ċ import Ġkotlinx . coroutines . flow . launch In Ċ import Ġkotlinx . coroutines . flow . on Each Ċ import Ġme . x iz zh u . android . j osh ua . R Ċ import Ġme . x iz zh u . android . j osh ua . core . Backup Manager Ċ import Ġme . x iz zh u . android . j osh ua . core . Highlight Ċ import Ġme . x iz zh u . android . j osh ua . core . Settings Ċ import Ġme . x iz zh u . android . j osh ua . core . Settings Manager Ċ import Ġme . x iz zh u . android . j osh ua . infra . Base ViewModel Ċ import Ġme . x iz zh u . android . j osh ua . infra . view Data Ċ import Ġme . x iz zh u . android . j osh ua . infra . on Failure Ċ import Ġme . x iz zh u . android . j osh ua . ui .* Ċ import Ġme . x iz zh u . android . logger . Log Ċ import Ġjava . io . IOException Ċ import Ġjavax . inject . Inject Ċ Ċ data Ġclass ĠSettings ViewData ( ĊĠĠĠĠĠĠĠ Ġval Ġcurrent FontSize Scale : ĠFloat , Ġval Ġbody Text Size In Pixel : ĠFloat , Ġval Ġcaption Text Size In Pixel : ĠFloat , ĊĠĠĠĠĠĠĠ Ġval Ġkeep Screen On : ĠBoolean , Ġval Ġnight Mode : ĠNight Mode , Ġval Ġsimple Reading Mode On : ĠBoolean , ĊĠĠĠĠĠĠĠ Ġval Ġhide Search Button : ĠBoolean , Ġval Ġcon solid ate Ver ses For Sharing : ĠBoolean , ĊĠĠĠĠĠĠĠ Ġval Ġdefault Highlight Color : ĠHighlight Color , Ġval Ġversion : ĠString Ċ ) Ġ{ ĊĠĠĠ Ġenum Ġclass ĠNight Mode ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ AppCompat Delegate . Night Mode Ġval Ġsystem Value : ĠInt , Ġ@ Settings . Companion . Night Mode Ġval Ġnight Mode : ĠInt , Ġ@ String Res Ġval Ġlabel : ĠInt ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ ĠON ( AppCompat Delegate . MODE _ N IGHT _ YES , ĠSettings . N IGHT _ MODE _ ON , ĠR . string . settings _ text _ night _ mode _ on ), ĊĠĠĠĠĠĠĠ ĠOFF ( AppCompat Delegate . MODE _ N IGHT _ NO , ĠSettings . N IGHT _ MODE _ OFF , ĠR . string . settings _ text _ night _ mode _ off ), ĊĠĠĠĠĠĠĠ ĠSYSTEM ( AppCompat Delegate . MODE _ N IGHT _ FOLLOW _ SYSTEM , ĠSettings . N IGHT _ MODE _ FOLLOW _ SYSTEM , ĠR . string . settings _ text _ night _ mode _ system ); ĊĊĠĠĠĠĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġfrom Night Mode (@ Settings . Companion . Night Mode Ġnight Mode : ĠInt ): ĠNight Mode Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalues (). first OrNull Ġ{ Ġit . night Mode Ġ== Ġnight Mode Ġ} Ġ?: ĠSYSTEM ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġenum Ġclass ĠHighlight Color (@ Highlight . Companion . Available Color Ġval Ġcolor : ĠInt , Ġ@ String Res Ġval Ġlabel : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ ĠNONE ( Highlight . COLOR _ NONE , ĠR . string . text _ highlight _ color _ none ), ĊĠĠĠĠĠĠĠ ĠY ELLOW ( Highlight . COLOR _ YELLOW , ĠR . string . text _ highlight _ color _ yellow ), ĊĠĠĠĠĠĠĠ ĠPIN K ( Highlight . COLOR _ PIN K , ĠR . string . text _ highlight _ color _ pink ), ĊĠĠĠĠĠĠĠ ĠP UR PLE ( Highlight . COLOR _ PUR PLE , ĠR . string . text _ highlight _ color _ purple ), ĊĠĠĠĠĠĠĠ ĠGREEN ( Highlight . COLOR _ GREEN , ĠR . string . text _ highlight _ color _ green ), ĊĠĠĠĠĠĠĠ ĠBL UE ( Highlight . COLOR _ BLUE , ĠR . string . text _ highlight _ color _ blue ); ĊĊĠĠĠĠĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġfrom Highlight Color (@ Highlight . Companion . Available Color Ġcolor : ĠInt ): ĠHighlight Color Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalues (). first Ġ{ Ġit . color Ġ== Ġcolor Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ H ilt ViewModel Ċ class ĠSettings ViewModel Ġ@ Inject Ġconstructor ( ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbackup Manager : ĠBackup Manager , Ġsettings Manager : ĠSettings Manager , Ġapplication : ĠApplication Ċ ) Ġ: ĠBase ViewModel ( settings Manager , Ġapplication ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġsettings ViewData : ĠMutable State Flow < ViewData < Settings ViewData > ?> Ġ= ĠMutable State Flow ( null ) ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġversion Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication . package Manager . get Package Info ( application . packageName , Ġ 0 ). version Name ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( tag , Ġ" Failed Ġto Ġload Ġapp Ġversion ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"" ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsettings (). on Each Ġ{ Ġsettings Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresources Ġ= Ġapplication . resources ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsettings ViewData . value Ġ= ĠView Data . Success ( Settings ViewData ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent FontSize Scale Ġ= Ġsettings . fontSize Scale , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbody Text Size In Pixel Ġ= Ġsettings . get Primary Text Size ( resources ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcaption Text Size In Pixel Ġ= Ġsettings . get Secondary Text Size ( resources ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkeep Screen On Ġ= Ġsettings . keep Screen On , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnight Mode Ġ= ĠSettings ViewData . Night Mode . from Night Mode ( settings . night Mode ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsimple Reading Mode On Ġ= Ġsettings . simple Reading Mode On , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhide Search Button Ġ= Ġsettings . hide Search Button , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcon solid ate Ver ses For Sharing Ġ= Ġsettings . con solid ate Ver ses For Sharing , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdefault Highlight Color Ġ= ĠSettings ViewData . Highlight Color . from Highlight Color ( settings . default Highlight Color ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġversion Ġ= Ġversion ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠ Ġ}. launch In ( viewModel Scope ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsettings ViewData (): ĠFlow < ViewData < Settings ViewData >> Ġ= Ġsettings ViewData . filter NotNull () ĊĊĠĠĠ Ġfun Ġcurrent Settings ViewData (): ĠSettings ViewData ? Ġ= Ġsettings ViewData . value ?. let Ġ{ Ġif Ġ( it Ġis ĠView Data . Success ) Ġit . data Ġelse Ġnull Ġ} ĊĊĠĠĠ Ġfun Ġsave FontSize Scale ( fontSize Scale : ĠFloat ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( fontSize Scale Ġ= ĠfontSize Scale )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġinline Ġfun Ġupdate Settings ( cross inline Ġop : Ġsuspend Ġ() Ġ-> ĠUnit ): ĠFlow < ViewData < Unit >> Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġview Data ( op ). on Failure Ġ{ ĠLog . e ( tag , Ġ" Failed Ġto Ġsave Ġsettings ", Ġit ) Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġcurrent Settings (): ĠSettings Ġ= Ġsettings (). first () ĊĊĠĠĠ Ġfun Ġsave Keep Screen On ( keep Screen On : ĠBoolean ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( keep Screen On Ġ= Ġkeep Screen On )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Night Mode ( night Mode : ĠSettings ViewData . Night Mode ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( night Mode Ġ= Ġnight Mode . night Mode )) ĊĠĠĠĠĠĠĠ ĠAppCompat Delegate . setDefault Night Mode ( night Mode . system Value ) Ġ// ĠThis Ġwill Ġrestart Ġthe Ġactivity , Ġso Ġdo Ġit ĠAFTER Ġthe Ġsettings Ġare Ġsaved . ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Simple Reading Mode On ( simple Reading Mode On : ĠBoolean ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( simple Reading Mode On Ġ= Ġsimple Reading Mode On )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Hide Search Button ( hide Search Button : ĠBoolean ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( hide Search Button Ġ= Ġhide Search Button )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Con solid ate Ver ses For Sharing ( con solid ate Ver ses : ĠBoolean ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( con solid ate Ver ses For Sharing Ġ= Ġcon solid ate Ver ses )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Default Highlight Color ( highlight Color : ĠSettings ViewData . Highlight Color ): ĠFlow < ViewData < Unit >> Ġ= Ġupdate Settings Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings Manager . save Settings ( current Settings (). copy ( default Highlight Color Ġ= Ġhighlight Color . color )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġbackup ( uri : ĠUri ?): ĠFlow < ViewData < Int >> Ġ= Ġflow Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( uri Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( ViewData . Failure ( IllegalArgumentException (" Null ĠURI "))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ flow ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġemit ( ViewData . Loading ()) ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication . content Resolver . open OutputStream ( uri ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . use Ġ{ Ġbackup Manager . backup ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠIOException (" Failed Ġto Ġopen ĠUri Ġfor Ġbackup Ġ- Ġ$ uri ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( ViewData . Success ( R . string . toast _ back ed _ up )) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( tag , Ġ" Failed Ġto Ġbackup Ġdata ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( ViewData . Failure ( e )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. flow On ( Dispatch ers . IO ) ĊĊĠĠĠ Ġfun Ġrestore ( uri : ĠUri ?): ĠFlow < ViewData < Int >> Ġ= Ġflow Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( uri Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( ViewData . Failure ( IllegalArgumentException (" Null ĠURI "))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ flow ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġemit ( ViewData . Loading ()) ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication . content Resolver . open InputStream ( uri ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . use Ġ{ Ġbackup Manager . restore ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠIOException (" Failed Ġto Ġopen ĠUri Ġfor Ġrestore Ġ- Ġ$ uri ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( ViewData . Success ( R . string . toast _ restore d )) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( t ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠException , Ġis ĠOut Of Memory Error Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCatch ing ĠOut Of Memory Error Ġhere , Ġbecause Ġthere 're Ġcases Ġwhen Ġusers Ġtry Ġto ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġopen Ġa Ġhuge Ġfile . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSee Ġhttps :// console . firebase . google . com / u / 0 / project / j osh ua - production / crash ly t ics / app / android : me . x iz zh u . android . j osh ua / issues / e 9 3 3 9 c 6 9 d 6 e 1 8 5 6 8 5 6 db 8 8 4 1 3 6 1 4 d 3 d 3 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( tag , Ġ" Failed Ġto Ġrestore Ġdata ", Ġt ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġemit ( ViewData . Failure ( t )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow Ġt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. flow On ( Dispatch ers . IO ) Ċ } Ċ