import SwiftUI struct PageListView: View { @Environment(\.language) private var language @EnvironmentObject private var content: Content @State private var selected: Page? @State private var showNewPageView = false @State private var newPageId = "" @State private var newPageIdIsValid = false private let allowedCharactersInPageId = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-")).inverted private var cleanPageId: String { newPageId.trimmingCharacters(in: .whitespacesAndNewlines) } var body: some View { NavigationSplitView { List(content.pages, selection: $selected) { page in Text(page.localized(in: language).title) .tag(page) } .toolbar { ToolbarItem(placement: .primaryAction) { Button(action: { showNewPageView = true }) { Label("New post", systemSymbol: .plus) } } } .navigationSplitViewColumnWidth(min: 300, ideal: 300, max: 300) } content: { if let selected { PageContentView(page: selected, language: language) .id(selected.id + language.rawValue) .layoutPriority(1) } else { // Fallback if no item is selected Text("Select a page from the list") .font(.largeTitle) .foregroundColor(.secondary) } } detail: { if let selected { PageDetailView(page: selected) .frame(maxWidth: 350) } else { EmptyView() .frame(maxWidth: 350) } } .onAppear { if selected == nil { selected = content.pages.first } } .sheet(isPresented: $showNewPageView, onDismiss: addNewPage) { TextEntrySheet( title: "Enter the id for the new page", text: $newPageId, isValid: $newPageIdIsValid) } } private func isValid(id: String) -> Bool { let id = cleanPageId guard id != "" else { return false } guard !content.pages.contains(where: { $0.id == id }) else { return false } // Only allow alphanumeric characters and hyphens return id.rangeOfCharacter(from: allowedCharactersInPageId) == nil } private func addNewPage() { let id = cleanPageId guard isValid(id: id) else { return } let page = Page( id: id, isDraft: true, createdDate: .now, startDate: .now, endDate: nil, german: .init(urlString: "seite", title: "Ein Titel"), english: .init(urlString: "page", title: "A Title"), tags: []) content.pages.insert(page, at: 0) selected = page } } #Preview { PageListView() .environmentObject(Content.mock) }