mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
feat(chat): numbered shortcuts on permission sheet (Phase 2.3)
Hermes v2026.4.23's TUI rewrite added 1-9 numbered shortcuts on approval prompts so power users approve/deny without reaching for the mouse. Mirror the pattern in Scarf: Mac PermissionApprovalView: - Each option button gets a "1. ", "2. ", … prefix on its label. - New private View extension `applyingNumberShortcut(index:)` binds the digit `idx + 1` (no modifiers) via .keyboardShortcut. Capped at 9; extra options stay tappable but unbound. iOS PermissionSheet: - Each row gets a monospaced "1." / "2." prefix as a hierarchy hint. - No keyboard binding (phones don't have hardware keyboards), but the numbering matches the Mac pattern so users transitioning between platforms see the same visual structure. Verified: Mac + iOS builds clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1270,7 +1270,12 @@ private struct PermissionSheet: View {
|
||||
}
|
||||
|
||||
Section("Your response") {
|
||||
ForEach(permission.options, id: \.optionId) { opt in
|
||||
// Visual numbering 1-9 matches the Mac sheet's
|
||||
// keyboard shortcuts; on iPhone the numbers serve
|
||||
// as a hierarchy hint rather than an accelerator
|
||||
// (no hardware keyboard binding). Mirrors the new
|
||||
// Hermes v2026.4.23 TUI pattern.
|
||||
ForEach(Array(permission.options.enumerated()), id: \.element.optionId) { idx, opt in
|
||||
Button {
|
||||
Task {
|
||||
await onRespond(opt.optionId)
|
||||
@@ -1278,6 +1283,11 @@ private struct PermissionSheet: View {
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
if idx < 9 {
|
||||
Text("\(idx + 1).")
|
||||
.font(.body.monospaced())
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Text(opt.name)
|
||||
Spacer()
|
||||
Image(systemName: "chevron.right")
|
||||
|
||||
@@ -444,21 +444,33 @@ struct PermissionApprovalView: View {
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal)
|
||||
|
||||
// Numbered keyboard shortcuts (1–9) on the option buttons.
|
||||
// Mirrors the new TUI pattern Hermes v2026.4.23 ships —
|
||||
// power users approve / deny without reaching for the
|
||||
// mouse. Visible "1." prefixes act as discoverability
|
||||
// hints; the actual key binding goes through
|
||||
// `.keyboardShortcut`. Capped at 9 — extra options stay
|
||||
// tappable but unbound (they'd need modifiers to
|
||||
// disambiguate beyond 9, which isn't worth it).
|
||||
HStack(spacing: 12) {
|
||||
ForEach(options, id: \.optionId) { option in
|
||||
if option.optionId == "deny" {
|
||||
Button(option.name) {
|
||||
onRespond(option.optionId)
|
||||
dismiss()
|
||||
ForEach(Array(options.enumerated()), id: \.element.optionId) { idx, option in
|
||||
let label = idx < 9 ? "\(idx + 1). \(option.name)" : option.name
|
||||
Group {
|
||||
if option.optionId == "deny" {
|
||||
Button(label) {
|
||||
onRespond(option.optionId)
|
||||
dismiss()
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
} else {
|
||||
Button(label) {
|
||||
onRespond(option.optionId)
|
||||
dismiss()
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
} else {
|
||||
Button(option.name) {
|
||||
onRespond(option.optionId)
|
||||
dismiss()
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.applyingNumberShortcut(index: idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,3 +496,17 @@ struct PermissionApprovalView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension View {
|
||||
/// Bind the digit `idx + 1` (1-9) to this view as a no-modifier
|
||||
/// keyboard shortcut. Indices ≥ 9 silently skip — there are only
|
||||
/// nine numeric shortcut keys without modifier conflicts.
|
||||
@ViewBuilder
|
||||
func applyingNumberShortcut(index idx: Int) -> some View {
|
||||
if idx < 9, let scalar = Unicode.Scalar(48 + idx + 1) {
|
||||
self.keyboardShortcut(KeyEquivalent(Character(scalar)), modifiers: [])
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user