import SwiftUI struct ShareExtensionView: View { @ObservedObject var viewModel: ShareViewModel var onCancel: () -> Void var onComplete: () -> Void var onOpenURL: (URL) -> Void // MARK: - Body var body: some View { NavigationStack { Group { if !viewModel.isConfigured { notConfiguredView } else if viewModel.isSaved { successView } else { formView } } .navigationTitle("Save to BookStax") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel", action: onCancel) } } } .task { guard viewModel.isConfigured, !viewModel.isSaved else { return } await viewModel.loadShelves() } .alert( "Error", isPresented: Binding( get: { viewModel.errorMessage != nil }, set: { if !$0 { viewModel.errorMessage = nil } } ), actions: { Button("OK") { viewModel.errorMessage = nil } }, message: { Text(viewModel.errorMessage ?? "") } ) } // MARK: - Not configured private var notConfiguredView: some View { VStack(spacing: 20) { Image(systemName: "exclamationmark.triangle.fill") .font(.system(size: 48)) .foregroundStyle(.orange) Text("BookStax Not Configured") .font(.headline) Text("Please open BookStax and sign in to your BookStack server.") .multilineTextAlignment(.center) .foregroundStyle(.secondary) .padding(.horizontal) Button("Close", action: onCancel) .buttonStyle(.borderedProminent) } .padding() } // MARK: - Success private var successView: some View { VStack(spacing: 24) { Image(systemName: "checkmark.circle.fill") .font(.system(size: 64)) .foregroundStyle(.green) VStack(spacing: 8) { Text("Page saved!") .font(.headline) Text(viewModel.pageTitle) .font(.subheadline) .foregroundStyle(.secondary) .multilineTextAlignment(.center) } VStack(spacing: 12) { if let url = URL(string: viewModel.serverURL), !viewModel.serverURL.isEmpty { Button { onOpenURL(url) onComplete() } label: { Label("Open BookStax", systemImage: "safari") .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) } Button("Done", action: onComplete) .buttonStyle(.bordered) } .padding(.horizontal) } .padding() .task { try? await Task.sleep(for: .milliseconds(1500)) onComplete() } } // MARK: - Form private var formView: some View { Form { Section("Selected Text") { Text(viewModel.sharedText) .lineLimit(4) .font(.footnote) .foregroundStyle(.secondary) } Section("Page Title") { TextField("Page title", text: $viewModel.pageTitle) .autocorrectionDisabled() } Section("Location") { NavigationLink { ShelfPickerView(viewModel: viewModel) } label: { LabeledRow(label: "Shelf", value: viewModel.selectedShelf?.name) } NavigationLink { BookPickerView(viewModel: viewModel) } label: { LabeledRow(label: "Book", value: viewModel.selectedBook?.name) } .disabled(viewModel.selectedShelf == nil) NavigationLink { ChapterPickerView(viewModel: viewModel) } label: { LabeledRow(label: "Chapter", value: viewModel.selectedChapter?.name, placeholder: "Optional") } .disabled(viewModel.selectedBook == nil) } Section { Button { Task { await viewModel.savePage() } } label: { HStack { Spacer() if viewModel.isLoading { ProgressView() } else { Text("Save") .fontWeight(.semibold) } Spacer() } } .disabled(viewModel.isSaveDisabled) } } } } // MARK: - Helper private struct LabeledRow: View { let label: String let value: String? var placeholder: String = "Select" var body: some View { HStack { Text(LocalizedStringKey(label)) Spacer() Text(value.map { LocalizedStringKey($0) } ?? LocalizedStringKey(placeholder)) .foregroundStyle(value == nil ? .secondary : .primary) } } }