fix: save action is not invalidated when 'Quick run' action is executed (#1369)

This commit is contained in:
Akash Yadav
2023-10-09 00:55:18 +05:30
parent 52844b201e
commit abe585eba0
5 changed files with 66 additions and 64 deletions
@@ -17,13 +17,9 @@
package com.itsaky.androidide.actions
import android.text.TextUtils
import com.itsaky.androidide.lookup.Lookup
import com.itsaky.androidide.projects.builder.BuildService
import com.itsaky.androidide.tooling.api.messages.result.TaskExecutionResult
import com.itsaky.androidide.tooling.api.messages.result.TaskExecutionResult.Failure.UNKNOWN
import com.itsaky.androidide.utils.ILogger
import com.itsaky.androidide.utils.flashError
/**
* Marker class for actions that execute build related tasks.
@@ -44,49 +40,5 @@ abstract class BaseBuildAction : EditorActivityAction() {
} else {
visible = true
}
if (isBuildInProgress()) {
enabled = false
return
} else {
enabled = true
}
}
fun shouldPrepare() = visible && enabled
private fun isBuildInProgress(): Boolean {
return buildService == null || buildService?.isBuildInProgress == true
}
@JvmOverloads
protected fun execTasks(
data: ActionData,
resultHandler: (TaskExecutionResult?) -> Unit = {},
vararg tasks: String,
) {
val buildService = this.buildService ?: return
if (!buildService.isToolingServerStarted()) {
flashError(R.string.msg_tooling_server_unavailable)
return
}
val activity =
data.getActivity()
?: run {
resultHandler(TaskExecutionResult(false, UNKNOWN, ""))
return
}
activity.saveAllAsync()
buildService.executeTasks(tasks = tasks).whenComplete { result, err ->
if (result == null || err != null) {
log.error("Tasks failed to execute", TextUtils.join(", ", tasks))
}
resultHandler(result)
}
}
}
@@ -20,6 +20,11 @@ package com.itsaky.androidide.actions
import android.content.Context
import android.graphics.drawable.Drawable
import com.itsaky.androidide.activities.editor.EditorHandlerActivity
import com.itsaky.androidide.tasks.cancelIfActive
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.plus
/** @author Akash Yadav */
abstract class EditorActivityAction : ActionItem {
@@ -32,16 +37,25 @@ abstract class EditorActivityAction : ActionItem {
override var requiresUIThread: Boolean = false
protected val actionScope = CoroutineScope(Dispatchers.Default) +
CoroutineName("${javaClass.simpleName}Scope")
override fun prepare(data: ActionData) {
if (!data.hasRequiredData(Context::class.java)) {
markInvisible()
}
}
fun ActionData.getActivity() : EditorHandlerActivity? {
fun ActionData.getActivity(): EditorHandlerActivity? {
return this[Context::class.java] as? EditorHandlerActivity
}
fun ActionData.requireActivity() : EditorHandlerActivity {
fun ActionData.requireActivity(): EditorHandlerActivity {
return getActivity()!!
}
override fun destroy() {
super.destroy()
actionScope.cancelIfActive("Action is being destroyed")
}
}
@@ -21,7 +21,9 @@ import android.content.Context
import android.graphics.ColorFilter
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.text.TextUtils
import androidx.core.content.ContextCompat
import com.itsaky.androidide.R.string
import com.itsaky.androidide.actions.ActionData
import com.itsaky.androidide.actions.BaseBuildAction
import com.itsaky.androidide.actions.getContext
@@ -39,6 +41,10 @@ import com.itsaky.androidide.utils.ApkInstaller
import com.itsaky.androidide.utils.InstallationResultHandler
import com.itsaky.androidide.utils.flashError
import com.itsaky.androidide.utils.resolveAttr
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
/**
@@ -114,21 +120,47 @@ class QuickRunWithCancellationAction(context: Context, override val order: Int)
log.info(
"Running task '$taskName' to assemble variant '${variant.name}' of project '${module.path}'")
execTasks(
data,
resultHandler = { result ->
executeAsyncProvideError({ handleResult(data, result, module, variant) }) { _, error ->
if (error != null) {
log.error("Failed to process task execution result", error)
}
}
},
taskName
)
onModuleSelected(data, module, variant, taskName)
}
return true
}
private fun onModuleSelected(
data: ActionData,
module: AndroidModule,
variant: BasicAndroidVariantMetadata,
taskName: String
) {
val buildService = this.buildService ?: return
if (!buildService.isToolingServerStarted()) {
flashError(string.msg_tooling_server_unavailable)
return
}
val activity =
data.getActivity()
?: run {
log.debug("Cannot start build. Activity instance not provided in ActionData.")
return
}
actionScope.launch(Dispatchers.Default) {
activity.saveAllResult()
val result = withContext(Dispatchers.IO) {
buildService.executeTasks(taskName).get()
}
if (result?.isSuccessful != true) {
log.error("Tasks failed to execute: '$taskName'")
return@launch
}
handleResult(data, result, module, variant)
}
}
private fun cancelBuild(): Boolean {
log.info("Sending build cancellation request...")
val builder = Lookup.getDefault().lookup(BuildService.KEY_BUILD_SERVICE)
@@ -319,31 +319,33 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
override fun saveAllAsync(
notify: Boolean,
requestSync: Boolean,
processResources: Boolean,
progressConsumer: ((Int, Int) -> Unit)?,
runAfter: (() -> Unit)?
) {
activityBackroundScope.launch {
saveAll(notify, processResources, progressConsumer)
saveAll(notify, requestSync, processResources, progressConsumer)
runAfter?.invoke()
}
}
override suspend fun saveAll(
notify: Boolean,
requestSync: Boolean,
processResources: Boolean,
progressConsumer: ((Int, Int) -> Unit)?
): Boolean {
val result = saveAllResult(progressConsumer)
// don't bother to switch the context if we don't need to
if (notify || result.gradleSaved) {
if (notify || (result.gradleSaved && requestSync)) {
withContext(Dispatchers.Main) {
if (notify) {
flashSuccess(string.all_saved)
}
if (result.gradleSaved) {
if (result.gradleSaved && requestSync) {
editorViewModel.isSyncNeeded = true
}
}
@@ -50,6 +50,7 @@ interface IEditorHandler {
*/
suspend fun saveAll(
notify: Boolean = true,
requestSync: Boolean = true,
processResources: Boolean = false,
progressConsumer: ((progress: Int, total: Int) -> Unit)? = null
) : Boolean
@@ -62,6 +63,7 @@ interface IEditorHandler {
*/
fun saveAllAsync(
notify: Boolean = true,
requestSync: Boolean = true,
processResources: Boolean = false,
progressConsumer: ((progress: Int, total: Int) -> Unit)? = null,
runAfter: (() -> Unit)? = null