Add visibility for the user during app restoring

When the app is restoring the button's text will be constantly updated
until the app is restored.

Test: manual

Bug: 304255818
Change-Id: Id5da0923e5f9f3e45889e10c017a3f3dc3f8bd95
This commit is contained in:
Mark Kim
2024-01-02 17:24:05 +00:00
parent 6f20548c55
commit 23c5574e01
2 changed files with 48 additions and 2 deletions

View File

@@ -3945,6 +3945,14 @@
<string name="archive">Archive</string>
<!-- Manage applications, text label for button to restore an application. Restoring means installing the archived app. -->
<string name="restore">Restore</string>
<!-- Manage applications, text label for button while the application is restoring. -->
<string name="restoring_step_one">Restoring</string>
<!-- Manage applications, text label for button while the application is restoring. -->
<string name="restoring_step_two">Restoring.</string>
<!-- Manage applications, text label for button while the application is restoring. -->
<string name="restoring_step_three">Restoring..</string>
<!-- Manage applications, text label for button while the application is restoring. -->
<string name="restoring_step_four">Restoring...</string>
<!-- Manage applications, individual application info screen,label under Storage heading. The total storage space taken up by this app. -->
<string name="total_size_label">Total</string>
<!-- Manage applications, individual application info screen, label under Storage heading. The amount of space taken up by the application itself (for example, the java compield files and things like that) -->

View File

@@ -27,9 +27,18 @@ import android.widget.Toast
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.CloudDownload
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
import com.android.settingslib.spa.widget.button.ActionButton
import com.android.settingslib.spaprivileged.framework.compose.DisposableBroadcastReceiverAsUser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
class AppRestoreButton(packageInfoPresenter: PackageInfoPresenter) {
private companion object {
@@ -43,6 +52,16 @@ class AppRestoreButton(packageInfoPresenter: PackageInfoPresenter) {
private val packageName = packageInfoPresenter.packageName
private val userHandle = UserHandle.of(packageInfoPresenter.userId)
private var broadcastReceiverIsCreated = false
private lateinit var coroutineScope: CoroutineScope
private lateinit var updateButtonTextJob: Job
private val buttonTexts = intArrayOf(
R.string.restore,
R.string.restoring_step_one,
R.string.restoring_step_two,
R.string.restoring_step_three,
R.string.restoring_step_four,
)
private var buttonTextIndexStateFlow = MutableStateFlow(0)
@Composable
fun getActionButton(app: ApplicationInfo): ActionButton {
@@ -55,10 +74,17 @@ class AppRestoreButton(packageInfoPresenter: PackageInfoPresenter) {
}
broadcastReceiverIsCreated = true
}
coroutineScope = rememberCoroutineScope()
if (app.isArchived && ::updateButtonTextJob.isInitialized && !updateButtonTextJob.isActive) {
buttonTextIndexStateFlow.value = 0
}
return ActionButton(
text = context.getString(R.string.restore),
text = context.getString(
buttonTexts[
buttonTextIndexStateFlow.asStateFlow().collectAsStateWithLifecycle(0).value]
),
imageVector = Icons.Outlined.CloudDownload,
enabled = app.isArchived
enabled = app.isArchived && (!::updateButtonTextJob.isInitialized || !updateButtonTextJob.isActive)
) { onRestoreClicked(app) }
}
@@ -87,6 +113,18 @@ class AppRestoreButton(packageInfoPresenter: PackageInfoPresenter) {
when (val unarchiveStatus =
intent.getIntExtra(PackageInstaller.EXTRA_UNARCHIVE_STATUS, Int.MIN_VALUE)) {
PackageInstaller.UNARCHIVAL_OK -> {
// updateButtonTextJob will be canceled automatically once
// AppButtonsPresenter#getActionButtons is triggered
updateButtonTextJob = coroutineScope.launch {
while (isActive) {
var index = buttonTextIndexStateFlow.value
index = (index + 1) % buttonTexts.size
// The initial state shouldn't be used here
if (index == 0) index++
buttonTextIndexStateFlow.emit(index)
delay(1000)
}
}
val appLabel = userPackageManager.getApplicationLabel(app)
Toast.makeText(
context,