Skip to content

Commit

Permalink
Add OfflineIndexObserver for insight to Offline state (#206)
Browse files Browse the repository at this point in the history
### Description
- Update tests to expect offline index observer events
- Update changelog
- Add debug description strings for CoreOfflineIndexChangeEventType

### Checklist
- [x] Update `CHANGELOG`
  • Loading branch information
aokj4ck authored Apr 9, 2024
1 parent 5e56456 commit aa07728
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Guide: https://keepachangelog.com/en/1.0.0/

<!-- Add changes for active work here -->

- [Offline] Added OfflineIndexObserver which accepts two blocks for indexChanged or error events. This can be assigned to the offline search engine to receive state updates.

## 2.0.0-rc.3

- [Core] Add `SearchResultAccuracy.proximate` case which "is a known address point but does not intersect a known rooftop/parcel."
Expand Down
16 changes: 16 additions & 0 deletions MapboxSearch.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
0477904D2B890F4E00A99528 /* search-box-retrieve-minsk.json in Resources */ = {isa = PBXBuildFile; fileRef = 0477904C2B890F4E00A99528 /* search-box-retrieve-minsk.json */; };
0477904E2B890F4E00A99528 /* search-box-retrieve-minsk.json in Resources */ = {isa = PBXBuildFile; fileRef = 0477904C2B890F4E00A99528 /* search-box-retrieve-minsk.json */; };
0477904F2B890F4E00A99528 /* search-box-retrieve-minsk.json in Resources */ = {isa = PBXBuildFile; fileRef = 0477904C2B890F4E00A99528 /* search-box-retrieve-minsk.json */; };
0484BCDF2BC4865C003CF408 /* OfflineIndexObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0484BCDE2BC4865C003CF408 /* OfflineIndexObserver.swift */; };
0484BCE22BC49A23003CF408 /* CoreOfflineIndexChangeEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0484BCE12BC49A23003CF408 /* CoreOfflineIndexChangeEventType.swift */; };
048823482B6B0A9D00C770AA /* category-hotel-search-along-route-jp.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */; };
048823492B6B0A9D00C770AA /* category-hotel-search-along-route-jp.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */; };
0488234A2B6B0A9E00C770AA /* category-hotel-search-along-route-jp.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B7C2B6B043C00FDE7D5 /* category-hotel-search-along-route-jp.json */; };
Expand Down Expand Up @@ -540,6 +542,8 @@
046818E02B87FF5C0082B188 /* search-box-suggestions-minsk.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "search-box-suggestions-minsk.json"; sourceTree = "<group>"; };
047790482B890A8500A99528 /* search-box-recursion.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "search-box-recursion.json"; sourceTree = "<group>"; };
0477904C2B890F4E00A99528 /* search-box-retrieve-minsk.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "search-box-retrieve-minsk.json"; sourceTree = "<group>"; };
0484BCDE2BC4865C003CF408 /* OfflineIndexObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfflineIndexObserver.swift; sourceTree = "<group>"; };
0484BCE12BC49A23003CF408 /* CoreOfflineIndexChangeEventType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreOfflineIndexChangeEventType.swift; sourceTree = "<group>"; };
04970F8C2B7A97C900213763 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = mapbox.places.san.francisco.json; sourceTree = "<group>"; };
04AB0B792B6AF37800FDE7D5 /* DiscoverIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoverIntegrationTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1052,6 +1056,14 @@
path = sbs;
sourceTree = "<group>";
};
0484BCE02BC49A18003CF408 /* Offline */ = {
isa = PBXGroup;
children = (
0484BCE12BC49A23003CF408 /* CoreOfflineIndexChangeEventType.swift */,
);
path = Offline;
sourceTree = "<group>";
};
04970F8B2B7A97C900213763 /* Resources */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1554,6 +1566,7 @@
F9274FF127394AE600708F37 /* TileRegionError.swift */,
F9274FEA2732BF0E00708F37 /* SearchTileStore.swift */,
F9274FF6273AAE7200708F37 /* TileRegionLoadOptions+Search.swift */,
0484BCDE2BC4865C003CF408 /* OfflineIndexObserver.swift */,
);
path = Offline;
sourceTree = "<group>";
Expand Down Expand Up @@ -1731,6 +1744,7 @@
FEEDD2C12508DFE400DC0A98 /* InternalAPI */ = {
isa = PBXGroup;
children = (
0484BCE02BC49A18003CF408 /* Offline */,
04C127562B62FFD000884325 /* Engine */,
148DE66E285777050085684D /* Common */,
F98BECBB2577B9150081D3BC /* Telemetry */,
Expand Down Expand Up @@ -2664,13 +2678,15 @@
F9E8146225418E7D00F6378E /* EventsManager.swift in Sources */,
FEEDD3002508DFE400DC0A98 /* CLLocationCoordinate2DCodable.swift in Sources */,
FEEDD3042508DFE400DC0A98 /* SearchResultType.swift in Sources */,
0484BCE22BC49A23003CF408 /* CoreOfflineIndexChangeEventType.swift in Sources */,
F91FD66C258CCB41008CB8E1 /* CoreResultType+Extensions.swift in Sources */,
FEEDD3152508DFE400DC0A98 /* ServerSearchResult.swift in Sources */,
140E47A2298BC90E00677E30 /* Discover.swift in Sources */,
14FA65872953644400056E5B /* PlaceAutocomplete+Suggestion.swift in Sources */,
04C127552B62F6BC00884325 /* ApiType.swift in Sources */,
FE059C5A251A0AE6001F7701 /* SearchCategorySuggestionImpl.swift in Sources */,
FEEDD2F62508DFE400DC0A98 /* CoreSearchResultResponse.swift in Sources */,
0484BCDF2BC4865C003CF408 /* OfflineIndexObserver.swift in Sources */,
FE260A6725C063880037B725 /* ReverseGeocodingOptions.swift in Sources */,
FECA461026D3F81800BC7B18 /* MapboxSearchUserAgent.swift in Sources */,
FEEDD2F32508DFE400DC0A98 /* CoreBoundingBox.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
</EnvironmentVariable>
</EnvironmentVariables>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
identifier = "San Francisco, CA, USA"
referenceType = "1">
</LocationScenarioReference>
</LaunchAction>
Expand Down
6 changes: 6 additions & 0 deletions Sources/MapboxSearch/InternalAPI/CoreAliases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ typealias CoreUserActivityReporterOptions = MapboxCoreSearch.UserActivityReporte

typealias CoreReverseGeoOptions = MapboxCoreSearch.ReverseGeoOptions

// Offline
typealias CoreOfflineIndexObserver = MapboxCoreSearch.OfflineIndexObserver
typealias CoreOfflineIndexChangeEvent = MapboxCoreSearch.OfflineIndexChangeEvent
typealias CoreOfflineIndexError = MapboxCoreSearch.OfflineIndexError
typealias CoreOfflineIndexChangeEventType = MapboxCoreSearch.OfflineIndexChangeEventType

let mapboxCoreSearchErrorDomain = "MapboxCoreSearchErrorDomain"

extension CoreSearchEngine {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ protocol CoreSearchEngineProtocol {
func setTileStore(_ tileStore: MapboxCommon.TileStore, completion: (() -> Void)?)

func setTileStore(_ tileStore: MapboxCommon.TileStore)

func addOfflineIndexObserver(for observer: CoreOfflineIndexObserver)

func removeOfflineIndexObserver(for observer: CoreOfflineIndexObserver)
}

extension CoreSearchEngine: CoreSearchEngineProtocol {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright © 2024 Mapbox. All rights reserved.

import Foundation

extension CoreOfflineIndexChangeEventType: CustomDebugStringConvertible {
public var debugDescription: String {
switch self {
case .added:
return "Added"
case .removed:
return "Removed"
case .updated:
return "Updated"
@unknown default:
return "Unknown"
}
}
}
3 changes: 1 addition & 2 deletions Sources/MapboxSearch/PublicAPI/DefaultLocationProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import CoreLocation
/// Would not trigger Location Permission dialogs but will retrieve permission changes notification.
/// Suitable for `SearchEngine` for providing user location by default without additional efforts.
public class DefaultLocationProvider {
// not used anywhere as public
/* public */ let locationManager: CLLocationManager
let locationManager: CLLocationManager

#if FAST_LOCATION_CHANGES_TRACKING
let locationRequestFrequency: TimeInterval = 1
Expand Down
29 changes: 29 additions & 0 deletions Sources/MapboxSearch/PublicAPI/Offline/OfflineIndexObserver.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright © 2024 Mapbox. All rights reserved.

import Foundation

class OfflineIndexObserver: CoreOfflineIndexObserver {
enum Types {
typealias indexChangedBlock = (CoreOfflineIndexChangeEvent) -> Void
typealias errorBlock = (CoreOfflineIndexError) -> Void
}

private var onIndexChangedBlock: Types.indexChangedBlock
private var onErrorBlock: Types.errorBlock

init(
onIndexChangedBlock: @escaping Types.indexChangedBlock = { _ in },
onErrorBlock: @escaping Types.errorBlock = { _ in }
) {
self.onIndexChangedBlock = onIndexChangedBlock
self.onErrorBlock = onErrorBlock
}

func onIndexChanged(for event: CoreOfflineIndexChangeEvent) {
onIndexChangedBlock(event)
}

func onError(forError error: CoreOfflineIndexError) {
onErrorBlock(error)
}
}
13 changes: 13 additions & 0 deletions Tests/MapboxSearchIntegrationTests/OfflineIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ class OfflineIntegrationTests: MockServerIntegrationTestCase<GeocodingMockRespon
func testLoadData() throws {
clearData()

// Set up index observer before the fetch starts to validate changes after it completes
let indexChangedExpectation = expectation(description: "Received offline index changed event")
let offlineIndexObserver = OfflineIndexObserver(onIndexChangedBlock: { changeEvent in
_Logger.searchSDK.info("Index changed: \(changeEvent)")
indexChangedExpectation.fulfill()
}, onErrorBlock: { error in
_Logger.searchSDK.error("Encountered error in OfflineIndexObserver \(error)")
XCTFail(error.debugDescription)
})
searchEngine.offlineManager.engine.addOfflineIndexObserver(for: offlineIndexObserver)

// Perform the offline fetch
let loadDataExpectation = expectation(description: "Load Data")
_ = loadData { result in
switch result {
Expand All @@ -70,6 +82,7 @@ class OfflineIntegrationTests: MockServerIntegrationTestCase<GeocodingMockRespon
loadDataExpectation.fulfill()
}
wait(for: [loadDataExpectation], timeout: 200)
wait(for: [indexChangedExpectation], timeout: 200)

let updateExpectation = delegate.updateExpectation
searchEngine.search(query: "dc")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class CoreSearchEngineStub {
}

extension CoreSearchEngineStub: CoreSearchEngineProtocol {
func addOfflineIndexObserver(for observer: MapboxSearch.CoreOfflineIndexObserver) {}

func removeOfflineIndexObserver(for observer: CoreOfflineIndexObserver) {}

func makeFeedbackEvent(
request: CoreRequestOptions,
result: CoreSearchResultProtocol?,
Expand Down

0 comments on commit aa07728

Please sign in to comment.