import SwiftUI struct StorageStatusView: View { @EnvironmentObject private var content: Content @Binding var isPresented: Bool var title: String { switch content.saveState { case .storageNotInitialized: "No Database Loaded" case .savingPausedDueToLoadErrors: "Database corrupted" case .isSaved: "Database is healthy" case .needsSave: "Database will be saved soon" case .failedToSave: "Database errors" case .isSaving: "Database is being saved" } } var subtitle: String { switch content.saveState { case .storageNotInitialized: "To start editing the content of a website, create a new database or load an existing one. Open a folder with an existing database, or choose an empty folder to create a new project." case .savingPausedDueToLoadErrors: "The errors loading the database are listed below. Saving has been disabled to prevent data corruption. Enable saving to save the partially loaded data." case .isSaved: "All data is saved to disk" case .needsSave: "Wait for a few seconds until the remaining changes are saved." case .failedToSave: "The errors while saving the database are listed below." case .isSaving: "Changes are being written to disk" } } var buttonText: String { switch content.saveState { case .storageNotInitialized: "Choose folder" case .savingPausedDueToLoadErrors: "Save partial data" case .isSaved, .isSaving, .needsSave: "Save database" case .failedToSave: "Attempt save again" } } var body: some View { VStack { Text(title) .font(.title) .padding() Text(subtitle) .multilineTextAlignment(.center) List(content.storageErrors) { error in VStack { Text(error.message) Text(error.date.formatted()) .font(.footnote) } } .frame(minHeight: 300) Button(buttonText, action: saveButtonPressed) .padding() .disabled(content.saveState == .isSaving) Button("Dismiss", action: { isPresented = false }) .padding() } .padding() } func saveButtonPressed() { switch content.saveState { case .storageNotInitialized: selectContentPath() case .savingPausedDueToLoadErrors: content.resumeSavingAfterLoadingErrors() case .isSaved, .needsSave, .failedToSave: content.saveUnconditionally() case .isSaving: break } } private func selectContentPath() { let panel = NSOpenPanel() // Sets up so user can only select a single directory panel.canChooseFiles = false panel.canChooseDirectories = true panel.allowsMultipleSelection = false panel.showsHiddenFiles = false panel.title = "Select the database folder" let response = panel.runModal() guard response == .OK else { content.storageErrors.append(.init(message: "Failed to select a folder: \(response)")) return } guard let url = panel.url else { content.storageErrors.append(.init(message: "No url found for selected content folder")) return } guard content.storage.save(contentPath: url) else { content.storageErrors.append(.init(message: "Failed to set content path")) return } content.loadFromDisk { } } }