Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Sources/CodeIsland/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}
}
// Shortcuts act on the card currently on screen, so they target that
// card's session rather than the head of the queue. (#308)
case .approve:
appState.approvePermission()
appState.approvePermission(expectedSessionId: appState.surface.approvalSessionId)
case .approveAlways:
appState.approvePermission(always: true)
appState.approvePermission(always: true, expectedSessionId: appState.surface.approvalSessionId)
case .deny:
appState.denyPermission()
appState.denyPermission(expectedSessionId: appState.surface.approvalSessionId)
case .skipQuestion:
appState.skipQuestion()
appState.skipQuestion(expectedSessionId: appState.surface.questionSessionId)
case .jumpToTerminal:
if let id = appState.activeSessionId, let session = appState.sessions[id] {
TerminalActivator.activate(session: session, sessionId: id)
Expand Down
227 changes: 193 additions & 34 deletions Sources/CodeIsland/AppState.swift

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions Sources/CodeIsland/IslandSurface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,17 @@ enum IslandSurface: Equatable {
case .approvalCard(let id), .questionCard(let id), .completionCard(let id): return id
}
}

/// Session of the surface only when it is the matching card kind. A
/// permission shortcut fired while a question card is up must not address
/// that session's (non-existent) approval and discard the live card. (#308)
var approvalSessionId: String? {
if case .approvalCard(let id) = self { return id }
return nil
}

var questionSessionId: String? {
if case .questionCard(let id) = self { return id }
return nil
}
}
30 changes: 16 additions & 14 deletions Sources/CodeIsland/NotchPanelView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,38 +204,40 @@ struct NotchPanelView: View {

switch appState.surface {
case .approvalCard(let sid):
if let pending = appState.pendingPermission {
// Card is addressed by session — render that session's
// request, not whatever is at the head of the queue. (#308)
if let pending = appState.pendingPermission(forSession: sid) {
let session = appState.sessions[sid]
ApprovalBar(
tool: pending.event.toolName ?? "Unknown",
toolInput: pending.event.toolInput,
queuePosition: 1,
queuePosition: appState.permissionQueuePosition(forSession: sid),
queueTotal: appState.permissionQueue.count,
session: session,
sessionId: sid,
appState: appState,
onAllow: { appState.approvePermission(always: false) },
onAlwaysAllow: { appState.approvePermission(always: true) },
onDeny: { appState.denyPermission() },
onDismiss: { appState.dismissPermissionPrompt() }
onAllow: { appState.approvePermission(always: false, expectedSessionId: sid) },
onAlwaysAllow: { appState.approvePermission(always: true, expectedSessionId: sid) },
onDeny: { appState.denyPermission(expectedSessionId: sid) },
onDismiss: { appState.dismissPermissionPrompt(expectedSessionId: sid) }
)
.transition(.blurFade.combined(with: .scale(scale: 0.96, anchor: .top)))
}
case .questionCard(let sid):
let session = appState.sessions[sid]
if let q = appState.pendingQuestion {
if let q = appState.pendingQuestion(forSession: sid) {
QuestionBar(
question: q.question.question,
options: q.question.options,
descriptions: q.question.descriptions,
allQuestions: q.askUserQuestionState?.items ?? [],
sessionSource: session?.source,
sessionContext: session?.cwd,
queuePosition: 1,
queuePosition: appState.questionQueuePosition(forSession: sid),
queueTotal: appState.questionQueue.count,
onAnswer: { appState.answerQuestion($0) },
onAnswerMulti: { appState.answerQuestionMulti($0) },
onSkip: { appState.skipQuestion() }
onAnswer: { appState.answerQuestion($0, expectedSessionId: sid) },
onAnswerMulti: { appState.answerQuestionMulti($0, expectedSessionId: sid) },
onSkip: { appState.skipQuestion(expectedSessionId: sid) }
)
.transition(.blurFade.combined(with: .scale(scale: 0.96, anchor: .top)))
} else if let preview = appState.previewQuestionPayload {
Expand Down Expand Up @@ -2279,21 +2281,21 @@ private struct SessionCard: View {
fg: .white,
bg: Color(red: 0.25, green: 0.65, blue: 0.35),
enabled: isActiveApproval,
action: { appState.approvePermission(always: false) }
action: { appState.approvePermission(always: false, expectedSessionId: sessionId) }
)
inlineActionButton(
L10n.shared["always"],
fg: .white,
bg: Color(red: 0.25, green: 0.55, blue: 0.85),
enabled: isActiveApproval,
action: { appState.approvePermission(always: true) }
action: { appState.approvePermission(always: true, expectedSessionId: sessionId) }
)
inlineActionButton(
L10n.shared["deny"],
fg: .white,
bg: Color(red: 0.85, green: 0.3, blue: 0.3),
enabled: isActiveApproval,
action: { appState.denyPermission() }
action: { appState.denyPermission(expectedSessionId: sessionId) }
)
}

Expand Down
Loading