smart update: scheduling

GitOrigin-RevId: a0d813e6d5ecbd3c15fb2780f7468138cfe3052e
This commit is contained in:
Dmitry Avdeev
2023-06-19 17:34:05 +00:00
committed by intellij-monorepo-bot
parent f87f1c86e7
commit a759707a31
3 changed files with 52 additions and 4 deletions
@@ -4,4 +4,6 @@ checkbox.build.project=&Build project
checkbox.update.project=&Update project
checkbox.update.ide=Update &IDE
dialog.title.smart.update=Update and Build
no.updates.available=No updates available
no.updates.available=No updates available
checkbox.schedule.update=Schedule update
label.every.day.at=Every day at
@@ -5,9 +5,9 @@ import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.*
import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.ProjectActivity
@@ -16,14 +16,22 @@ import com.intellij.openapi.vcs.update.CommonUpdateProjectAction
import com.intellij.ui.dsl.builder.MutableProperty
import com.intellij.util.xmlb.XmlSerializerUtil
import com.intellij.util.xmlb.annotations.MapAnnotation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import org.jetbrains.ide.UpdateActionsListener
import java.time.Duration
import java.time.LocalTime
import java.util.*
@State(name = "SmartUpdateOptions", storages = [Storage(value = StoragePathMacros.WORKSPACE_FILE, roamingType = RoamingType.DISABLED)])
@Service(Service.Level.PROJECT)
class SmartUpdate(val project: Project) : PersistentStateComponent<SmartUpdate.Options>, Disposable {
class SmartUpdate(val project: Project, private val coroutineScope: CoroutineScope) : PersistentStateComponent<SmartUpdate.Options>, Disposable {
class Options: BaseState() {
var scheduled = false
var scheduledTime: LocalTime = LocalTime.of(6, 0)
@get:MapAnnotation(surroundWithTag = false)
var map: MutableMap<String, Boolean> by linkedMap()
fun value(id: String) = map[id] ?: true
@@ -54,12 +62,23 @@ class SmartUpdate(val project: Project) : PersistentStateComponent<SmartUpdate.O
fun execute(project: Project, e: AnActionEvent? = null) {
executeNext(LinkedList(availableSteps().filter { options.value(it.id) }), project, e)
scheduleUpdate()
}
private fun executeNext(steps: Queue<SmartUpdateStep>, project: Project, e: AnActionEvent?) {
steps.poll()?.performUpdateStep(project, e) { executeNext(steps, project, e) }
}
internal fun scheduleUpdate() {
if (!options.scheduled) return
coroutineScope.async {
var duration = Duration.between(LocalTime.now(), options.scheduledTime)
if (duration.isNegative) duration = duration.plusDays(1)
delay(duration.toMillis())
blockingContext { execute(project) }
}
}
override fun dispose() {
}
}
@@ -91,9 +110,11 @@ const val IDE_RESTARTED_KEY = "smart.update.ide.restarted"
class IdeRestartedActivity: ProjectActivity {
override suspend fun execute(project: Project) {
val service = project.service<SmartUpdate>()
if (PropertiesComponent.getInstance().isTrueValue(IDE_RESTARTED_KEY)) {
PropertiesComponent.getInstance().setValue(IDE_RESTARTED_KEY, false)
project.service<SmartUpdate>().execute(project)
service.execute(project)
}
else service.scheduleUpdate()
}
}
@@ -4,8 +4,18 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.dsl.builder.Cell
import com.intellij.ui.dsl.builder.bindSelected
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.dsl.builder.selected
import java.time.Instant
import java.time.LocalDate
import java.time.LocalTime
import java.time.ZoneId
import java.util.*
import javax.swing.JSpinner
import javax.swing.SpinnerDateModel
class SmartUpdateDialog(private val project: Project) : DialogWrapper(project) {
init {
@@ -26,6 +36,21 @@ class SmartUpdateDialog(private val project: Project) : DialogWrapper(project) {
indent { row { cell(it).enabled(enabled) } }
}
}
lateinit var scheduled: Cell<JBCheckBox>
row { scheduled = checkBox(SmartUpdateBundle.message("checkbox.schedule.update")).bindSelected({ options.scheduled }, { options.scheduled = it}) }
indent {
val spinner = JSpinner(SpinnerDateModel().apply { value = getScheduled(options.scheduledTime) })
spinner.editor = JSpinner.DateEditor(spinner, "hh:mm")
row {
label(SmartUpdateBundle.message("label.every.day.at"))
cell(spinner)
}.enabledIf(scheduled.selected)
}
}
}
private fun getScheduled(time: LocalTime): Date {
val instant: Instant = time.atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant()
return Date.from(instant)
}
}