fix(ui): allow out-of-order permission clicks
Show permission action buttons for queued tool calls while keeping keyboard shortcuts bound to the first active request. Prevent permission center list clicks from overriding keyboard-active ordering.
This commit is contained in:
@@ -7,8 +7,6 @@ import {
|
|||||||
getPermissionQueue,
|
getPermissionQueue,
|
||||||
getQuestionQueue,
|
getQuestionQueue,
|
||||||
getQuestionEnqueuedAtForInstance,
|
getQuestionEnqueuedAtForInstance,
|
||||||
setActivePermissionIdForInstance,
|
|
||||||
setActiveQuestionIdForInstance,
|
|
||||||
} from "../stores/instances"
|
} from "../stores/instances"
|
||||||
import { ensureSessionParentExpanded, loadMessages, sessions as sessionStateSessions, setActiveSessionFromList } from "../stores/sessions"
|
import { ensureSessionParentExpanded, loadMessages, sessions as sessionStateSessions, setActiveSessionFromList } from "../stores/sessions"
|
||||||
import { messageStoreBus } from "../stores/message-v2/bus"
|
import { messageStoreBus } from "../stores/message-v2/bus"
|
||||||
@@ -265,19 +263,10 @@ const PermissionApprovalModal: Component<PermissionApprovalModalProps> = (props)
|
|||||||
return count === 1 ? "1 question" : `${count} questions`
|
return count === 1 ? "1 question" : `${count} questions`
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleActivate = () => {
|
|
||||||
if (item.kind === "permission") {
|
|
||||||
setActivePermissionIdForInstance(props.instanceId, item.id)
|
|
||||||
} else {
|
|
||||||
setActiveQuestionIdForInstance(props.instanceId, item.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={`permission-center-item${isActive() ? " permission-center-item-active" : ""}`}
|
class={`permission-center-item${isActive() ? " permission-center-item-active" : ""}`}
|
||||||
role="listitem"
|
role="listitem"
|
||||||
onClick={handleActivate}
|
|
||||||
>
|
>
|
||||||
<div class="permission-center-item-header">
|
<div class="permission-center-item-header">
|
||||||
<div class="permission-center-item-heading">
|
<div class="permission-center-item-heading">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useGlobalCache } from "../lib/hooks/use-global-cache"
|
|||||||
import { useConfig } from "../stores/preferences"
|
import { useConfig } from "../stores/preferences"
|
||||||
import type { DiffViewMode } from "../stores/preferences"
|
import type { DiffViewMode } from "../stores/preferences"
|
||||||
import { activeInterruption, sendPermissionResponse, sendQuestionReject, sendQuestionReply } from "../stores/instances"
|
import { activeInterruption, sendPermissionResponse, sendQuestionReject, sendQuestionReply } from "../stores/instances"
|
||||||
|
import type { PermissionRequestLike } from "../types/permission"
|
||||||
import { getPermissionDisplayTitle, getPermissionKind, getPermissionSessionId } from "../types/permission"
|
import { getPermissionDisplayTitle, getPermissionKind, getPermissionSessionId } from "../types/permission"
|
||||||
import type { QuestionRequest } from "@opencode-ai/sdk/v2"
|
import type { QuestionRequest } from "@opencode-ai/sdk/v2"
|
||||||
import type { TextPart, RenderCache } from "../types/message"
|
import type { TextPart, RenderCache } from "../types/message"
|
||||||
@@ -859,15 +860,17 @@ export default function ToolCall(props: ToolCallProps) {
|
|||||||
const activeKey = activePermissionKey()
|
const activeKey = activePermissionKey()
|
||||||
if (!activeKey) return
|
if (!activeKey) return
|
||||||
const handler = (event: KeyboardEvent) => {
|
const handler = (event: KeyboardEvent) => {
|
||||||
|
const permission = permissionDetails()
|
||||||
|
if (!permission || !isPermissionActive()) return
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
handlePermissionResponse("once")
|
void handlePermissionResponse(permission, "once")
|
||||||
} else if (event.key === "a" || event.key === "A") {
|
} else if (event.key === "a" || event.key === "A") {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
handlePermissionResponse("always")
|
void handlePermissionResponse(permission, "always")
|
||||||
} else if (event.key === "d" || event.key === "D") {
|
} else if (event.key === "d" || event.key === "D") {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
handlePermissionResponse("reject")
|
void handlePermissionResponse(permission, "reject")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("keydown", handler)
|
document.addEventListener("keydown", handler)
|
||||||
@@ -1240,11 +1243,8 @@ export default function ToolCall(props: ToolCallProps) {
|
|||||||
return renderer().renderBody(rendererContext)
|
return renderer().renderBody(rendererContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handlePermissionResponse(response: "once" | "always" | "reject") {
|
async function handlePermissionResponse(permission: PermissionRequestLike, response: "once" | "always" | "reject") {
|
||||||
const permission = permissionDetails()
|
if (!permission) return
|
||||||
if (!permission || !isPermissionActive()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setPermissionSubmitting(true)
|
setPermissionSubmitting(true)
|
||||||
setPermissionError(null)
|
setPermissionError(null)
|
||||||
try {
|
try {
|
||||||
@@ -1310,37 +1310,37 @@ export default function ToolCall(props: ToolCallProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
<Show
|
<Show when={!active}>
|
||||||
when={active}
|
<p class="tool-call-permission-queued-text">Waiting for earlier permission responses.</p>
|
||||||
fallback={<p class="tool-call-permission-queued-text">Waiting for earlier permission responses.</p>}
|
</Show>
|
||||||
>
|
<div class="tool-call-permission-actions">
|
||||||
<div class="tool-call-permission-actions">
|
<div class="tool-call-permission-buttons">
|
||||||
<div class="tool-call-permission-buttons">
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
class="tool-call-permission-button"
|
||||||
class="tool-call-permission-button"
|
disabled={permissionSubmitting()}
|
||||||
disabled={permissionSubmitting()}
|
onClick={() => void handlePermissionResponse(permission, "once")}
|
||||||
onClick={() => handlePermissionResponse("once")}
|
>
|
||||||
>
|
Allow Once
|
||||||
Allow Once
|
</button>
|
||||||
</button>
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
class="tool-call-permission-button"
|
||||||
class="tool-call-permission-button"
|
disabled={permissionSubmitting()}
|
||||||
disabled={permissionSubmitting()}
|
onClick={() => void handlePermissionResponse(permission, "always")}
|
||||||
onClick={() => handlePermissionResponse("always")}
|
>
|
||||||
>
|
Always Allow
|
||||||
Always Allow
|
</button>
|
||||||
</button>
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
class="tool-call-permission-button"
|
||||||
class="tool-call-permission-button"
|
disabled={permissionSubmitting()}
|
||||||
disabled={permissionSubmitting()}
|
onClick={() => void handlePermissionResponse(permission, "reject")}
|
||||||
onClick={() => handlePermissionResponse("reject")}
|
>
|
||||||
>
|
Deny
|
||||||
Deny
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
<Show when={active}>
|
||||||
<div class="tool-call-permission-shortcuts">
|
<div class="tool-call-permission-shortcuts">
|
||||||
<kbd class="kbd">Enter</kbd>
|
<kbd class="kbd">Enter</kbd>
|
||||||
<span>Allow once</span>
|
<span>Allow once</span>
|
||||||
@@ -1349,10 +1349,10 @@ export default function ToolCall(props: ToolCallProps) {
|
|||||||
<kbd class="kbd">D</kbd>
|
<kbd class="kbd">D</kbd>
|
||||||
<span>Deny</span>
|
<span>Deny</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<Show when={permissionError()}>
|
|
||||||
<div class="tool-call-permission-error">{permissionError()}</div>
|
|
||||||
</Show>
|
</Show>
|
||||||
|
</div>
|
||||||
|
<Show when={permissionError()}>
|
||||||
|
<div class="tool-call-permission-error">{permissionError()}</div>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user