59 lines
2.2 KiB
Swift
59 lines
2.2 KiB
Swift
import SwiftUI
|
|
|
|
struct RequestTabCloseAction {
|
|
let perform: (UUID) -> Void
|
|
func callAsFunction(_ id: UUID) { perform(id) }
|
|
}
|
|
private struct RequestTabCloseKey: EnvironmentKey {
|
|
static let defaultValue = RequestTabCloseAction { _ in }
|
|
}
|
|
extension EnvironmentValues {
|
|
var requestTabClose: RequestTabCloseAction {
|
|
get { self[RequestTabCloseKey.self] }
|
|
set { self[RequestTabCloseKey.self] = newValue }
|
|
}
|
|
}
|
|
|
|
struct UnsavedChangesAlert: ViewModifier {
|
|
@ObservedObject var editorState: EditorState
|
|
let buildService: BuildService
|
|
@State private var pendingTabId: UUID?
|
|
@State private var showAlert = false
|
|
|
|
func body(content: Content) -> some View {
|
|
content
|
|
.environment(\.requestTabClose, RequestTabCloseAction { tabId in
|
|
if let tab = editorState.tabs.first(where: { $0.id == tabId }), tab.isDirty {
|
|
pendingTabId = tabId; showAlert = true
|
|
} else {
|
|
editorState.closeTab(id: tabId)
|
|
}
|
|
})
|
|
.alert("Unsaved Changes", isPresented: $showAlert) {
|
|
Button("Save & Close") {
|
|
if let id = pendingTabId,
|
|
let tab = editorState.tabs.first(where: { $0.id == id }) {
|
|
Task {
|
|
await buildService.saveFile(path: tab.path, content: tab.content)
|
|
editorState.closeTab(id: id)
|
|
}
|
|
}
|
|
}
|
|
Button("Discard", role: .destructive) {
|
|
if let id = pendingTabId { editorState.closeTab(id: id) }
|
|
}
|
|
Button("Cancel", role: .cancel) { pendingTabId = nil }
|
|
} message: {
|
|
if let id = pendingTabId,
|
|
let name = editorState.tabs.first(where: { $0.id == id })?.fileName {
|
|
Text("\"\(name)\" has unsaved changes.")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension View {
|
|
func unsavedChangesGuard(editorState: EditorState, buildService: BuildService) -> some View {
|
|
modifier(UnsavedChangesAlert(editorState: editorState, buildService: buildService))
|
|
}
|
|
}
|