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 <alexander.korovin@vk.team>
This commit is contained in:
Violine 2025-03-24 04:10:07 +03:00 committed by GitHub
parent 2bec39576a
commit 577d8bc084
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 64 additions and 10 deletions

View file

@ -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 {

View file

@ -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())

View file

@ -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)
}
}

View file

@ -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)
}
}
}

View file

@ -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 <T> withEdt(
modalityState: ModalityState = ModalityState.defaultModalityState(),
block: suspend CoroutineScope.() -> T,
): T {
return withContext(EdtDispatchers.withModalityState(modalityState), block)
}
suspend fun <T> withCurrentEdt(block: suspend CoroutineScope.() -> T): T {
return withContext(EdtDispatchers.Current, block)
}
suspend fun <T> withNonModalEdt(block: suspend CoroutineScope.() -> T): T {
return withContext(EdtDispatchers.NonModal, block)
}