Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ protocol FingerprintClientFactory {

protocol DeviceIdentificationServiceProtocol: Sendable {
func fingerprintDevice() async throws -> FingerprintResponse
func startCollectingLocation() async throws
}

struct DeviceIdentificationService<ClientFactory: FingerprintClientFactory>: DeviceIdentificationServiceProtocol {
Expand All @@ -17,9 +18,19 @@ struct DeviceIdentificationService<ClientFactory: FingerprintClientFactory>: Dev
init(settingsContainer: any ReadOnlySettingsContainer) {
self.settingsContainer = settingsContainer
}

func startCollectingLocation() async throws {
let client = try makeFingerprintClient()
await MainActor.run {
client.allowUseOfLocationData = true
}
}

func fingerprintDevice() async throws -> FingerprintResponse {
let client = try makeFingerprintClient()
await MainActor.run {
client.allowUseOfLocationData = true
}
let response = try await client.getVisitorIdResponse()
return response
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
@MainActor
extension GeolocationService {

static let shared: GeolocationService = .init()
static let shared: GeolocationService = .init(identificationService: .default)
}

@MainActor
extension GeolocationServiceProtocol where Self == GeolocationService {

static var `default`: Self { .shared }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@preconcurrency import CoreLocation
import FingerprintPro
import os

protocol GeolocationServiceProtocol: Sendable {
Expand All @@ -21,23 +22,49 @@ final class GeolocationService: NSObject, GeolocationServiceProtocol {
initialState: .notDetermined
)

private let locationManager = CLLocationManager()
private let shouldRequestPermission: Bool
private let locationHelper: LocationPermissionHelperProviding
private let identificationService: any DeviceIdentificationServiceProtocol

init(shouldRequestPermission: Bool = true) {
self.shouldRequestPermission = shouldRequestPermission
@MainActor
init(identificationService: any DeviceIdentificationServiceProtocol) {
self.locationHelper = FingerprintProFactory.getLocationPermissionHelperInstance()
self.identificationService = identificationService
super.init()
locationManager.delegate = self
self.locationHelper.delegate = self
}
}

extension GeolocationService: CLLocationManagerDelegate {
extension GeolocationService: LocationPermissionDelegate {

func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
currentAuthorizationStatus.withLock { status in
status = manager.authorizationStatus
guard status == .notDetermined, shouldRequestPermission else { return }
manager.requestWhenInUseAuthorization()
func locationPermissionHelper(
_ helper: LocationPermissionHelperProviding,
shouldShowLocationRationale rationale: LocationPermissionRationale
) {
os_log("Location rationale: %{public}@", String(describing: rationale))

switch rationale {
case .needInitialPermission:
helper.requestPermission()
case .upgradeToPrecise:
helper.requestTemporaryPrecisePermission()
case .needSettingsChange:
helper.requestTemporaryPrecisePermission()
@unknown default:
os_log("⚠️ Received unknown rationale: %{public}@", String(describing: rationale))
}
}

func locationPermissionHelper(
_ helper: LocationPermissionHelperProviding,
didUpdateLocationPermission status: CLAuthorizationStatus
) {
currentAuthorizationStatus.withLock { $0 = status }
switch status {
case .authorizedWhenInUse, .authorizedAlways:
Task {
try? await identificationService.startCollectingLocation()
}
default: break
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ final class DeviceFingerprintViewModel: ObservableObject {
private nonisolated let geolocationService: any GeolocationServiceProtocol
private nonisolated let settingsContainer: SettingsContainer

@MainActor
init(
identificationService: any DeviceIdentificationServiceProtocol = .default,
smartSignalsService: (any SmartSignalsServiceProtocol)? = .default,
geolocationService: any GeolocationServiceProtocol = .default,
settingsContainer: SettingsContainer = .default
identificationService: any DeviceIdentificationServiceProtocol,
smartSignalsService: (any SmartSignalsServiceProtocol)?,
geolocationService: any GeolocationServiceProtocol,
settingsContainer: SettingsContainer
) {
self.identificationService = identificationService
self.smartSignalsService = smartSignalsService
Expand Down
11 changes: 9 additions & 2 deletions FingerprintProDemo/Features/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ extension RootView where Home == HomeView, Settings == SettingsView {
deviceFingerprintViewModel: {
guard ConfigVariable.SmartSignals.isEnabled else {
return .init(
identificationService: .default,
smartSignalsService: .none,
geolocationService: GeolocationService(shouldRequestPermission: false)
geolocationService: .default,
settingsContainer: .default
)
}
return .init()
return .init(
identificationService: .default,
smartSignalsService: .none,
geolocationService: .default,
settingsContainer: .default
)
}()
)
settings = .init(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import FingerprintPro

struct DeviceIdentificationServicePreviewFixture: DeviceIdentificationServiceProtocol {

func startCollectingLocation() async throws {}
func fingerprintDevice() async throws -> FingerprintResponse { .preview }
}

Expand Down
Loading