# Examples

### Install the module

Run the following command to install the module (make sure to install the **core** and **crash-detection** modules beforehand):

```bash
npm i @sentiance-react-native/legacy
```

### Import the module

```javascript
import RNSentiance from "@sentiance-react-native/legacy";
```

You can find a reference to all the types mentioned on this page [here](https://github.com/sentiance/react-native-sentiance/blob/main/packages/legacy/lib/index.d.ts).

### Initialize the SDK and create a user

#### Without User Linking

```javascript
const shouldStart = true; // start the SDK too
// returns Promise<boolean | SdkStatus>
const result = await RNSentiance.init(appId, secret, baseUrl, shouldStart);
```

#### With User Linking

```javascript
const emitter = new NativeEventEmitter(RNSentiance);

emitter.addListener('SDKUserLink',
      async data => {
        const { installId } = data;
        const success = await linkUserToYourBackend(installId);
        RNSentiance.userLinkCallback(success);
      }
    );

const shouldStart = true; // start the SDK too
// returns Promise<boolean | SdkStatus>
const result = await RNSentiance.initWithUserLinkingEnabled(
    appId, secret, baseUrl, shouldStart);
```

### Starting the SDK

```javascript
// returns Promise<SdkStatus>
const result = await RNSentiance.start();
```

You can also enable detections while also setting a future expiry date for the SDK to stop automatically:

```javascript
const expiryDate = Date.now() + 60 * 60 * 1000; // 1 hour from now
// returns Promise<SdkStatus>
const result = await RNSentiance.startWithStopDate(expiryDate);
```

### Stopping the SDK

While it's possible to "pause" the detections of the Sentiance SDK's, it's not recommended, as it can lead to missed detections (e.g. trips).

```javascript
try {
  // returns Promise<boolean>
  const result = await RNSentiance.stop();
  // SDK stopped properly.
} catch (err) {
  // An error prevented the SDK from stopping correctly
}
```

### Init status

Checking if SDK is initialized:

```javascript
// returns Promise<SdkInitState>
const initState = await RNSentiance.getInitState();
const isInitialized = initState == "INITIALIZED";
```

### SDK status

Getting the status of the SDK:

```javascript
// returns Promise<SdkStatus>
const sdkStatus = await RNSentiance.getSdkStatus();
```

The SDK can signal SDK status updates to JavaScript without being invoked directly. You can subscribe to these status updates:

```javascript
import { NativeEventEmitter } from "react-native";

const sentianceEmitter = new NativeEventEmitter(RNSentiance);
const subscription = sentianceEmitter.addListener(
  "SENTIANCE_STATUS_UPDATE_EVENT", (res) => {
  // Returns SDK status
});

// Don't forget to unsubscribe, typically in componentWillUnmount
subscription.remove();
```

### Get the SDK version

```javascript
// returns Promise<string>
const version = await RNSentiance.getVersion();
```

### Get the user ID

If the SDK is initialized, you can get the user ID as follows. This user ID will allow you to interact with the APIs from Sentiance. You need a token and a user ID to authorize requests and query the right data.

```javascript
// returns Promise<string>
const userId = await RNSentiance.getUserId();
```

### Get the user access token

If the SDK is initialized, you can get a user access token as follows. This token will allow you to interact with the APIs from Sentiance. You need a token and a user ID to authorize requests and query the right data. If the token has expired, or will expire soon, the SDK will get a new bearer token before returning it. Generally, this operation will complete instantly by returning a cached bearer token, but if a new token has to be obtained from the Sentiance API, there is a possibility that it will fail

```javascript
// returns Promise<UserAccessToken>
const { tokenId } = await RNSentiance.getUserAccessToken();
```

### Adding custom metadata

Custom metadata allows you to store text-based key-value user properties on the Sentiance platform, such as application related properties, which you can then obtain when processing data offloads (generated by Sentiance).

```javascript
const label = "correlation_id";
const value = "3a5276ec-b2b2-4636-b893-eb9a9f014938";

// returns Promise<boolean>
await RNSentiance.addUserMetadataField(label, value);
```

### Remove custom metadata

You can remove previously added metadata fields by passing the metadata label to the removeUserMetadataField function.

```javascript
const label = "correlation_id";

// returns Promise<boolean>
await RNSentiance.removeUserMetadataField(label);
```

### Adding multiple custom metadata fields

You can add multiple custom metadata fields by passing an object to the addUserMetadataFields function.

```javascript
const metadata = { corrolation_id: "3a5276ec-b2b2-4636-b893-eb9a9f014938" };

// returns Promise<boolean>
await RNSentiance.addUserMetadataFields(metadata);
```

### Starting trip

When you call `startTrip` on the SDK, you override automatic SDK detections and force trip data collection, until you call `stopTrip`, or until the trip times out (only applicable to the triggered trip SDK flavor). `startTrip` accepts a metadata object and a transport mode hint (numeric) as parameters.

Transport mode hint:

```
export enum TransportMode {
    UNKNOWN = 1,
    CAR,
    BICYCLE,
    ON_FOOT,
    TRAIN,
    TRAM,
    BUS,
    PLANE,
    BOAT,
    METRO,
    RUNNING
}
```

Example:

```javascript
const metadata = { corrolation_id: "3a5276ec-b2b2-4636-b893-eb9a9f014938" };
const transportModeHint = 1;

try {
  // returns Promise<boolean>
  await RNSentiance.startTrip(metadata, transportModeHint);
  // Trip is started
} catch (err) {
  // Unable to start trip
}
```

### Stopping trip

```javascript
try {
  // returns Promise<boolean>
  const trip = await RNSentiance.stopTrip();
  // Stopped trip
} catch (err) {
  // Unable to stop trip
}
```

You can also receive trip timeout events:

```javascript
import { NativeEventEmitter } from "react-native";

const sentianceEmitter = new NativeEventEmitter(RNSentianceLibrary);
const subscription = sentianceEmitter.addListener("TripTimeout", () => {
  // Trip timeout received
});
```

### Trip status

Checking an ongoing trip status:

```javascript
// returns Promise<boolean>
const isTripOngoing = await RNSentiance.isTripOngoing();
```

### Control sending data

If you want to override the default SDK data submission behavior, you can initiate a forced submission of detections. Ideally, you use this method only after explaining to the user that your app will consume more bandwidth in case the device is not connected to Wi-Fi.

```javascript
try {
  // returns Promise<boolean>
  await RNSentiance.submitDetections();
} catch (err) {
  // Something went wrong with submitting data, for more information, see the error variable
}
```

### Disk, mobile network and Wi-Fi quotas

The usage and limits of network and disk capacity in bytes can be obtained using the getWiFiQuotaUsage, getWiFiQuotaLimit and similar methods on the Sentiance SDK interface.

```javascript
// returns Promise<string>
const limit = await RNSentiance.getWiFiQuotaLimit();
```

All quota functions:

* `getWiFiQuotaLimit`
* `getWiFiQuotaUsage`
* `getMobileQuotaLimit`
* `getMobileQuotaUsage`
* `getDiskQuotaLimit`
* `getDiskQuotaUsage`

### User Activity

To get the user's current activity:

```javascript
// returns Promise<UserActivity>
const userActivity = await RNSentiance.getUserActivity();
```

You can subscribe to receive user activity updates:

```javascript
import { NativeEventEmitter } from "react-native";

const sentianceEmitter = new NativeEventEmitter(RNSentiance);
const subscription = sentianceEmitter.addListener(
  "SDKUserActivityUpdate",
  (userActivity) => {
    // Handle user activity
  }
);

RNSentiance.listenUserActivityUpdates();

// Don't forget to unsubscribe, typically in componentWillUnmount
subscription.remove();
```

Handling user activity:

```javascript
const { type, tripInfo, stationaryInfo } = userActivity;

if (type === "USER_ACTIVITY_TYPE_STATIONARY") {
  const { location } = stationaryInfo;

  if (location) {
    const { latitude, longitude } = location;
  }
  //..
} else if (type === "USER_ACTIVITY_TYPE_TRIP") {
  //..
} else if (type === "USER_ACTIVITY_TYPE_UNKNOWN") {
  //..
}
```

### Update the SDK foreground notification (ANDROID ONLY)

Updates the title and text of SDK notification. After calling this method, any notification shown by the SDK will be updated.

Note that this change is valid only during the process's lifetime. After the app process restarts, the SDK will display the default notification.

```javascript
// returns Promise<boolean>
await RNSentiance.updateSdkNotification("RN SDK Sample", "SDK is running");
```

### Resetting the SDK

To delete the Sentiance user and its data from the device, you can reset the SDK by calling `RNSentiance.clear`. This allows you to create a new Sentiance user by reinitializing the SDK, and linking it to a new external ID.

```javascript
try {
  // returns Promise<boolean>
  await RNSentiance.clear();
  // The SDK was successfully cleared and reset
} catch (err) {
  // Resetting the SDK failed
  // err.name has three values: SDK_INIT_IN_PROGRESS, SDK_RESET_IN_PROGRESS, SDK_RESET_UNKNOWN_ERROR
}
```

**Determine if the app should initialize Sentiance SDK natively**

To make user linking possible, the first SDK initialization should be executed in JS. After it completes successfully, `await RNSentiance.enableNativeInitialization()` should be invoked.

In AppDelegate (iOS) and MainApplication (Android), `isNativeInitializationEnabled` can be used to determine if the SDK should be initialized natively.

To disable native initialization, invoke `await RNSentiance.disableNativeInitialization()`.

Please refer to our [example app](https://github.com/sentiance/react-native-sentiance-example) for a complete usage.

### Vehicle Crash Event Detection

Listen to vehicle crash events:

```javascript
import { NativeEventEmitter } from "react-native";

const sentianceEmitter = new NativeEventEmitter(RNSentiance);
const vehicleCrashEventSubscription = sentianceEmitter.addListener(
  "VehicleCrashEvent",
  (event: VehicleCrashEvent) => {}
);

RNSentiance.listenVehicleCrashEvents();

// To unsubscribe
vehicleCrashEventSubscription.remove();
```

#### Invoke a dummy vehicle crash event

```javascript
// returns Promise<boolean>
await RNSentiance.invokeDummyVehicleCrash();
```

#### Check if crash detection is supported

```javascript
// returns Promise<boolean>
const crashDetectionSupported =
  await RNSentiance.isVehicleCrashDetectionSupported("TRIP_TYPE_SDK");
if (crashDetectionSupported) {
  // setup vehicle crash event listener
}
```

### Disable battery optimization (Android)

```javascript
// returns Promise<boolean>
await SentianceCore.disableBatteryOptimization();
```
