import SwiftUI struct FileListView: View { @EnvironmentObject private var content: Content @Binding var selectedFile: FileResource? @State private var selectedFileType: FileTypeCategory? = nil @State private var searchString = "" let allowedType: FileTypeCategory? init(selectedFile: Binding, allowedType: FileTypeCategory? = nil) { self._selectedFile = selectedFile self.allowedType = allowedType } var filesBySelectedType: [FileResource] { guard let selectedFileType else { return content.files } return content.files.filter { selectedFileType == $0.type.category } } var filteredFiles: [FileResource] { guard !searchString.isEmpty else { return filesBySelectedType } return filesBySelectedType.filter { $0.id.contains(searchString) } } var body: some View { VStack(alignment: .center) { if allowedType == nil { Picker("", selection: $selectedFileType) { let all: FileTypeCategory? = nil Text("All").tag(all) ForEach(FileTypeCategory.allCases) { type in Text(type.text).tag(type) } } .pickerStyle(.menu) .padding(.trailing, 7) } TextField("", text: $searchString, prompt: Text("Search")) .textFieldStyle(.roundedBorder) .padding(.horizontal, 8) List(filteredFiles, selection: $selectedFile) { file in Text(file.id).tag(file) } .onChange(of: selectedFileType) { oldValue, newValue in guard oldValue != newValue else { return } let newFile = filteredFiles.first guard let selectedFile else { if let newFile { DispatchQueue.main.async { selectedFile = newFile } } return } if newValue == selectedFile.type.category { return } DispatchQueue.main.async { self.selectedFile = newFile } } } .onAppear { if let allowedType { selectedFileType = allowedType } if selectedFile == nil { selectedFile = content.files.first } } } } #Preview { NavigationSplitView { FileListView(selectedFile: .constant(nil)) .environmentObject(Content.mock) .navigationSplitViewColumnWidth(250) } detail: { Text("") .frame(width: 50) } }