From 577d8bc08441184bc8b422ea5fcacd547f14dc47 Mon Sep 17 00:00:00 2001 From: Violine <3253340@gmail.com> Date: Mon, 24 Mar 2025 04:10:07 +0300 Subject: [PATCH] fix: custom open ai settings UI (#938) * Added Coroutine dispatchers for EDT * Don't apply custom open ai settings immediately * Use Coroutine EDT dispatchers for update UI --------- Co-authored-by: alexander.korovin --- .../custom/CustomServiceConfigurable.kt | 3 ++- .../custom/form/CustomServiceListForm.kt | 9 +++----- .../util/coroutines/CoroutineDispatchers.kt | 20 ++++++++++++++--- .../util/coroutines/EdtCoroutineDispatcher.kt | 22 +++++++++++++++++++ .../EdtCoroutineDispatcherExtensions.kt | 20 +++++++++++++++++ 5 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcher.kt create mode 100644 src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcherExtensions.kt diff --git a/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/CustomServiceConfigurable.kt b/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/CustomServiceConfigurable.kt index 2b3085c1..af749cfe 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/CustomServiceConfigurable.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/CustomServiceConfigurable.kt @@ -3,6 +3,7 @@ package ee.carlrobert.codegpt.settings.service.custom import com.intellij.openapi.components.service import com.intellij.openapi.options.Configurable import ee.carlrobert.codegpt.settings.service.custom.form.CustomServiceListForm +import ee.carlrobert.codegpt.util.coroutines.EdtDispatchers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -11,7 +12,7 @@ import javax.swing.JComponent class CustomServiceConfigurable : Configurable { - private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) + private val coroutineScope = CoroutineScope(SupervisorJob() + EdtDispatchers.Default) private lateinit var component: CustomServiceListForm override fun getDisplayName(): String { diff --git a/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/form/CustomServiceListForm.kt b/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/form/CustomServiceListForm.kt index 0427a317..9f0b06aa 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/form/CustomServiceListForm.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/settings/service/custom/form/CustomServiceListForm.kt @@ -369,13 +369,10 @@ class CustomServiceListForm( val newActualService = settings.firstOrNull { it.name == formState.value.active.name } ?: settings.first() - service.state.run { - services = settings.mapTo(mutableListOf()) { it.mapToState() } - active = newActualService.mapToState() - } - formState.update { - service.state.mapToData() + formState.update { state -> + state.copy(services = settings, active = newActualService) } + updateFormData(0) } } .submit(AppExecutorUtil.getAppExecutorService()) diff --git a/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/CoroutineDispatchers.kt b/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/CoroutineDispatchers.kt index f9ef72ee..ce30fdb2 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/CoroutineDispatchers.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/CoroutineDispatchers.kt @@ -1,15 +1,29 @@ package ee.carlrobert.codegpt.util.coroutines +import com.intellij.openapi.application.ModalityState import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.MainCoroutineDispatcher class CoroutineDispatchers { fun default(): CoroutineDispatcher = Dispatchers.Default - fun main(): MainCoroutineDispatcher = Dispatchers.Main - fun unconfined(): CoroutineDispatcher = Dispatchers.Unconfined fun io(): CoroutineDispatcher = Dispatchers.IO + + fun edtNonModal(): CoroutineDispatcher = EdtDispatchers.NonModal + + fun edtCurrent(): CoroutineDispatcher = EdtDispatchers.Current + + fun edtDefault(): CoroutineDispatcher = EdtDispatchers.Default } + +object EdtDispatchers { + val NonModal = EdtCoroutineDispatcher(ModalityState.nonModal()) + val Default = EdtCoroutineDispatcher() + val Current = EdtCoroutineDispatcher(ModalityState.current()) + + fun withModalityState(modalityState: ModalityState): CoroutineDispatcher { + return EdtCoroutineDispatcher(modalityState) + } +} \ No newline at end of file diff --git a/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcher.kt b/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcher.kt new file mode 100644 index 00000000..415eed21 --- /dev/null +++ b/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcher.kt @@ -0,0 +1,22 @@ +package ee.carlrobert.codegpt.util.coroutines + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ModalityState +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Runnable +import kotlin.coroutines.CoroutineContext + +class EdtCoroutineDispatcher( + private val modalityState: ModalityState = ModalityState.defaultModalityState() +) : CoroutineDispatcher() { + + override fun dispatch(context: CoroutineContext, block: Runnable) { + val app = ApplicationManager.getApplication() + + if (app.isDispatchThread) { + block.run() + } else { + app.invokeLater({ block.run() }, modalityState) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcherExtensions.kt b/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcherExtensions.kt new file mode 100644 index 00000000..dd90f31f --- /dev/null +++ b/src/main/kotlin/ee/carlrobert/codegpt/util/coroutines/EdtCoroutineDispatcherExtensions.kt @@ -0,0 +1,20 @@ +package ee.carlrobert.codegpt.util.coroutines + +import com.intellij.openapi.application.ModalityState +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.withContext + +suspend fun withEdt( + modalityState: ModalityState = ModalityState.defaultModalityState(), + block: suspend CoroutineScope.() -> T, +): T { + return withContext(EdtDispatchers.withModalityState(modalityState), block) +} + +suspend fun withCurrentEdt(block: suspend CoroutineScope.() -> T): T { + return withContext(EdtDispatchers.Current, block) +} + +suspend fun withNonModalEdt(block: suspend CoroutineScope.() -> T): T { + return withContext(EdtDispatchers.NonModal, block) +} \ No newline at end of file