Add download progress

This commit is contained in:
世界
2026-03-30 22:40:29 +08:00
parent 834a5f7df0
commit 080488932f
4 changed files with 49 additions and 9 deletions

View File

@@ -1,5 +1,6 @@
package io.nekohasekai.sfa.vendor
import io.nekohasekai.libbox.HTTPResponseWriteToProgressHandler
import io.nekohasekai.libbox.Libbox
import io.nekohasekai.sfa.Application
import io.nekohasekai.sfa.update.UpdateState
@@ -27,7 +28,15 @@ class ApkDownloader : Closeable {
request.setURL(url)
val response = request.execute()
response.writeTo(apkFile.absolutePath)
response.writeToWithProgress(
apkFile.absolutePath,
object : HTTPResponseWriteToProgressHandler {
override fun update(progress: Long, total: Long) {
UpdateState.downloadProgress.value =
if (total > 0) progress.toFloat() / total.toFloat() else null
}
},
)
if (!apkFile.exists() || apkFile.length() == 0L) {
throw Exception("Download failed: empty file")

View File

@@ -42,6 +42,7 @@ import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.NavigationBar
@@ -565,10 +566,22 @@ class MainActivity :
color = MaterialTheme.colorScheme.error,
)
} else {
Row(verticalAlignment = Alignment.CenterVertically) {
CircularProgressIndicator(modifier = Modifier.size(24.dp))
Spacer(modifier = Modifier.width(12.dp))
Text(stringResource(R.string.downloading))
val progress by UpdateState.downloadProgress
Column {
if (progress != null) {
Text("${stringResource(R.string.downloading)} ${(progress!! * 100).toInt()}%")
} else {
Text(stringResource(R.string.downloading))
}
Spacer(modifier = Modifier.height(8.dp))
if (progress != null) {
LinearProgressIndicator(
progress = { progress!! },
modifier = Modifier.fillMaxWidth(),
)
} else {
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
}
}
}
}
@@ -580,6 +593,7 @@ class MainActivity :
downloadJob = null
showDownloadDialog = false
downloadError = null
UpdateState.downloadProgress.value = null
},
) {
Text(stringResource(if (downloadError != null) R.string.ok else android.R.string.cancel))

View File

@@ -47,6 +47,7 @@ import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
@@ -261,10 +262,22 @@ fun AppSettingsScreen(navController: NavController) {
color = MaterialTheme.colorScheme.error,
)
} else {
Row(verticalAlignment = Alignment.CenterVertically) {
CircularProgressIndicator(modifier = Modifier.size(24.dp))
Spacer(modifier = Modifier.width(12.dp))
Text(stringResource(R.string.downloading))
val progress by UpdateState.downloadProgress
Column {
if (progress != null) {
Text("${stringResource(R.string.downloading)} ${(progress!! * 100).toInt()}%")
} else {
Text(stringResource(R.string.downloading))
}
Spacer(modifier = Modifier.height(8.dp))
if (progress != null) {
LinearProgressIndicator(
progress = { progress!! },
modifier = Modifier.fillMaxWidth(),
)
} else {
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
}
}
}
}
@@ -276,6 +289,7 @@ fun AppSettingsScreen(navController: NavController) {
downloadJob = null
showDownloadDialog = false
downloadError = null
UpdateState.downloadProgress.value = null
},
) {
Text(stringResource(if (downloadError != null) R.string.ok else android.R.string.cancel))

View File

@@ -11,6 +11,7 @@ object UpdateState {
val isChecking = mutableStateOf(false)
val isDownloading = mutableStateOf(false)
val downloadProgress = mutableStateOf<Float?>(null)
val downloadError = mutableStateOf<String?>(null)
val cachedApkFile = mutableStateOf<File?>(null)
@@ -38,6 +39,7 @@ object UpdateState {
hasUpdate.value = false
updateInfo.value = null
isDownloading.value = false
downloadProgress.value = null
downloadError.value = null
installStatus.value = InstallStatus.Idle
cachedApkFile.value = null
@@ -46,6 +48,7 @@ object UpdateState {
fun resetDownload() {
isDownloading.value = false
downloadProgress.value = null
downloadError.value = null
}