mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-10 19:42:21 +00:00
67 lines
2.6 KiB
Swift
67 lines
2.6 KiB
Swift
import HapiClient
|
|
import HapiUI
|
|
import SwiftUI
|
|
|
|
/// A plan menu, not an approval footer. The proposal remains readable after
|
|
/// its live id is withdrawn; only the current root proposal can be executed.
|
|
struct CodexPlanActionsView: View {
|
|
let planId: String
|
|
let interactions: ChatInteractor
|
|
@Environment(\.hapiTheme) private var theme
|
|
@Environment(\.hapiTypography) private var typography
|
|
|
|
var body: some View {
|
|
let state = interactions.codexPlanActions(planId: planId)
|
|
if state.isVisible {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
if let error = state.error {
|
|
Text(verbatim: LocalizedNoticeMapper.map(error))
|
|
.font(typography.captionFont)
|
|
.foregroundStyle(theme.danger)
|
|
.accessibilityIdentifier("plan-error-\(planId)")
|
|
}
|
|
if state.available || state.pending {
|
|
// Prefer one compact row, but never squeeze or truncate
|
|
// the labels to fit a narrow column or larger text size.
|
|
ViewThatFits(in: .horizontal) {
|
|
HStack(spacing: 8) {
|
|
buttons(state: state, horizontal: true)
|
|
}
|
|
VStack(spacing: 8) {
|
|
buttons(state: state, horizontal: false)
|
|
}
|
|
}
|
|
.font(typography.toolTitleFont)
|
|
.disabled(!state.canAct)
|
|
}
|
|
}
|
|
.padding(12)
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private func buttons(state: CodexPlanActionState, horizontal: Bool) -> some View {
|
|
Button { interactions.implementCodexPlan(planId: planId) } label: {
|
|
HStack(spacing: 8) {
|
|
if state.pending {
|
|
ProgressView()
|
|
.controlSize(.small)
|
|
.tint(theme.background)
|
|
.accessibilityHidden(true)
|
|
}
|
|
Text("Implement plan")
|
|
}
|
|
.fixedSize(horizontal: horizontal, vertical: true)
|
|
}
|
|
.buttonStyle(ChatActionButtonStyle(emphasis: .primary))
|
|
.accessibilityIdentifier("plan-implement-\(planId)")
|
|
|
|
Button { interactions.continueCodexPlan(planId: planId) } label: {
|
|
Text("Continue planning")
|
|
.fixedSize(horizontal: horizontal, vertical: true)
|
|
}
|
|
.buttonStyle(ChatActionButtonStyle(emphasis: .secondary))
|
|
.accessibilityIdentifier("plan-continue-\(planId)")
|
|
}
|
|
}
|