Files
awesome-cordova-plugins/src/@awesome-cordova-plugins/plugins/hyper-track/index.ts
T
2022-05-21 20:29:08 +02:00

381 lines
11 KiB
TypeScript

import { Injectable } from '@angular/core';
import { AwesomeCordovaNativePlugin, Cordova, Plugin } from '@awesome-cordova-plugins/core';
const hypertrackIonicPluginVersion = "0.2.0"
// Minimal cordova-plugin-hypertrack-v3 version: 0.5.0
@Plugin({
pluginName: 'cordova-plugin-hypertrack-v3',
plugin: 'cordova-plugin-hypertrack-v3',
pluginRef: 'hypertrack',
repo: 'https://github.com/hypertrack/cordova-plugin-hypertrack.git',
platforms: ['Android, iOS'],
})
@Injectable()
export class HyperTrackPlugin extends AwesomeCordovaNativePlugin {
@Cordova()
initialize(publishableKey: string): Promise<HyperTrackCordova> {
return;
}
@Cordova()
getBlockers(): Promise<Set<Blocker>> {
return;
}
@Cordova()
enableDebugLogging(): Promise<any> {
return;
}
}
// Interfaces for Cordova Plugin callbacks
interface DeviceIdReceiver {
(deviceId: string): any;
}
interface TrackingStateReceiver {
(isRunning: boolean): any;
}
interface FailureHandler {
(error: Error): any;
}
interface SuccessHandler {
(): any;
}
interface LocationReceiver {
(location: CordovaLatestLocationResult): any;
}
// SDK instance that exposed from Cordova utilizes usage of callbacks, so we
// wrap it with adapter to avoid mix of callbacks and Promises
interface HyperTrackCordova {
getDeviceId(success: DeviceIdReceiver, error: FailureHandler): void;
isRunning(success: TrackingStateReceiver, error: FailureHandler): void;
setDeviceName(name: string, success: SuccessHandler, error: FailureHandler): void;
setDeviceMetadata(metadata: Object, success: SuccessHandler, error: FailureHandler): void;
setTrackingNotificationProperties(
title: string,
message: string,
success: SuccessHandler,
error: FailureHandler
): void;
addGeoTag(
geotagData: Object,
expectedLocation: Coordinates | undefined,
success: SuccessHandler,
error: FailureHandler
): void;
requestPermissionsIfNecessary(success: SuccessHandler, error: FailureHandler): void;
allowMockLocations(success: SuccessHandler, error: FailureHandler): void;
syncDeviceSettings(success: SuccessHandler, error: FailureHandler): void;
start(success: SuccessHandler, error: FailureHandler): void;
stop(success: SuccessHandler, error: FailureHandler): void;
getLatestLocation(success: LocationReceiver, error: FailureHandler): void;
getCurrentLocation(success: LocationReceiver, error: FailureHandler): void;
}
export class CoordinatesValidationError extends Error {}
/** Wrapper class for passing spatial geoposition as a geotag's expected location */
export class Coordinates {
constructor(public latitude: number, public longitude: number) {
if (latitude < -90.0 || latitude > 90.0 || longitude < -180.0 || longitude > 180.0) {
throw new CoordinatesValidationError('latitude and longitude should be of correct values');
}
}
public toString = (): string => {
return JSON.stringify(this);
}
}
/** A blocker is an obstacle that needs to be resolved to achieve reliable tracking. */
export interface Blocker {
/** Recommended name for a user action, that needs to be performed to resolve the blocker. */
userActionTitle: string;
/** Recommended name for a button, that will navigate user to the place where he can resolve the blocker */
userActionCTA: string;
/** User action explanation */
userActionExplanation: string;
/** An action that navigates user to the dedicated settings menu. */
resolve: () => void;
}
export type CordovaLatestLocationResult = {
type: "location",
location: Coordinates,
} | {
type: "outage",
outage: {
code: number,
name: keyof typeof Outage
}
}
export type LocationResult = {
type: LocationResultType.LOCATION,
value: Coordinates
} |
{
type: LocationResultType.OUTAGE,
value: Outage
}
export enum LocationResultType {
LOCATION, OUTAGE
}
export enum Outage {
MISSING_LOCATION_PERMISSION,
MISSING_ACTIVITY_PERMISSION,
LOCATION_SERVICE_DISABLED,
NOT_TRACKING,
START_HAS_NOT_FINISHED,
NO_GPS_SIGNAL,
RESTART_REQUIRED
}
/**
* @usage
* ```typescript
* import { HyperTrack } from '@awesome-cordova-plugins/hyper-track';
*
* initializeHypertrack() {
* HyperTrack.enableDebugLogging();
* HyperTrack.initialize('YOUR_PUBLISHING_KEY')
* .then( this.onSdkInstanceReceived )
* .catch( (err) => console.error("HyperTrack init failed with error " + err) );
* }
* onSdkInstanceReceived(sdkInstance: HyperTrack) {
* sdkInstance.getDeviceId()
* .then((id) => console.log("Got device id " + id))
* .then(() => sdkInstance.setDeviceName("Elvis Ionic"))
* .then(() => console.log("Device name was changed"))
* .then(() => sdkInstance.setDeviceMetadata({platform: "Ionic Android"}))
* .then(() => console.log("Device metadata was changed"))
* .then(() => sdkInstance.setTrackingNotificationProperties("Tracking On", "Ionic SDK is tracking"))
* .then(() => console.log("Notification properties were changed"))
* .catch((err) => console.error("Got error in HyperTrack " + err));
* }
*
* ```
*/
export class HyperTrack {
/** Enables debug log in native HyperTrack SDK. */
static enableDebugLogging(): void {
new HyperTrackPlugin().enableDebugLogging();
}
/**
* Entry point into SDK.
*
* Initializes SDK. Also resolves SDK instance that could be used to query deviceId or set
* various data.
*
* @param publishableKey account-specific secret from the HyperTrack dashborad.
* @see {@link https://dashboard.hypertrack.com/setup}.
*/
static initialize(publishableKey: string): Promise<HyperTrack> {
console.log(`Hypertrack Ionic plugin version ${hypertrackIonicPluginVersion}`)
return new Promise((resolve, reject) => {
new HyperTrackPlugin()
.initialize(publishableKey)
.then((cordovaInstance: HyperTrackCordova) => {
resolve(new HyperTrack(cordovaInstance));
})
.catch((err: Error) => reject(err));
});
}
/**
* Get the list of blockers that needs to be resolved for reliable tracking.
*
* @see {Blocker}
*/
static getBlockers(): Promise<Set<Blocker>> {
return new HyperTrackPlugin().getBlockers();
}
/** Resolves device ID that could be used to identify the device. */
getDeviceId(): Promise<string> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.getDeviceId(
(deviceId) => resolve(deviceId),
(err) => reject(err)
);
});
}
/** Resolves to true if tracking service is running and false otherwise */
isRunning(): Promise<boolean> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.isRunning(
(isRunning) => resolve(isRunning),
(err) => reject(err)
);
});
}
/**
* Sets device name that could be used to identify the device in HyperTrack dashboard
*
* @param name
*/
setDeviceName(name: string): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.setDeviceName(
name,
() => resolve(),
(err) => reject(err)
);
});
}
/**
* Use this to set additional properties, like segments, teams etc.
*
* @param metadata key-value pais of properties.
*/
setDeviceMetadata(metadata: Object): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.setDeviceMetadata(
metadata,
() => resolve(),
(err) => reject(err)
);
});
}
/**
* Updates title and text in persistent notification, that appears when tracking is active.
*
* @param title
* @param message
*/
setTrackingNotificationProperties(title: string, message: string): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.setTrackingNotificationProperties(
title,
message,
() => resolve(),
(err) => reject(err)
);
});
}
/**
* Adds special marker-like object to device timeline.
*
* @param geotagData
* @param expectedLocation
*/
addGeotag(geotagData: Object, expectedLocation?: Coordinates): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.addGeoTag(
geotagData,
expectedLocation,
() => resolve(),
(err) => reject(err)
);
});
}
/** Pops up permission request dialog, if permissions weren't granted before or does nothing otherwise. */
requestPermissionsIfNecessary(): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.requestPermissionsIfNecessary(
() => resolve(),
(err) => reject(err)
);
});
}
/** Allows injecting false locations into the SDK, which ignores them by default. */
allowMockLocations(): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.allowMockLocations(
() => resolve(),
(err) => reject(err)
);
});
}
/**
* Synchronizes tracking state with platform model. This method is used to
* harden platform2device communication channel.
*/
syncDeviceSettings(): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.syncDeviceSettings(
() => resolve(),
(err) => reject(err)
);
});
}
/** Start tracking. */
start(): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.start(
() => resolve(),
(err) => reject(err)
);
});
}
/** Stop tracking. */
stop(): Promise<void> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.stop(
() => resolve(),
(err) => reject(err)
);
});
}
/**
* Resolves latest device location that was sent by the SDK.
* Only available for Android platform.
* */
getLatestLocation(): Promise<LocationResult> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.getLatestLocation(
locationResult => resolve(this.handleLocationResult(locationResult)),
err => reject(err)
);
});
}
/**
* Resolves latest device location from system location provider.
* Only available for Android platform.
* */
getCurrentLocation(): Promise<LocationResult> {
return new Promise((resolve, reject) => {
this.cordovaInstanceHandle.getCurrentLocation(
locationResult => resolve(this.handleLocationResult(locationResult)),
err => reject(err)
);
});
}
private handleLocationResult(locationResult: CordovaLatestLocationResult): LocationResult {
switch (locationResult.type) {
case "location": {
return {
type: LocationResultType.LOCATION,
value: locationResult.location
}
}
case "outage": {
const outage = Outage[locationResult.outage.name]
return {
type: LocationResultType.OUTAGE,
value: outage
}
}
}
}
private constructor(private cordovaInstanceHandle: HyperTrackCordova) {}
}