From ccad82aa6d6e56518fa3e28a8bf73d6ca2c74a18 Mon Sep 17 00:00:00 2001
From: Arty Bishop <bishop.arty@gmail.com>
Date: Sun, 21 Aug 2022 12:39:22 +0100
Subject: [PATCH] Added automatic data update toggle #96

---
 .../look4sat/framework/SettingsManager.kt     |  9 +++
 .../look4sat/framework/UpdateManager.kt       | 63 +++++++++++++++++++
 .../look4sat/framework/UpdateWorker.kt        | 20 ------
 .../look4sat/presentation/MainActivity.kt     | 12 ----
 .../settingsScreen/SettingsFragment.kt        |  4 ++
 .../settingsScreen/SettingsViewModel.kt       | 11 +++-
 app/src/main/res/layout/card_other.xml        | 28 ++++++---
 app/src/main/res/values-ru/strings.xml        |  1 +
 app/src/main/res/values/strings.xml           |  1 +
 .../look4sat/domain/ISettingsManager.kt       |  4 ++
 10 files changed, 111 insertions(+), 42 deletions(-)
 create mode 100644 app/src/main/java/com/rtbishop/look4sat/framework/UpdateManager.kt
 delete mode 100644 app/src/main/java/com/rtbishop/look4sat/framework/UpdateWorker.kt

diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt
index 68c6a068..31f0207e 100644
--- a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt
@@ -33,6 +33,7 @@ class SettingsManager @Inject constructor(private val prefs: SharedPreferences)
         const val keyCompass = "compass"
         const val keyRadarSweep = "radarSweep"
         const val keyTimeUTC = "timeUTC"
+        const val keyAutoUpdate = "autoUpdate"
         const val keyHoursAhead = "hoursAhead"
         const val keyMinElevation = "minElevation"
         const val keyRotator = "isRotatorEnabled"
@@ -122,6 +123,14 @@ class SettingsManager @Inject constructor(private val prefs: SharedPreferences)
         prefs.edit { putBoolean(keyTimeUTC, value) }
     }
 
