From ec12536ca7e76b6c6d13e947c17c971e3bc4f4be Mon Sep 17 00:00:00 2001 From: Michael Collins Date: Wed, 5 Jun 2024 22:59:43 -0700 Subject: [PATCH] Add tap gesture to provide additional feature info I enhanced RoadmapFeature by adding a URL property that can be used to display additional information about the feature request, such as a GitHub issue or a blog post. I enhanced RoadmapView by adding a bindable variable for the selected feature in the list. I added a tap gesture recognizer that will update the bindable value with the selected feature. This will allow a developer to navigate to another view to show more detailed information about the feature, or to use the new url field to open a web view to show the detailed information about the feature. --- .../RoadmapExample/ContentView.swift | 2 +- Sources/Roadmap/Models/RoadmapFeature.swift | 5 +++-- Sources/Roadmap/RoadmapView.swift | 20 +++++++++++-------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Example/RoadmapExample/RoadmapExample/ContentView.swift b/Example/RoadmapExample/RoadmapExample/ContentView.swift index b6eff96..f61ead4 100644 --- a/Example/RoadmapExample/RoadmapExample/ContentView.swift +++ b/Example/RoadmapExample/RoadmapExample/ContentView.swift @@ -16,7 +16,7 @@ struct ContentView: View { allowSearching: true, allowsFilterByStatus: true ) - + var body: some View { #if os(macOS) roadmapView diff --git a/Sources/Roadmap/Models/RoadmapFeature.swift b/Sources/Roadmap/Models/RoadmapFeature.swift index 7322056..b5e6597 100644 --- a/Sources/Roadmap/Models/RoadmapFeature.swift +++ b/Sources/Roadmap/Models/RoadmapFeature.swift @@ -7,10 +7,11 @@ import Foundation -public struct RoadmapFeature: Codable, Identifiable { +public struct RoadmapFeature: Codable, Identifiable, Equatable { public let id: String public let title: String? public var status: String? = nil + public var url: URL? = nil private var description : String? = nil private var localizedTitle: [LocalizedItem]? = nil private var localizedStatus: [LocalizedItem]? = nil @@ -52,7 +53,7 @@ public struct RoadmapFeature: Codable, Identifiable { } } -struct LocalizedItem: Codable { +struct LocalizedItem: Codable, Equatable { let language: String let value: String } diff --git a/Sources/Roadmap/RoadmapView.swift b/Sources/Roadmap/RoadmapView.swift index 950cf33..07f783b 100644 --- a/Sources/Roadmap/RoadmapView.swift +++ b/Sources/Roadmap/RoadmapView.swift @@ -12,6 +12,7 @@ public struct RoadmapView: View { let header: Header let footer: Footer @State private var selectedFilter: String + @Binding var selectedFeature: RoadmapFeature? private var filterHorizontalPadding: CGFloat { #if os(macOS) @@ -64,6 +65,9 @@ public struct RoadmapView: View { RoadmapFeatureView(viewModel: viewModel.featureViewModel(for: feature)) .macOSListRowSeparatorHidden() .listRowBackground(Color.clear) + .onTapGesture { + selectedFeature = feature + } } footer } @@ -72,26 +76,26 @@ public struct RoadmapView: View { } public extension RoadmapView where Header == EmptyView, Footer == EmptyView { - init(configuration: RoadmapConfiguration) { - self.init(viewModel: .init(configuration: configuration), header: EmptyView(), footer: EmptyView(), selectedFilter: "") + init(configuration: RoadmapConfiguration, selectedFeature: Binding = .constant(nil)) { + self.init(viewModel: .init(configuration: configuration), header: EmptyView(), footer: EmptyView(), selectedFilter: "", selectedFeature: selectedFeature) } } public extension RoadmapView where Header: View, Footer == EmptyView { - init(configuration: RoadmapConfiguration, @ViewBuilder header: () -> Header) { - self.init(viewModel: .init(configuration: configuration), header: header(), footer: EmptyView(), selectedFilter: "") + init(configuration: RoadmapConfiguration, @ViewBuilder header: () -> Header, selectedFeature: Binding = .constant(nil)) { + self.init(viewModel: .init(configuration: configuration), header: header(), footer: EmptyView(), selectedFilter: "", selectedFeature: selectedFeature) } } public extension RoadmapView where Header == EmptyView, Footer: View { - init(configuration: RoadmapConfiguration, @ViewBuilder footer: () -> Footer) { - self.init(viewModel: .init(configuration: configuration), header: EmptyView(), footer: footer(), selectedFilter: "") + init(configuration: RoadmapConfiguration, @ViewBuilder footer: () -> Footer, selectedFeature: Binding = .constant(nil)) { + self.init(viewModel: .init(configuration: configuration), header: EmptyView(), footer: footer(), selectedFilter: "", selectedFeature: selectedFeature) } } public extension RoadmapView where Header: View, Footer: View { - init(configuration: RoadmapConfiguration, @ViewBuilder header: () -> Header, @ViewBuilder footer: () -> Footer) { - self.init(viewModel: .init(configuration: configuration), header: header(), footer: footer(), selectedFilter: "") + init(configuration: RoadmapConfiguration, @ViewBuilder header: () -> Header, @ViewBuilder footer: () -> Footer, selectedFeature: Binding = .constant(nil)) { + self.init(viewModel: .init(configuration: configuration), header: header(), footer: footer(), selectedFilter: "", selectedFeature: selectedFeature) } }