Adding search by vin and notes (in addition to plate numbers)
This commit is contained in:
parent
48c700fc13
commit
c4e28a0656
@ -1661,7 +1661,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 166;
|
CURRENT_PROJECT_VERSION = 167;
|
||||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
|
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
|
||||||
@ -1690,7 +1690,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 166;
|
CURRENT_PROJECT_VERSION = 167;
|
||||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
|
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ struct MapScreen: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Map {
|
Map(position: $viewModel.currentPosition) {
|
||||||
ForEach(viewModel.markers) {
|
ForEach(viewModel.markers) {
|
||||||
Marker($0.title, coordinate: $0.coordinate)
|
Marker($0.title, coordinate: $0.coordinate)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ final class MapViewModel: ACHudContainer {
|
|||||||
let clusterManager = ClusterManager<MapMarkerModel>()
|
let clusterManager = ClusterManager<MapMarkerModel>()
|
||||||
var mapSize: CGSize = .zero
|
var mapSize: CGSize = .zero
|
||||||
var currentRegion: MKCoordinateRegion = .init()
|
var currentRegion: MKCoordinateRegion = .init()
|
||||||
|
var currentPosition: MapCameraPosition = .automatic
|
||||||
|
|
||||||
var isFilter: Bool {
|
var isFilter: Bool {
|
||||||
switch mapInput {
|
switch mapInput {
|
||||||
@ -75,7 +76,7 @@ final class MapViewModel: ACHudContainer {
|
|||||||
title = String.localizedStringWithFormat(NSLocalizedString("events found", comment: ""), events.count)
|
title = String.localizedStringWithFormat(NSLocalizedString("events found", comment: ""), events.count)
|
||||||
await clusterManager.add(markers)
|
await clusterManager.add(markers)
|
||||||
await reloadMarkers()
|
await reloadMarkers()
|
||||||
currentRegion = getRegion(for: markers)
|
currentPosition = getRegion(for: markers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,9 +115,9 @@ final class MapViewModel: ACHudContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRegion(for markers: [MapMarkerModel]) -> MKCoordinateRegion {
|
func getRegion(for markers: [MapMarkerModel]) -> MapCameraPosition {
|
||||||
guard !markers.isEmpty else {
|
guard !markers.isEmpty else {
|
||||||
return .init()
|
return .automatic
|
||||||
}
|
}
|
||||||
|
|
||||||
let latitudes = markers.map(\.coordinate.latitude)
|
let latitudes = markers.map(\.coordinate.latitude)
|
||||||
@ -127,15 +128,17 @@ final class MapViewModel: ACHudContainer {
|
|||||||
let minLong = longitudes.min() ?? 0
|
let minLong = longitudes.min() ?? 0
|
||||||
let maxLong = longitudes.max() ?? 0
|
let maxLong = longitudes.max() ?? 0
|
||||||
|
|
||||||
return .init(
|
let region = MKCoordinateRegion(
|
||||||
center: .init(
|
center: .init(
|
||||||
latitude: (maxLat - minLat)/2,
|
latitude: (maxLat + minLat)/2,
|
||||||
longitude: (maxLong - minLong)/2
|
longitude: (maxLong + minLong)/2
|
||||||
),
|
),
|
||||||
span: .init(
|
span: .init(
|
||||||
latitudeDelta: (maxLat - minLat)*1.2,
|
latitudeDelta: (maxLat - minLat)*1.3,
|
||||||
longitudeDelta: (maxLong - minLong)*1.2
|
longitudeDelta: (maxLong - minLong)*1.3
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return .region(region)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,14 @@ struct SearchScreen: View {
|
|||||||
}
|
}
|
||||||
.listStyle(.plain)
|
.listStyle(.plain)
|
||||||
.hud($viewModel.hud)
|
.hud($viewModel.hud)
|
||||||
.searchable(text: $viewModel.searchText, prompt: "Search plate numbers")
|
.searchable(
|
||||||
|
text: $viewModel.searchText,
|
||||||
|
tokens: $viewModel.currentScopes,
|
||||||
|
suggestedTokens: .constant(SearchScope.allCases),
|
||||||
|
prompt: "Search plate numbers"
|
||||||
|
) { scope in
|
||||||
|
Text(scope.title)
|
||||||
|
}
|
||||||
.searchPresentationToolbarBehavior(.avoidHidingContent)
|
.searchPresentationToolbarBehavior(.avoidHidingContent)
|
||||||
.makeTextFieldDumb()
|
.makeTextFieldDumb()
|
||||||
.titleModeInline()
|
.titleModeInline()
|
||||||
|
|||||||
@ -46,6 +46,7 @@ final class SearchViewModel: ACHudContainer {
|
|||||||
didSet {
|
didSet {
|
||||||
if searchText != oldValue {
|
if searchText != oldValue {
|
||||||
filter.searchString = searchText
|
filter.searchString = searchText
|
||||||
|
filter.scope = currentScopes.first ?? .plateNumber
|
||||||
searchTask = Task { [filter] in
|
searchTask = Task { [filter] in
|
||||||
do {
|
do {
|
||||||
try await Task.sleep(for: .milliseconds(500))
|
try await Task.sleep(for: .milliseconds(500))
|
||||||
@ -56,6 +57,8 @@ final class SearchViewModel: ACHudContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var currentScopes: [SearchScope] = []
|
||||||
|
|
||||||
@ObservationIgnored
|
@ObservationIgnored
|
||||||
@AutoCancellable
|
@AutoCancellable
|
||||||
var searchTask: Task<Void, Never>?
|
var searchTask: Task<Void, Never>?
|
||||||
|
|||||||
@ -38,11 +38,11 @@ public enum SortOrder: String, CustomStringConvertible, CaseIterable, Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SearchScope: Int, CaseIterable, Sendable, Hashable {
|
public enum SearchScope: String, CaseIterable, Sendable, Hashable, Identifiable {
|
||||||
|
|
||||||
case plateNumber = 0
|
case plateNumber
|
||||||
case vin = 1
|
case vin
|
||||||
case notes = 2
|
case notes
|
||||||
|
|
||||||
public var title: String {
|
public var title: String {
|
||||||
switch self {
|
switch self {
|
||||||
@ -52,12 +52,8 @@ public enum SearchScope: Int, CaseIterable, Sendable, Hashable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var stringValue: String {
|
public var id: String {
|
||||||
switch self {
|
rawValue
|
||||||
case .plateNumber: return "plateNumber"
|
|
||||||
case .vin: return "vin"
|
|
||||||
case .notes: return "notes"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +166,7 @@ public struct Filter: Sendable, Hashable {
|
|||||||
dict["toLocationDate"] = String(toLocationDate.timeIntervalSince1970)
|
dict["toLocationDate"] = String(toLocationDate.timeIntervalSince1970)
|
||||||
}
|
}
|
||||||
|
|
||||||
dict["scope"] = scope.stringValue
|
dict["scope"] = scope.rawValue
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user