+    override fun getUpdateEnabled(): Boolean {
+        return prefs.getBoolean(keyAutoUpdate, false)
+    }
+
+    override fun setUpdateEnabled(value: Boolean) {
+        prefs.edit { putBoolean(keyAutoUpdate, value) }
+    }
+
     override fun getUseCompass(): Boolean {
         return prefs.getBoolean(keyCompass, true)
     }
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/UpdateManager.kt b/app/src/main/java/com/rtbishop/look4sat/framework/UpdateManager.kt
new file mode 100644
index 00000000..0f176f1f
--- /dev/null
+++ b/app/src/main/java/com/rtbishop/look4sat/framework/UpdateManager.kt
@@ -0,0 +1,63 @@
+/*
+ * Look4Sat. Amateur radio satellite tracker and pass predictor.
+ * Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.rtbishop.look4sat.framework
+
+import android.content.Context
+import android.util.Log
+import androidx.work.*
+import com.rtbishop.look4sat.presentation.MainApplication
+import dagger.hilt.android.qualifiers.ApplicationContext
+import java.text.DateFormat
+import java.util.*
+import java.util.concurrent.TimeUnit
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class UpdateManager @Inject constructor(@ApplicationContext context: Context) {
+
+    private val workTag = "AutoUpdateWork"
+    private val workManager = WorkManager.getInstance(context)
+
+    fun toggleAutoUpdate(isEnabled: Boolean) {
+        if (isEnabled) enableAutoUpdate() else disableAutoUpdate()
+        Log.d("UpdateManager", workManager.getWorkInfosForUniqueWork(workTag).get().toString())
+    }
+
+    private fun enableAutoUpdate() {
+        val network = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
+        val request = PeriodicWorkRequest.Builder(UpdateWorker::class.java, 24, TimeUnit.HOURS)
+            .setConstraints(network).build()
+        workManager.enqueueUniquePeriodicWork(workTag, ExistingPeriodicWorkPolicy.REPLACE, request)
+    }
+
+    private fun disableAutoUpdate() {
+        workManager.cancelUniqueWork(workTag)
+    }
+
+    class UpdateWorker constructor(private val context: Context, params: WorkerParameters) :
+        Worker(context, params) {
+
+        override fun doWork(): Result {
+            val dateTime = DateFormat.getDateTimeInstance().format(Calendar.getInstance().time)
+            Log.d("UpdateWorker", "Started periodic data update on $dateTime")
+            (context.applicationContext as MainApplication).repository.updateFromWeb()
+            return Result.success()
+        }
+    }
+}
diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/UpdateWorker.kt b/app/src/main/java/com/rtbishop/look4sat/framework/UpdateWorker.kt
deleted file mode 100644
index ea16e0fe..00000000
--- a/app/src/main/java/com/rtbishop/look4sat/framework/UpdateWorker.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.rtbishop.look4sat.framework
-
-import android.content.Context
-import android.util.Log
-import androidx.work.Worker
-import androidx.work.WorkerParameters
-import com.rtbishop.look4sat.presentation.MainApplication
-import java.text.DateFormat
-import java.util.*
-
-class UpdateWorker constructor(private val appContext: Context, workerParams: WorkerParameters) :
-    Worker(appContext, workerParams) {
-
-    override fun doWork(): Result {
-        val dateTime = DateFormat.getDateTimeInstance().format(Calendar.getInstance().time)
-        Log.d("UpdateWorker", "Started periodic data update on $dateTime")
-        (appContext.applicationContext as MainApplication).repository.updateFromWeb()
-        return Result.success()
-    }
-}
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt
index fa394993..7bdedb43 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt
@@ -31,11 +31,8 @@ import androidx.fragment.app.Fragment
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleEventObserver
 import androidx.navigation.fragment.findNavController
-import androidx.work.*
 import com.rtbishop.look4sat.databinding.ActivityMainBinding
-import com.rtbishop.look4sat.framework.UpdateWorker
 import dagger.hilt.android.AndroidEntryPoint
-import java.util.concurrent.TimeUnit
 
 @AndroidEntryPoint
 class MainActivity : AppCompatActivity() {
@@ -46,7 +43,6 @@ class MainActivity : AppCompatActivity() {
         installSplashScreen()
         super.onCreate(savedInstanceState)
         setContentView(ActivityMainBinding.inflate(layoutInflater).root)
-        refreshUpdateWorker(this)
     }
 
     override fun attachBaseContext(newBase: Context?) {
@@ -55,14 +51,6 @@ class MainActivity : AppCompatActivity() {
         applyOverrideConfiguration(newConfig)
         super.attachBaseContext(newBase)
     }
-
-    private fun refreshUpdateWorker(context: Context, workerName: String = "UpdateWorker") {
-        val workPolicy = ExistingPeriodicWorkPolicy.REPLACE
-        val network = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
-        val request = PeriodicWorkRequest.Builder(UpdateWorker::class.java, 24, TimeUnit.HOURS)
-            .setConstraints(network).build()
-        WorkManager.getInstance(context).enqueueUniquePeriodicWork(workerName, workPolicy, request)
-    }
 }
 
 fun <T> Fragment.getNavResult(@IdRes id: Int, key: String, onResult: (result: T) -> Unit) {
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt
index 62687010..5946ff38 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt
@@ -213,6 +213,10 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
                 isChecked = viewModel.getUseUTC()
                 setOnCheckedChangeListener { _, isChecked -> viewModel.setUseUTC(isChecked) }
             }
+            settingsOther.otherSwitchUpdate.apply {
+                isChecked = viewModel.getUpdateEnabled()
+                setOnCheckedChangeListener { _, isChecked -> viewModel.setUpdateEnabled(isChecked) }
+            }
             settingsOther.otherSwitchSweep.apply {
                 isChecked = viewModel.getShowSweep()
                 setOnCheckedChangeListener { _, isChecked -> viewModel.setShowSweep(isChecked) }
diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt
index fb3e74d2..c718b8e8 100644
--- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt
@@ -24,6 +24,7 @@ import com.rtbishop.look4sat.domain.ILocationManager
 import com.rtbishop.look4sat.domain.ISettingsManager
 import com.rtbishop.look4sat.domain.model.DataState
 import com.rtbishop.look4sat.domain.predict.GeoPos
+import com.rtbishop.look4sat.framework.UpdateManager
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.flow.SharedFlow
 import javax.inject.Inject
@@ -32,7 +33,8 @@ import javax.inject.Inject
 class SettingsViewModel @Inject constructor(
     private val locationManager: ILocationManager,
     private val repository: IDataRepository,
-    private val settings: ISettingsManager
+    private val settings: ISettingsManager,
+    private val updateManager: UpdateManager
 ) : ViewModel() {
 
     val entriesTotal = repository.getEntriesTotal().asLiveData()
@@ -56,6 +58,13 @@ class SettingsViewModel @Inject constructor(
 
     fun setUseUTC(value: Boolean) = settings.setUseUTC(value)
 
+    fun getUpdateEnabled(): Boolean = settings.getUpdateEnabled()
+
+    fun setUpdateEnabled(value: Boolean) {
+        updateManager.toggleAutoUpdate(value)
+        settings.setUpdateEnabled(value)
+    }
+
     fun getUseCompass(): Boolean = settings.getUseCompass()
 
     fun setUseCompass(value: Boolean) = settings.setUseCompass(value)
diff --git a/app/src/main/res/layout/card_other.xml b/app/src/main/res/layout/card_other.xml
index 61094098..b5e698bc 100644
--- a/app/src/main/res/layout/card_other.xml
+++ b/app/src/main/res/layout/card_other.xml
@@ -30,13 +30,25 @@
             android:layout_marginTop="6dp"
             android:minHeight="42dp"
             android:text="@string/other_switch_utc"
-            app:layout_constraintBottom_toTopOf="@+id/other_switch_sweep"
+            app:layout_constraintBottom_toTopOf="@+id/other_switch_update"
             app:layout_constraintEnd_toEndOf="@+id/other_title"
-            app:layout_constraintHorizontal_bias="0.5"
             app:layout_constraintStart_toStartOf="@+id/other_title"
             app:layout_constraintTop_toBottomOf="@+id/other_title"
             app:trackTint="@color/textDisabled" />
 
+        <com.google.android.material.switchmaterial.SwitchMaterial
+            android:id="@+id/other_switch_update"
+            style="@style/SettingsText"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:minHeight="42dp"
+            android:text="@string/other_switch_update"
+            app:layout_constraintBottom_toTopOf="@+id/other_switch_sweep"
+            app:layout_constraintEnd_toEndOf="@+id/other_switch_utc"
+            app:layout_constraintStart_toStartOf="@+id/other_switch_utc"
+            app:layout_constraintTop_toBottomOf="@+id/other_switch_utc"
+            app:trackTint="@color/textDisabled" />
+
         <com.google.android.material.switchmaterial.SwitchMaterial
             android:id="@+id/other_switch_sweep"
             style="@style/SettingsText"
@@ -45,10 +57,9 @@
             android:minHeight="42dp"
             android:text="@string/other_switch_sweep"
             app:layout_constraintBottom_toTopOf="@+id/other_switch_sensors"
-            app:layout_constraintEnd_toEndOf="@+id/other_switch_utc"
-            app:layout_constraintHorizontal_bias="0.5"
-            app:layout_constraintStart_toStartOf="@+id/other_switch_utc"
-            app:layout_constraintTop_toBottomOf="@+id/other_switch_utc"
+            app:layout_constraintEnd_toEndOf="@+id/other_switch_update"
+            app:layout_constraintStart_toStartOf="@+id/other_switch_update"
+            app:layout_constraintTop_toBottomOf="@+id/other_switch_update"
             app:trackTint="@color/textDisabled" />
 
         <com.google.android.material.switchmaterial.SwitchMaterial
@@ -60,9 +71,8 @@
             android:minHeight="42dp"
             android:text="@string/other_switch_sensors"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="@+id/other_switch_utc"
-            app:layout_constraintHorizontal_bias="0.5"
-            app:layout_constraintStart_toStartOf="@+id/other_switch_utc"
+            app:layout_constraintEnd_toEndOf="@+id/other_switch_sweep"
+            app:layout_constraintStart_toStartOf="@+id/other_switch_sweep"
             app:layout_constraintTop_toBottomOf="@+id/other_switch_sweep"
             app:trackTint="@color/textDisabled" />
 
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 2e504518..cc249d29 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -149,6 +149,7 @@
 
     <string name="other_title">Другие настройки</string>
     <string name="other_switch_utc">Показывать время по UTC</string>
+    <string name="other_switch_update">Обновлять данные автоматически</string>
     <string name="other_switch_sweep">Показывать анимацию радара</string>
     <string name="other_switch_sensors">Использовать сенсоры устройства</string>
 
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0403f1d1..17d6ab7a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -150,6 +150,7 @@
 
     <string name="other_title">Other preferences</string>
     <string name="other_switch_utc">Show pass time in UTC</string>
+    <string name="other_switch_update">Enable automatic data update</string>
     <string name="other_switch_sweep">Enable radar sweep animation</string>
     <string name="other_switch_sensors">Use sensors to rotate radar view</string>
 
diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt
index c0aa875e..734d11a1 100644
--- a/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt
+++ b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt
@@ -75,6 +75,10 @@ interface ISettingsManager {
 
     fun setUseUTC(value: Boolean)
 
+    fun getUpdateEnabled(): Boolean
+
+    fun setUpdateEnabled(value: Boolean)
+
     fun getUseCompass(): Boolean
 
     fun setUseCompass(value: Boolean)