Add download progress
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package io.nekohasekai.sfa.vendor
|
package io.nekohasekai.sfa.vendor
|
||||||
|
|
||||||
|
import io.nekohasekai.libbox.HTTPResponseWriteToProgressHandler
|
||||||
import io.nekohasekai.libbox.Libbox
|
import io.nekohasekai.libbox.Libbox
|
||||||
import io.nekohasekai.sfa.Application
|
import io.nekohasekai.sfa.Application
|
||||||
import io.nekohasekai.sfa.update.UpdateState
|
import io.nekohasekai.sfa.update.UpdateState
|
||||||
@@ -27,7 +28,15 @@ class ApkDownloader : Closeable {
|
|||||||
request.setURL(url)
|
request.setURL(url)
|
||||||
|
|
||||||
val response = request.execute()
|
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) {
|
if (!apkFile.exists() || apkFile.length() == 0L) {
|
||||||
throw Exception("Download failed: empty file")
|
throw Exception("Download failed: empty file")
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import androidx.compose.material3.ExtendedFloatingActionButton
|
|||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
@@ -565,10 +566,22 @@ class MainActivity :
|
|||||||
color = MaterialTheme.colorScheme.error,
|
color = MaterialTheme.colorScheme.error,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
val progress by UpdateState.downloadProgress
|
||||||
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
Column {
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
if (progress != null) {
|
||||||
Text(stringResource(R.string.downloading))
|
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
|
downloadJob = null
|
||||||
showDownloadDialog = false
|
showDownloadDialog = false
|
||||||
downloadError = null
|
downloadError = null
|
||||||
|
UpdateState.downloadProgress.value = null
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Text(stringResource(if (downloadError != null) R.string.ok else android.R.string.cancel))
|
Text(stringResource(if (downloadError != null) R.string.ok else android.R.string.cancel))
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import androidx.compose.material3.CircularProgressIndicator
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.ListItemDefaults
|
import androidx.compose.material3.ListItemDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -261,10 +262,22 @@ fun AppSettingsScreen(navController: NavController) {
|
|||||||
color = MaterialTheme.colorScheme.error,
|
color = MaterialTheme.colorScheme.error,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
val progress by UpdateState.downloadProgress
|
||||||
CircularProgressIndicator(modifier = Modifier.size(24.dp))
|
Column {
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
if (progress != null) {
|
||||||
Text(stringResource(R.string.downloading))
|
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
|
downloadJob = null
|
||||||
showDownloadDialog = false
|
showDownloadDialog = false
|
||||||
downloadError = null
|
downloadError = null
|
||||||
|
UpdateState.downloadProgress.value = null
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Text(stringResource(if (downloadError != null) R.string.ok else android.R.string.cancel))
|
Text(stringResource(if (downloadError != null) R.string.ok else android.R.string.cancel))
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ object UpdateState {
|
|||||||
val isChecking = mutableStateOf(false)
|
val isChecking = mutableStateOf(false)
|
||||||
|
|
||||||
val isDownloading = mutableStateOf(false)
|
val isDownloading = mutableStateOf(false)
|
||||||
|
val downloadProgress = mutableStateOf<Float?>(null)
|
||||||
val downloadError = mutableStateOf<String?>(null)
|
val downloadError = mutableStateOf<String?>(null)
|
||||||
|
|
||||||
val cachedApkFile = mutableStateOf<File?>(null)
|
val cachedApkFile = mutableStateOf<File?>(null)
|
||||||
@@ -38,6 +39,7 @@ object UpdateState {
|
|||||||
hasUpdate.value = false
|
hasUpdate.value = false
|
||||||
updateInfo.value = null
|
updateInfo.value = null
|
||||||
isDownloading.value = false
|
isDownloading.value = false
|
||||||
|
downloadProgress.value = null
|
||||||
downloadError.value = null
|
downloadError.value = null
|
||||||
installStatus.value = InstallStatus.Idle
|
installStatus.value = InstallStatus.Idle
|
||||||
cachedApkFile.value = null
|
cachedApkFile.value = null
|
||||||
@@ -46,6 +48,7 @@ object UpdateState {
|
|||||||
|
|
||||||
fun resetDownload() {
|
fun resetDownload() {
|
||||||
isDownloading.value = false
|
isDownloading.value = false
|
||||||
|
downloadProgress.value = null
|
||||||
downloadError.value = null
|
downloadError.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user