MBL-2342: Add search filtering by project location#2482
Conversation
1573761 to
31939b9
Compare
| self.searchFilters = searchFilters | ||
|
|
||
| let selectedLocationName = searchFilters.location.selectedLocation?.displayableName | ||
| _locationSearchText = State(initialValue: selectedLocationName ?? "") |
There was a problem hiding this comment.
I've learned a lot of lessons about initializing state in SwiftUI. You can really only do this particular trick once, when the root view is instantiated.
There was a problem hiding this comment.
wow is _locationSearchText like a private accessor to locationSearchText?
There was a problem hiding this comment.
Correct, this is a feature of property wrappers (of which State is one). This is what the swift language documentation has to say:
The wrapper defines and manages any underlying storage needed by its wrapped value. The compiler synthesizes storage for the instance of the wrapper type by prefixing the name of the wrapped property with an underscore (_) — for example, the wrapper for someProperty is stored as _someProperty. The synthesized storage for the wrapper has an access control level of private.
So this is the officially supported way to set a State value on init. However, it's pretty tricky to use - if the SwiftUI view is used as a child view anywhere, it may be initialized many times, causing this state to break. This only works here because FilterRootView is initialized once and set as the root view of a UIHostingController.
| placement: .navigationBarDrawer(displayMode: .always), | ||
| prompt: "FPO: Search by city, state, country..." | ||
| ) | ||
| .searchSuggestions { |
There was a problem hiding this comment.
I spent a bunch of time writing my own autosuggestions code, until eventually I realized Apple had already done it for me 🤷♀️
| selectedLocation: self.$selectedLocation | ||
| ) | ||
| } | ||
| .searchable( |
There was a problem hiding this comment.
This isn't customizable, but I feel like using the system one is very ergonomic and nice.
31939b9 to
03653ab
Compare
| func selectedPercentRaisedBucket(_ bucket: DiscoveryParams.PercentRaisedBucket) | ||
|
|
||
| /// Cal this when the user selects a filter location. | ||
| func filteredLocation(_: Location?) |
There was a problem hiding this comment.
Had to name it this everywhere to prevent an overlap with the selectedLocation var.
jovaniks
left a comment
There was a problem hiding this comment.
Overall looks good! Just one suggestion: for any hardcoded strings that don't yet have a corresponding translation, could we wrap them with a TODOS comment or marker so it's easier to track and replace them later?
| @ViewBuilder | ||
| var locationSection: some View { | ||
| FilterSectionButton( | ||
| title: "FPO: Location", |
There was a problem hiding this comment.
Do we want to have this on translation strings?
| .modalHeader(withTitle: Strings.Percentage_raised(), onClose: self.onClose) | ||
| case .location: | ||
| self.locationModal | ||
| .modalHeader(withTitle: "FPO: Location", onClose: self.onClose) |
There was a problem hiding this comment.
Same here, looks like we want to have this in translated strings
| self.selectedLocation = nil | ||
| } label: { | ||
| self.buttonLabel( | ||
| title: "FPO: Anywhere", |
| .searchable( | ||
| text: self.$searchText, | ||
| placement: .navigationBarDrawer(displayMode: .always), | ||
| prompt: "FPO: Search by city, state, country..." |
There was a problem hiding this comment.
Would be great to have this included in the translated strings.
| var suggestedLocations: [Location] | ||
| @Binding var selectedLocation: Location? | ||
| var onSearchedForLocations: (String) -> Void | ||
| @Binding var searchText: String |
There was a problem hiding this comment.
Just wondering - since defaultLocations, suggestedLocations, and onSearchedForLocations don't seem to change after initialization, would it make sense to declare them as let instead of var?
There was a problem hiding this comment.
Whoops, yes, will fix!
| self.category.categories = categories | ||
| } | ||
|
|
||
| internal func update( |
There was a problem hiding this comment.
Since internal is the default access level in Swift, can we remove it here to avoid redundancy?
| self.location.defaultLocations = locations | ||
| } | ||
|
|
||
| internal func update( |
| ) | ||
|
|
||
| if featureSearchFilterByLocation() { | ||
| let locationTitle = self.location.selectedLocation?.displayableName ?? "FPO: Location" |
There was a problem hiding this comment.
Should we replace this with a translated string?
Thanks for the reminder, I'll add |
bcb1c3b to
e0a6fb0
Compare
03653ab to
33952f4
Compare
Generated by 🚫 Danger |
scottkicks
left a comment
There was a problem hiding this comment.
Sorry for the delay on this one! LGTM
📲 What
Implement search filtering by location.
location.search.working.mp4
🤔 Why
This is the belated phase 3 of our search filters! Plus filtering by location is very popular.