mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-30 17:14:40 +08:00
fix(jetbrains): retain permission diff card across re-renders
syncActive re-invokes PermissionView.show on every StateChanged while a request is pending, including RESPONDING/ERROR ticks. syncDiffs disposed and rebuilt the PermissionDiffView each time, so a fresh (collapsed) instance replaced any expanded inline preview. Retain the card instance across re-renders and update it in place via setDiffs, matching ModifiedFilesView. The card is still disposed in hideView when the request resolves, so a new request starts fresh.
This commit is contained in:
+3
-1
@@ -42,7 +42,9 @@ internal class PermissionDiffView private constructor(
|
||||
|
||||
@RequiresEdt
|
||||
fun setDiffs(value: List<PermissionFileDiff>) {
|
||||
render(value.map(::dto))
|
||||
val dtos = value.map(::dto)
|
||||
if (items == dtos) return
|
||||
render(dtos)
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
|
||||
+21
-13
@@ -99,7 +99,7 @@ class PermissionView(
|
||||
}
|
||||
|
||||
private var md: MdView? = null
|
||||
private val diffViews = mutableListOf<PermissionDiffView>()
|
||||
private var diffView: PermissionDiffView? = null
|
||||
|
||||
private val ID_DENY = "deny"
|
||||
private val ID_RUN = "run"
|
||||
@@ -165,13 +165,13 @@ class PermissionView(
|
||||
fun setDiffOpener(openDiff: SessionDiffOpener, sessionId: String?) {
|
||||
this.openDiff = openDiff
|
||||
this.sessionId = sessionId
|
||||
for (view in diffViews) view.setDiffOpener(openDiff, sessionId, requestId)
|
||||
diffView?.setDiffOpener(openDiff, sessionId, requestId)
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
fun setHoverSink(sink: (PartView, Boolean) -> Unit) {
|
||||
hover = sink
|
||||
for (view in diffViews) view.hover = sink
|
||||
diffView?.hover = sink
|
||||
}
|
||||
|
||||
/** Hide this view and clear the active request id. */
|
||||
@@ -195,9 +195,7 @@ class PermissionView(
|
||||
desc.foreground = SessionUiStyle.Text.Secondary.foreground()
|
||||
rules.applyStyle(style)
|
||||
md?.let { applyCodeStyle(it) }
|
||||
for (dv in diffViews) {
|
||||
dv.applyStyle(style)
|
||||
}
|
||||
diffView?.applyStyle(style)
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
@@ -208,16 +206,26 @@ class PermissionView(
|
||||
|
||||
@RequiresEdt
|
||||
private fun syncDiffs(diffs: List<PermissionFileDiff>) {
|
||||
disposeDiffs()
|
||||
diffRow.isVisible = diffs.isNotEmpty()
|
||||
if (diffs.isNotEmpty()) {
|
||||
if (diffs.isEmpty()) {
|
||||
disposeDiffs()
|
||||
return
|
||||
}
|
||||
// Retain the card across the RESPONDING/ERROR re-renders of the same request so an
|
||||
// expanded inline preview is not torn down; setDiffs updates it in place. The card is
|
||||
// disposed in hideView when the request resolves, so a new request always starts fresh.
|
||||
val existing = diffView
|
||||
if (existing != null) {
|
||||
existing.setDiffOpener(openDiff, sessionId, requestId)
|
||||
existing.setDiffs(diffs)
|
||||
} else {
|
||||
val dv = PermissionDiffView(diffs, openFile, selection)
|
||||
dv.setDiffOpener(openDiff, sessionId, requestId)
|
||||
dv.hover = hover
|
||||
dv.applyStyle(style)
|
||||
diffViews.add(dv)
|
||||
diffView = dv
|
||||
diffRow.add(dv)
|
||||
}
|
||||
diffRow.isVisible = true
|
||||
diffRow.revalidate()
|
||||
diffRow.repaint()
|
||||
}
|
||||
@@ -418,8 +426,8 @@ class PermissionView(
|
||||
|
||||
@RequiresEdt
|
||||
private fun disposeDiffs() {
|
||||
for (view in diffViews) Disposer.dispose(view)
|
||||
diffViews.clear()
|
||||
diffView?.let(Disposer::dispose)
|
||||
diffView = null
|
||||
diffRow.removeAll()
|
||||
diffRow.isVisible = false
|
||||
}
|
||||
@@ -443,7 +451,7 @@ class PermissionView(
|
||||
internal fun runButtonForTest() = buttons(this).first { it.text == KiloBundle.message("session.permission.allow") || it.text == KiloBundle.message("session.permission.allow.once") }
|
||||
internal fun denyButtonForTest() = buttons(this).first { it.text == KiloBundle.message("session.permission.reject") }
|
||||
internal fun codeLabelsForTest() = codeEditors()
|
||||
internal fun diffViewsForTest() = diffViews.toList()
|
||||
internal fun diffViewsForTest() = listOfNotNull(diffView)
|
||||
internal fun headerFontForTest() = textAreas(this).first { it.font.isBold }.font
|
||||
internal fun rulesForTest() = rules
|
||||
|
||||
|
||||
+33
@@ -1147,6 +1147,39 @@ class PermissionViewTest : BasePlatformTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
fun `test diff view is retained and keeps expansion across same-request re-render`() {
|
||||
fun request(state: PermissionRequestState) = Permission(
|
||||
id = "perm_retain_diff",
|
||||
sessionId = "ses",
|
||||
name = "edit",
|
||||
patterns = listOf("src/A.kt"),
|
||||
always = emptyList(),
|
||||
meta = PermissionMeta(
|
||||
fileDiffs = listOf(
|
||||
PermissionFileDiff(
|
||||
file = "src/A.kt",
|
||||
patch = "@@ -1 +1 @@\n-old\n+new",
|
||||
additions = 1,
|
||||
deletions = 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
state = state,
|
||||
)
|
||||
|
||||
view.show(request(PermissionRequestState.PENDING))
|
||||
val diff = view.diffViewsForTest().single()
|
||||
diff.expand()
|
||||
assertTrue(diff.isExpanded())
|
||||
|
||||
// The RESPONDING tick re-renders the same request; the card must survive so the
|
||||
// expanded inline preview is not torn down.
|
||||
view.show(request(PermissionRequestState.RESPONDING))
|
||||
|
||||
assertSame(diff, view.diffViewsForTest().single())
|
||||
assertTrue("Expanded preview should persist across re-render", diff.isExpanded())
|
||||
}
|
||||
|
||||
fun `test stale rule command fields are released on rebuild`() {
|
||||
val base = EditorFactory.getInstance().allEditors.size
|
||||
view.show(permissionWithRules("perm_rules_rebuild", listOf("git status *")))
|
||||
|
||||
Reference in New Issue
Block a user