krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Sources/OrgstarMobile/SearchScreen.swift

191ddb506f3a91b93c755ba6e8123a4e8ac4f90d
orgstar/Sources/OrgstarMobile/SearchScreen.swift history · blame · raw

51 lines · 2173 bytes

 1#if os(iOS)
 2import OrgApp
 3import OrgIndex
 4import SwiftUI
 5
 6/// Files by name and headings by their words, as ⌘P and ⇧⌘F find them on the Mac.
 7struct SearchScreen: View {
 8    let workspace: WorkspaceModel
 9    let session: DocumentSession
10    @State private var query = ""
11
12    var body: some View {
13        let trimmed = query.trimmingCharacters(in: .whitespaces)
14        List {
15            if !trimmed.isEmpty {
16                let files = FuzzyMatch.rank(trimmed, workspace.files.filter { $0.kind == .org }, limit: 8)
17                if !files.isEmpty {
18                    Section("Files") {
19                        ForEach(files) { file in
20                            NavigationLink(value: ReaderRoute.file(file.path)) {
21                                Label(file.relativePath, systemImage: "doc.text")
22                            }
23                        }
24                    }
25                }
26                let headings = workspace.search(trimmed, overlay: workspace.overlay(session.openDocuments))
27                Section("Headings") {
28                    if headings.isEmpty { Text("No headings match").foregroundStyle(.secondary) }
29                    ForEach(headings, id: \.self) { location in
30                        NavigationLink(value: ReaderRoute.heading(location)) {
31                            VStack(alignment: .leading, spacing: 2) {
32                                Text(location.title.isEmpty ? "(untitled)" : location.title).lineLimit(2)
33                                Text((location.path as NSString).lastPathComponent).font(.caption).foregroundStyle(.secondary)
34                            }
35                        }
36                    }
37                }
38            }
39        }
40        .overlay {
41            if trimmed.isEmpty {
42                ContentUnavailableView("Search notes", systemImage: "magnifyingglass", description: Text("File names and the words of headings and their text."))
43            }
44        }
45        .navigationTitle("Search")
46        .searchable(text: $query, placement: .navigationBarDrawer(displayMode: .always))
47        .autocorrectionDisabled()
48        .textInputAutocapitalization(.never)
49    }
50}
51#endif