merge modal location
This commit is contained in:
@@ -386,14 +386,6 @@ private struct MergeButton: View {
|
||||
.buttonStyle(WebButtonStyle())
|
||||
.disabled(busy || held || intoParent || !unmerged)
|
||||
.help(help)
|
||||
.onGeometryChange(for: CGRect.self) { g in
|
||||
g.frame(in: .named("window"))
|
||||
} action: { frame in
|
||||
overlays.mergeFrame = frame
|
||||
}
|
||||
.onDisappear {
|
||||
overlays.mergeFrame = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ struct OverlayModal {
|
||||
let content: AnyView
|
||||
let buttons: [ModalButton]
|
||||
let anchor: CGRect?
|
||||
let inPane: Bool
|
||||
let canSubmit: @MainActor () -> Bool
|
||||
let done: (String) -> Void
|
||||
}
|
||||
@@ -49,7 +50,7 @@ final class Overlays {
|
||||
var leftTab = LeftTab.lead
|
||||
var leadFocus = 0
|
||||
@ObservationIgnored var pickerFrame: CGRect = .zero
|
||||
@ObservationIgnored var mergeFrame: CGRect?
|
||||
var paneFrame: CGRect = .zero
|
||||
@ObservationIgnored private var monitor: Any?
|
||||
|
||||
var isOpen: Bool {
|
||||
@@ -64,10 +65,10 @@ final class Overlays {
|
||||
alerts.append(OverlayAlert(content: AnyView(content)))
|
||||
}
|
||||
|
||||
func showModal(_ content: some View, _ buttons: [ModalButton], anchor: CGRect? = nil, canSubmit: @escaping @MainActor () -> Bool = { true }) async -> String {
|
||||
func showModal(_ content: some View, _ buttons: [ModalButton], anchor: CGRect? = nil, inPane: Bool = false, canSubmit: @escaping @MainActor () -> Bool = { true }) async -> String {
|
||||
modal?.done("cancel")
|
||||
return await withCheckedContinuation { cont in
|
||||
modal = OverlayModal(content: AnyView(content), buttons: buttons, anchor: anchor, canSubmit: canSubmit) { value in
|
||||
modal = OverlayModal(content: AnyView(content), buttons: buttons, anchor: anchor, inPane: inPane, canSubmit: canSubmit) { value in
|
||||
cont.resume(returning: value)
|
||||
}
|
||||
}
|
||||
@@ -248,7 +249,7 @@ struct OverlayHost: View {
|
||||
.onTapGesture {
|
||||
overlays.answerModal("cancel")
|
||||
}
|
||||
ModalPlacement(modal: m) { value in
|
||||
ModalPlacement(modal: m, pane: overlays.paneFrame) { value in
|
||||
overlays.answerModal(value)
|
||||
}
|
||||
}
|
||||
@@ -316,8 +317,25 @@ private struct AnchoredBox: Layout {
|
||||
}
|
||||
}
|
||||
|
||||
private struct PaneCenteredBox: Layout {
|
||||
let pane: CGRect
|
||||
|
||||
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
||||
proposal.replacingUnspecifiedDimensions()
|
||||
}
|
||||
|
||||
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
|
||||
let width = min(520, pane.width - 48)
|
||||
let size = subviews[0].sizeThatFits(ProposedViewSize(width: width, height: nil))
|
||||
let x = pane.midX - size.width / 2
|
||||
let y = min(max(overlayMargin, pane.midY - size.height / 2), bounds.height - overlayMargin - size.height)
|
||||
subviews[0].place(at: CGPoint(x: bounds.minX + x, y: bounds.minY + y), proposal: ProposedViewSize(width: width, height: size.height))
|
||||
}
|
||||
}
|
||||
|
||||
private struct ModalPlacement: View {
|
||||
let modal: OverlayModal
|
||||
let pane: CGRect
|
||||
let answer: (String) -> Void
|
||||
|
||||
var body: some View {
|
||||
@@ -327,6 +345,10 @@ private struct ModalPlacement: View {
|
||||
AnchoredBox(anchor: anchor) {
|
||||
box
|
||||
}
|
||||
} else if modal.inPane {
|
||||
PaneCenteredBox(pane: pane) {
|
||||
box
|
||||
}
|
||||
} else {
|
||||
box
|
||||
.padding(24)
|
||||
|
||||
@@ -137,9 +137,8 @@ func confirmMerge(_ taskId: String, _ store: Store, _ overlays: Overlays) async
|
||||
overlays.showAlert(errorText(error))
|
||||
}
|
||||
}
|
||||
let anchor = overlays.mergeFrame
|
||||
if !model.running {
|
||||
if await overlays.showModal(content, [ModalButton(label: "Cancel", value: "cancel"), ModalButton(label: "Merge", value: "ok", primary: true)], anchor: anchor, canSubmit: { model.valid }) == "ok" {
|
||||
if await overlays.showModal(content, [ModalButton(label: "Cancel", value: "cancel"), ModalButton(label: "Merge", value: "ok", primary: true)], inPane: true, canSubmit: { model.valid }) == "ok" {
|
||||
await merge(false)
|
||||
}
|
||||
return
|
||||
@@ -148,7 +147,7 @@ func confirmMerge(_ taskId: String, _ store: Store, _ overlays: Overlays) async
|
||||
ModalButton(label: "Cancel", value: "cancel"),
|
||||
ModalButton(label: "Merge now", value: "now"),
|
||||
ModalButton(label: "After review", value: "after", primary: true, help: "Merge once the running review finishes with no findings"),
|
||||
], anchor: anchor, canSubmit: { model.valid })
|
||||
], inPane: true, canSubmit: { model.valid })
|
||||
if choice == "now" || choice == "after" {
|
||||
await merge(choice == "after")
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ private struct LeftPane: View {
|
||||
|
||||
private struct TaskPane: View {
|
||||
@Environment(Store.self) private var store
|
||||
@Environment(Overlays.self) private var overlays
|
||||
@ViewState private var seen: Set<String> = []
|
||||
|
||||
var body: some View {
|
||||
@@ -198,6 +199,11 @@ private struct TaskPane: View {
|
||||
} action: { frame in
|
||||
store.paneFocus.setFrame(frame)
|
||||
}
|
||||
.onGeometryChange(for: CGRect.self) { g in
|
||||
g.frame(in: .named("window"))
|
||||
} action: { frame in
|
||||
overlays.paneFrame = frame
|
||||
}
|
||||
.onAppear {
|
||||
seen = Set(store.inbox.map(\.id))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user