Files
metacryst 637c9e4674 init
2026-01-09 11:14:27 -06:00

155 lines
4.6 KiB
Swift

import Capacitor
import IONGeolocationLib
private enum GeolocationCallbackType {
case requestPermissions
case location
case watch
var shouldKeepCallback: Bool {
self == .watch
}
var shouldClearAfterSending: Bool {
self == .location || self == .requestPermissions
}
}
private struct GeolocationCallbackGroup {
let ids: [CAPPluginCall]
let type: GeolocationCallbackType
}
final class GeolocationCallbackManager {
private(set) var requestPermissionsCallbacks: [CAPPluginCall]
private(set) var locationCallbacks: [CAPPluginCall]
private(set) var watchCallbacks: [String: CAPPluginCall]
private let capacitorBridge: CAPBridgeProtocol?
private var allCallbackGroups: [GeolocationCallbackGroup] {
[
.init(ids: requestPermissionsCallbacks, type: .requestPermissions),
.init(ids: locationCallbacks, type: .location),
.init(ids: Array(watchCallbacks.values), type: .watch)
]
}
private var requestPermissionsCallbackGroup: GeolocationCallbackGroup? {
allCallbackGroups.first { $0.type == .requestPermissions }
}
init(capacitorBridge: CAPBridgeProtocol?) {
self.capacitorBridge = capacitorBridge
self.requestPermissionsCallbacks = []
self.locationCallbacks = []
self.watchCallbacks = [:]
}
func addRequestPermissionsCallback(capacitorCall call: CAPPluginCall) {
capacitorBridge?.saveCall(call)
requestPermissionsCallbacks.append(call)
}
func addLocationCallback(capacitorCall call: CAPPluginCall) {
capacitorBridge?.saveCall(call)
locationCallbacks.append(call)
}
func addWatchCallback(_ watchId: String, capacitorCall call: CAPPluginCall) {
capacitorBridge?.saveCall(call)
watchCallbacks[watchId] = call
}
func clearRequestPermissionsCallbacks() {
requestPermissionsCallbacks.forEach {
capacitorBridge?.releaseCall($0)
}
requestPermissionsCallbacks.removeAll()
}
func clearWatchCallbackIfExists(_ watchId: String) {
if let callbackToRemove = watchCallbacks[watchId] {
capacitorBridge?.releaseCall(callbackToRemove)
watchCallbacks.removeValue(forKey: watchId)
}
}
func clearLocationCallbacks() {
locationCallbacks.forEach {
capacitorBridge?.releaseCall($0)
}
locationCallbacks.removeAll()
}
func sendSuccess(_ call: CAPPluginCall) {
call.resolve()
}
func sendSuccess(_ call: CAPPluginCall, with data: PluginCallResultData) {
call.resolve(data)
}
func sendRequestPermissionsSuccess(_ permissionsResult: String) {
if let group = requestPermissionsCallbackGroup {
let data = [
Constants.AuthorisationStatus.ResultKey.location: permissionsResult,
Constants.AuthorisationStatus.ResultKey.coarseLocation: permissionsResult
]
send(.success(data), to: group)
}
}
func sendSuccess(with position: IONGLOCPositionModel) {
createPluginResult(status: .success(position.toJSObject()))
}
func sendError(_ call: CAPPluginCall, error: GeolocationError) {
let errorModel = error.toCodeMessagePair()
call.reject(errorModel.1, errorModel.0)
}
func sendError(_ error: GeolocationError) {
createPluginResult(status: .error(error.toCodeMessagePair()))
}
}
private enum CallResultStatus {
typealias SuccessModel = JSObject
typealias ErrorModel = (code: String, message: String)
case success(_ data: SuccessModel)
case error(_ codeAndMessage: ErrorModel)
}
private extension GeolocationCallbackManager {
func createPluginResult(status: CallResultStatus) {
allCallbackGroups.forEach {
send(status, to: $0)
}
}
func send(_ callResultStatus: CallResultStatus, to group: GeolocationCallbackGroup) {
group.ids.forEach { call in
call.keepAlive = group.type.shouldKeepCallback
switch callResultStatus {
case .success(let data):
call.resolve(data)
case .error(let error):
call.reject(error.message, error.code)
}
}
if group.type.shouldClearAfterSending {
clearCallbacks(for: group.type)
}
}
func clearCallbacks(for type: GeolocationCallbackType) {
if case .location = type {
clearLocationCallbacks()
} else if case .requestPermissions = type {
clearRequestPermissionsCallbacks()
}
}
}