diff --git a/app/src/main/java/com/droiddeck/launcher/stores/StoreInstallRoot.kt b/app/src/main/java/com/droiddeck/launcher/stores/StoreInstallRoot.kt index a7cb3f15d..09bf3c61f 100644 --- a/app/src/main/java/com/droiddeck/launcher/stores/StoreInstallRoot.kt +++ b/app/src/main/java/com/droiddeck/launcher/stores/StoreInstallRoot.kt @@ -33,9 +33,6 @@ object StoreInstallRoot { val enough: Boolean, val requiredBytes: Long, val availableBytes: Long, - val internalRequiredBytes: Long = 0L, - val internalAvailableBytes: Long = 0L, - val isInternalShortage: Boolean = false, val errorMessage: String? = null ) @@ -48,58 +45,21 @@ object StoreInstallRoot { } /** - * Estimated bytes needed for an install. Epic on internal storage needs both chunk cache - * and assembled files simultaneously (~2x game size). + * The catalog size is the known minimum for an install. Epic's actual chunk-cache requirement + * is determined from its manifest before chunk downloads begin. */ - fun estimatedBytesNeeded(item: CatalogItem, targetRoot: File, isInternal: Boolean): Long { - val size = StoreSizes.size(item) - if (size <= 0L) return 0L - return if (item.store == Store.EPIC && isInternal) size * 2 else size - } + fun estimatedBytesNeeded(item: CatalogItem): Long = StoreSizes.size(item).coerceAtLeast(0L) /** Pre-install storage check to detect insufficient space before starting. */ fun checkStorage(context: Context, item: CatalogItem, targetRoot: File): StorageCheck { - val size = StoreSizes.size(item) + val size = estimatedBytesNeeded(item) val freeTarget = availableBytes(targetRoot) if (size <= 0L) return StorageCheck(enough = true, requiredBytes = 0L, availableBytes = freeTarget) - val internal = isInternal(context, targetRoot) - if (internal) { - val needed = if (item.store == Store.EPIC) size * 2 else size - if (freeTarget in 1 until needed) { - val msg = if (item.store == Store.EPIC) { - context.getString( - com.droiddeck.launcher.R.string.stores_storage_insufficient, - formatBytes(needed), - formatBytes(freeTarget) - ) + " (" + formatBytes(size) + " + " + formatBytes(size) + " " + context.getString(com.droiddeck.launcher.R.string.stores_stage_download).lowercase() + ")" - } else { - context.getString(com.droiddeck.launcher.R.string.stores_storage_insufficient, formatBytes(needed), formatBytes(freeTarget)) - } - return StorageCheck(enough = false, requiredBytes = needed, availableBytes = freeTarget, errorMessage = msg) - } - return StorageCheck(enough = true, requiredBytes = needed, availableBytes = freeTarget) - } else { - if (freeTarget in 1 until size) { - val msg = context.getString(com.droiddeck.launcher.R.string.stores_storage_insufficient, formatBytes(size), formatBytes(freeTarget)) - return StorageCheck(enough = false, requiredBytes = size, availableBytes = freeTarget, errorMessage = msg) - } - if (item.store == Store.EPIC) { - val internalFree = availableBytes(context.cacheDir) - if (internalFree in 1 until size) { - val msg = context.getString(com.droiddeck.launcher.R.string.stores_storage_internal_cache_insufficient, formatBytes(size), formatBytes(internalFree)) - return StorageCheck( - enough = false, - requiredBytes = size, - availableBytes = freeTarget, - internalRequiredBytes = size, - internalAvailableBytes = internalFree, - isInternalShortage = true, - errorMessage = msg - ) - } - } - return StorageCheck(enough = true, requiredBytes = size, availableBytes = freeTarget) + if (freeTarget in 1 until size) { + val msg = context.getString(com.droiddeck.launcher.R.string.stores_storage_insufficient, formatBytes(size), formatBytes(freeTarget)) + return StorageCheck(enough = false, requiredBytes = size, availableBytes = freeTarget, errorMessage = msg) } + return StorageCheck(enough = true, requiredBytes = size, availableBytes = freeTarget) } /** The internal root: always there, always the default. */ diff --git a/app/src/main/java/com/droiddeck/launcher/ui/StoresInstallDialog.kt b/app/src/main/java/com/droiddeck/launcher/ui/StoresInstallDialog.kt index 4cc53ae2f..703ba2058 100644 --- a/app/src/main/java/com/droiddeck/launcher/ui/StoresInstallDialog.kt +++ b/app/src/main/java/com/droiddeck/launcher/ui/StoresInstallDialog.kt @@ -72,7 +72,7 @@ internal fun InstallWhereDialog(item: CatalogItem, onDismiss: () -> Unit) { Rise(1) { Column(verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { targets.forEachIndexed { i, t -> - val needed = com.droiddeck.launcher.stores.StoreInstallRoot.estimatedBytesNeeded(item, t.root, !t.removable) + val needed = com.droiddeck.launcher.stores.StoreInstallRoot.estimatedBytesNeeded(item) val isLow = needed > 0 && t.freeBytes in 1 until needed val freeText = if (isLow) { stringResource(R.string.stores_storage_low, formatBytes(t.freeBytes), formatBytes(needed)) diff --git a/app/src/main/java/com/droiddeck/launcher/ui/StoresPage.kt b/app/src/main/java/com/droiddeck/launcher/ui/StoresPage.kt index 2494514e4..3f005ec7b 100644 --- a/app/src/main/java/com/droiddeck/launcher/ui/StoresPage.kt +++ b/app/src/main/java/com/droiddeck/launcher/ui/StoresPage.kt @@ -511,7 +511,7 @@ private fun InstallWhere(item: CatalogItem) { StepTitle(title) StepList { targets.forEachIndexed { i, t -> - val needed = com.droiddeck.launcher.stores.StoreInstallRoot.estimatedBytesNeeded(item, t.root, !t.removable) + val needed = com.droiddeck.launcher.stores.StoreInstallRoot.estimatedBytesNeeded(item) val isLow = needed > 0 && t.freeBytes in 1 until needed val trailingText = if (isLow) { stringResource(R.string.stores_storage_low, formatBytes(t.freeBytes), formatBytes(needed)) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dd47a9882..309d6e000 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2258,7 +2258,6 @@ Internal %1$s free Not enough free space: need %1$s, only %2$s free - Not enough internal space for download cache: need %1$s, only %2$s free Insufficient space (%1$s free, need %2$s) Store downloads Shows game download progress and keeps downloads running in the background diff --git a/app/src/test/java/com/droiddeck/launcher/stores/StoreInstallRootTest.kt b/app/src/test/java/com/droiddeck/launcher/stores/StoreInstallRootTest.kt index ae1353e79..10d8b0ea4 100644 --- a/app/src/test/java/com/droiddeck/launcher/stores/StoreInstallRootTest.kt +++ b/app/src/test/java/com/droiddeck/launcher/stores/StoreInstallRootTest.kt @@ -60,16 +60,12 @@ class StoreInstallRootTest { assertEquals("a_b_c", dir.name) } - @Test fun estimatedBytesNeededCountsDoubleForEpicInternalStorage() { + @Test fun estimatedBytesNeededUsesKnownInstallSizeForAllStores() { val item = CatalogItem(Store.EPIC, "game1", "Game 1", imageUrl = null, owned = true, sizeBytes = 10_000_000L) - val internalDir = StoreInstallRoot.internalRoot(app) - val cardDir = File(app.filesDir, "card/Games") - - assertEquals(20_000_000L, StoreInstallRoot.estimatedBytesNeeded(item, internalDir, isInternal = true)) - assertEquals(10_000_000L, StoreInstallRoot.estimatedBytesNeeded(item, cardDir, isInternal = false)) + assertEquals(10_000_000L, StoreInstallRoot.estimatedBytesNeeded(item)) val gogItem = CatalogItem(Store.GOG, "game2", "Game 2", imageUrl = null, owned = true, sizeBytes = 10_000_000L) - assertEquals(10_000_000L, StoreInstallRoot.estimatedBytesNeeded(gogItem, internalDir, isInternal = true)) + assertEquals(10_000_000L, StoreInstallRoot.estimatedBytesNeeded(gogItem)) } @Test fun checkStorageReportsEnoughWhenSpaceIsUnknownOrAvailable() {