From bbdd64434101208a59bcb1404b155719609cf0ef Mon Sep 17 00:00:00 2001
From: LooKeR <mohit2002ss@gmail.com>
Date: Wed, 25 Dec 2024 23:40:13 +0530
Subject: [PATCH] Show a dialog if the storage is low Closes #667 This denies
 installation, so no crashes

---
 .../com/looker/droidify/ui/MessageDialog.kt   |  9 +++++++
 .../ui/appDetail/AppDetailFragment.kt         | 24 +++++++++++++------
 .../com/looker/core/common/cache/Cache.kt     |  7 ++++++
 core/common/src/main/res/values/strings.xml   |  2 ++
 4 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/app/src/main/kotlin/com/looker/droidify/ui/MessageDialog.kt b/app/src/main/kotlin/com/looker/droidify/ui/MessageDialog.kt
index 1400d0b55..bb5f500dd 100644
--- a/app/src/main/kotlin/com/looker/droidify/ui/MessageDialog.kt
+++ b/app/src/main/kotlin/com/looker/droidify/ui/MessageDialog.kt
@@ -187,6 +187,12 @@ class MessageDialog() : DialogFragment() {
                 dialog.setMessage(stringRes.incompatible_signature_DESC)
                 dialog.setPositiveButton(stringRes.ok, null)
             }
+
+            is Message.InsufficientStorage -> {
+                dialog.setTitle(stringRes.insufficient_storage)
+                dialog.setMessage(stringRes.insufficient_storage_DESC)
+                dialog.setPositiveButton(stringRes.ok, null)
+            }
         }::class
         return dialog.create()
     }
@@ -220,6 +226,9 @@ sealed interface Message : Parcelable {
 
     @Parcelize
     data object ReleaseSignatureMismatch : Message
+
+    @Parcelize
+    data object InsufficientStorage : Message
 }
 
 class ReleaseIncompatibilityParceler : Parceler<Release.Incompatibility> {
diff --git a/app/src/main/kotlin/com/looker/droidify/ui/appDetail/AppDetailFragment.kt b/app/src/main/kotlin/com/looker/droidify/ui/appDetail/AppDetailFragment.kt
index 594217536..d92d18f29 100644
--- a/app/src/main/kotlin/com/looker/droidify/ui/appDetail/AppDetailFragment.kt
+++ b/app/src/main/kotlin/com/looker/droidify/ui/appDetail/AppDetailFragment.kt
@@ -22,19 +22,20 @@ import androidx.recyclerview.widget.RecyclerView
 import androidx.recyclerview.widget.SimpleItemAnimator
 import coil.load
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.looker.core.common.cache.Cache
 import com.looker.core.common.extension.getLauncherActivities
 import com.looker.core.common.extension.getMutatedIcon
 import com.looker.core.common.extension.isFirstItemVisible
 import com.looker.core.common.extension.isSystemApplication
 import com.looker.core.common.extension.systemBarsPadding
 import com.looker.core.common.extension.updateAsMutable
+import com.looker.droidify.content.ProductPreferences
 import com.looker.droidify.model.InstalledItem
 import com.looker.droidify.model.Product
 import com.looker.droidify.model.ProductPreference
 import com.looker.droidify.model.Release
 import com.looker.droidify.model.Repository
 import com.looker.droidify.model.findSuggested
-import com.looker.droidify.content.ProductPreferences
 import com.looker.droidify.service.Connection
 import com.looker.droidify.service.DownloadService
 import com.looker.droidify.ui.Message
@@ -341,12 +342,17 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
     override fun onActionClick(action: AppDetailAdapter.Action) {
         when (action) {
             AppDetailAdapter.Action.INSTALL,
-            AppDetailAdapter.Action.UPDATE
-            -> downloadConnection.startUpdate(
-                viewModel.packageName,
-                installed?.installedItem,
-                products
-            )
+            AppDetailAdapter.Action.UPDATE -> {
+                if (Cache.getEmptySpace(requireContext()) < products.first().first.releases.first().size) {
+                    MessageDialog(Message.InsufficientStorage).show(childFragmentManager)
+                    return
+                }
+                downloadConnection.startUpdate(
+                    viewModel.packageName,
+                    installed?.installedItem,
+                    products
+                )
+            }
 
             AppDetailAdapter.Action.LAUNCH -> {
                 val launcherActivities = installed?.launcherActivities.orEmpty()
@@ -461,6 +467,10 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
                 ).show(childFragmentManager)
             }
 
+            Cache.getEmptySpace(requireContext()) < release.size -> {
+                MessageDialog(Message.InsufficientStorage).show(childFragmentManager)
+            }
+
             installedItem != null && installedItem.versionCode > release.versionCode -> {
                 MessageDialog(Message.ReleaseOlder).show(childFragmentManager)
             }
diff --git a/core/common/src/main/java/com/looker/core/common/cache/Cache.kt b/core/common/src/main/java/com/looker/core/common/cache/Cache.kt
index 18a368227..ff9904b80 100644
--- a/core/common/src/main/java/com/looker/core/common/cache/Cache.kt
+++ b/core/common/src/main/java/com/looker/core/common/cache/Cache.kt
@@ -9,6 +9,7 @@ import android.database.MatrixCursor
 import android.net.Uri
 import android.os.Build
 import android.os.ParcelFileDescriptor
+import android.os.storage.StorageManager
 import android.provider.OpenableColumns
 import android.system.Os
 import com.looker.core.common.SdkCheck
@@ -16,6 +17,7 @@ import com.looker.core.common.sdkAbove
 import java.io.File
 import java.util.UUID
 import kotlin.concurrent.thread
+import kotlin.math.min
 import kotlin.time.Duration
 import kotlin.time.Duration.Companion.days
 import kotlin.time.Duration.Companion.hours
@@ -50,6 +52,11 @@ object Cache {
         return filePath.substring(dirPath.length)
     }
 
+    fun getEmptySpace(context: Context): Long {
+        val dir = context.cacheDir
+        return min(dir.usableSpace, dir.freeSpace)
+    }
+
     fun getImagesDir(context: Context): File {
         return ensureCacheDir(context, IMAGES_DIR)
     }
diff --git a/core/common/src/main/res/values/strings.xml b/core/common/src/main/res/values/strings.xml
index a6bb7b5ac..45ff1c9f7 100644
--- a/core/common/src/main/res/values/strings.xml
+++ b/core/common/src/main/res/values/strings.xml
@@ -98,6 +98,8 @@
     <string name="install">Install</string>
     <string name="install_types">Installation Types</string>
     <string name="installer">Installer</string>
+    <string name="insufficient_storage">Insufficient Space</string>
+    <string name="insufficient_storage_DESC">There is not enough free space on the device to install this application. Try clearing some space</string>
     <string name="legacy_installer">Legacy Installer</string>
     <string name="session_installer">Session Installer</string>
     <string name="root_installer">Root Installer</string>