From 9748b427972d123689371518d90680cc26614ffc Mon Sep 17 00:00:00 2001 From: kean Date: Thu, 10 Oct 2024 21:32:34 -0400 Subject: [PATCH] Update deep search --- CHANGELOG.md | 1 + .../ConsoleSearchResultsSectionView.swift | 83 +++++++++++-------- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 220ca5013..1d683147e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix an issue with `isAutomaticConnectionEnabled` not starting the browser the first time it's enabled - Fix crash when exporting HAR file by @rounak in https://github.com/kean/Pulse/pull/299 - Fix concurrency issue in `StoreDetailsViewModel` by @ejensen in https://github.com/kean/Pulse/pull/302 +- Update the deep search. It will now show all search scopes found and only one match per scope. You can tap on a match to see the scope with a prepopulated search query to see the remaining items. ## Pulse 5.1.1 diff --git a/Sources/PulseUI/Features/Search/Views/ConsoleSearchResultsSectionView.swift b/Sources/PulseUI/Features/Search/Views/ConsoleSearchResultsSectionView.swift index 8769201c1..3579dbd2a 100644 --- a/Sources/PulseUI/Features/Search/Views/ConsoleSearchResultsSectionView.swift +++ b/Sources/PulseUI/Features/Search/Views/ConsoleSearchResultsSectionView.swift @@ -12,7 +12,6 @@ import Combine @available(iOS 16, visionOS 1, macOS 13, *) struct ConsoleSearchResultView: View { let viewModel: ConsoleSearchResultViewModel - var limit: Int = 4 var isSeparatorNeeded = false @ScaledMetric(relativeTo: .body) private var fontMultiplier = 1.0 @@ -21,42 +20,26 @@ struct ConsoleSearchResultView: View { var body: some View { ConsoleEntityCell(entity: viewModel.entity) - let occurrences = Array(viewModel.occurrences).filter { $0.scope.isDisplayedInResults } - ForEach(occurrences.prefix(limit)) { item in - NavigationLink(destination: ConsoleSearchResultView.makeDestination(for: item, entity: viewModel.entity).injecting(environment)) { + ForEach(makeMatches(from: viewModel.occurrences)) { item in + NavigationLink(destination: ConsoleSearchResultView.makeDestination(for: item.occurrence, entity: viewModel.entity).injecting(environment)) { makeCell(for: item) } } - if occurrences.count > limit { - let total = occurrences.count > ConsoleSearchMatch.limit ? "\(ConsoleSearchMatch.limit)+" : "\(occurrences.count)" - NavigationLink(destination: ConsoleSearchResultDetailsView(viewModel: viewModel).injecting(environment)) { - Text("Total Results: ") - .font(.callout) + - Text(total) - .font(.callout) - .foregroundColor(.secondary) - } - } if isSeparatorNeeded { PlainListGroupSeparator() } } @ViewBuilder - private func makeCell(for occurrence: ConsoleSearchOccurrence) -> some View { - let contents = VStack(alignment: .leading, spacing: 4) { - Text(occurrence.preview) - .font(contentFont) - .lineLimit(3) - Text(occurrence.scope.title + " (\(occurrence.line):\(occurrence.range.lowerBound + 1))") + private func makeCell(for item: ConsoleSearchResultsItem) -> some View { + VStack(alignment: .leading, spacing: 4) { + Text(item.title) .font(detailsFont) .foregroundColor(.secondary) - } - if #unavailable(iOS 16) { - contents.padding(.vertical, 4) - } else { - contents - } + Text(item.occurrence.preview) + .font(contentFont) + .lineLimit(3) + }.padding(.vertical, 4) } @ViewBuilder @@ -101,16 +84,48 @@ struct ConsoleSearchResultView: View { } @available(iOS 16, visionOS 1, *) -struct ConsoleSearchResultDetailsView: View { - let viewModel: ConsoleSearchResultViewModel +private func makeMatches(from occurrences: [ConsoleSearchOccurrence]) -> [ConsoleSearchResultsItem] { + var items: [ConsoleSearchResultsItem] = [] + var index = 0 + while index < occurrences.endIndex { + let occurrence = occurrences[index] + + if !occurrence.scope.isDisplayedInResults { + index += 1 + continue // Skip + } - var body: some View { - List { - ConsoleSearchResultView(viewModel: viewModel, limit: Int.max) + // Count all occurences in this scope and skip to the end + var counter = 1 // Already found one + while (index+1) < occurrences.endIndex && occurrences[index+1].scope == occurrence.scope { + counter += 1 + index += 1 // Consume next + } + + let item = ConsoleSearchResultsItem(totalCount: counter, occurrence: occurrence) + items.append(item) + index += 1 + } + return items +} + +@available(iOS 16, visionOS 1, *) +struct ConsoleSearchResultsItem: Identifiable { + var id: ConsoleSearchOccurrence { occurrence } + let totalCount: Int + let occurrence: ConsoleSearchOccurrence + + var title: String { + let suffix: String + if totalCount == 1 { + suffix = "" + } else if totalCount < ConsoleSearchMatch.limit { + suffix = " (\(totalCount) matches)" + } else { + // we know there is 6, showin + suffix = " (\(ConsoleSearchMatch.limit-1)+ matches)" } - .listStyle(.plain) - .environment(\.defaultMinListRowHeight, 0) - .inlineNavigationTitle("Search Results") + return "\(occurrence.scope.title)\(suffix)" } }