@sentiance-react-native/event-timeline 6.9.1-rc.1 → 6.10.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ package com.sentiance.react.bridge.eventtimeline;
2
+
3
+ public class ErrorCodes {
4
+ public static final String E_TRANSPORT_TAG_ERROR = "E_TRANSPORT_TAG_ERROR";
5
+ }
@@ -1,5 +1,6 @@
1
1
  package com.sentiance.react.bridge.eventtimeline;
2
2
 
3
+ import static com.sentiance.react.bridge.eventtimeline.ErrorCodes.E_TRANSPORT_TAG_ERROR;
3
4
  import static com.sentiance.react.bridge.eventtimeline.EventTimelineEmitter.TIMELINE_UPDATE_EVENT;
4
5
 
5
6
  import androidx.annotation.NonNull;
@@ -7,9 +8,11 @@ import androidx.annotation.NonNull;
7
8
  import com.facebook.react.bridge.Promise;
8
9
  import com.facebook.react.bridge.ReactApplicationContext;
9
10
  import com.facebook.react.bridge.ReactMethod;
11
+ import com.facebook.react.bridge.ReadableMap;
10
12
  import com.sentiance.react.bridge.core.common.SentianceSubscriptionsManager;
11
13
  import com.sentiance.react.bridge.core.common.base.AbstractSentianceModule;
12
14
  import com.sentiance.react.bridge.eventtimeline.converters.OnDeviceTypesConverter;
15
+ import com.sentiance.sdk.NoSentianceUserException;
13
16
  import com.sentiance.sdk.Sentiance;
14
17
  import com.sentiance.sdk.eventtimeline.api.EventTimelineApi;
15
18
  import com.sentiance.sdk.eventtimeline.api.EventTimelineUpdateListener;
@@ -19,108 +22,124 @@ import java.util.Date;
19
22
  import java.util.List;
20
23
 
21
24
  public class SentianceEventTimelineModule extends AbstractSentianceModule {
22
- public static final String NATIVE_MODULE_NAME = "SentianceEventTimeline";
23
-
24
- private final EventTimelineApi mEventTimelineApi;
25
- private final EventTimelineEmitter mEmitter;
26
- private final OnDeviceTypesConverter onDeviceTypesConverter;
27
-
28
- public SentianceEventTimelineModule(ReactApplicationContext reactApplicationContext,
29
- Sentiance sentiance,
30
- SentianceSubscriptionsManager subscriptionsManager,
31
- EventTimelineApi eventTimelineApi,
32
- EventTimelineEmitter emitter,
33
- OnDeviceTypesConverter converter) {
34
- super(reactApplicationContext, sentiance, subscriptionsManager);
35
- mEventTimelineApi = eventTimelineApi;
36
- mEmitter = emitter;
37
- onDeviceTypesConverter = converter;
38
- }
39
-
40
- @Override
41
- protected void addSupportedEventSubscriptions(SentianceSubscriptionsManager subscriptionsManager) {
42
- subscriptionsManager.addSupportedSubscription(
43
- TIMELINE_UPDATE_EVENT,
44
- mEventTimelineApi::setTimelineUpdateListener,
45
- listener -> mEventTimelineApi.setTimelineUpdateListener(null),
46
- SentianceSubscriptionsManager.SubscriptionType.SINGLE
47
- );
48
- }
49
-
50
- @Override
51
- @ReactMethod
52
- protected void removeNativeListener(String eventName, int subscriptionId, Promise promise) {
53
- if (rejectIfNotInitialized(promise)) {
54
- return;
25
+ public static final String NATIVE_MODULE_NAME = "SentianceEventTimeline";
26
+
27
+ private final EventTimelineApi mEventTimelineApi;
28
+ private final EventTimelineEmitter mEmitter;
29
+ private final OnDeviceTypesConverter onDeviceTypesConverter;
30
+
31
+ public SentianceEventTimelineModule(ReactApplicationContext reactApplicationContext,
32
+ Sentiance sentiance,
33
+ SentianceSubscriptionsManager subscriptionsManager,
34
+ EventTimelineApi eventTimelineApi,
35
+ EventTimelineEmitter emitter,
36
+ OnDeviceTypesConverter converter) {
37
+ super(reactApplicationContext, sentiance, subscriptionsManager);
38
+ mEventTimelineApi = eventTimelineApi;
39
+ mEmitter = emitter;
40
+ onDeviceTypesConverter = converter;
55
41
  }
56
42
 
57
- mSubscriptionsManager.removeSubscription(subscriptionId, eventName);
58
- promise.resolve(null);
59
- }
43
+ @Override
44
+ protected void addSupportedEventSubscriptions(SentianceSubscriptionsManager subscriptionsManager) {
45
+ subscriptionsManager.addSupportedSubscription(
46
+ TIMELINE_UPDATE_EVENT,
47
+ mEventTimelineApi::setTimelineUpdateListener,
48
+ listener -> mEventTimelineApi.setTimelineUpdateListener(null),
49
+ SentianceSubscriptionsManager.SubscriptionType.SINGLE
50
+ );
51
+ }
52
+
53
+ @Override
54
+ @ReactMethod
55
+ protected void removeNativeListener(String eventName, int subscriptionId, Promise promise) {
56
+ if (rejectIfNotInitialized(promise)) {
57
+ return;
58
+ }
60
59
 
61
- @Override
62
- @ReactMethod
63
- protected void addNativeListener(String eventName, int subscriptionId, Promise promise) {
64
- if (rejectIfNotInitialized(promise)) {
65
- return;
60
+ mSubscriptionsManager.removeSubscription(subscriptionId, eventName);
61
+ promise.resolve(null);
66
62
  }
67
63
 
68
- switch (eventName) {
69
- case TIMELINE_UPDATE_EVENT:
70
- mSubscriptionsManager.addSubscription(eventName, subscriptionId, (EventTimelineUpdateListener) mEmitter::sendTimelineUpdateEvent);
71
- break;
64
+ @Override
65
+ @ReactMethod
66
+ protected void addNativeListener(String eventName, int subscriptionId, Promise promise) {
67
+ if (rejectIfNotInitialized(promise)) {
68
+ return;
69
+ }
70
+
71
+ switch (eventName) {
72
+ case TIMELINE_UPDATE_EVENT:
73
+ mSubscriptionsManager.addSubscription(eventName, subscriptionId, (EventTimelineUpdateListener) mEmitter::sendTimelineUpdateEvent);
74
+ break;
75
+ }
76
+ promise.resolve(null);
72
77
  }
73
- promise.resolve(null);
74
- }
75
78
 
76
- @Override
77
- @ReactMethod
78
- protected void addListener(String eventName) {
79
+ @Override
80
+ @ReactMethod
81
+ protected void addListener(String eventName) {
79
82
 
80
- }
83
+ }
81
84
 
82
- @Override
83
- @ReactMethod
84
- protected void removeListeners(Integer count) {
85
+ @Override
86
+ @ReactMethod
87
+ protected void removeListeners(Integer count) {
85
88
 
86
- }
89
+ }
87
90
 
88
- @NonNull
89
- @Override
90
- public String getName() {
91
- return NATIVE_MODULE_NAME;
92
- }
91
+ @NonNull
92
+ @Override
93
+ public String getName() {
94
+ return NATIVE_MODULE_NAME;
95
+ }
96
+
97
+ @ReactMethod
98
+ public void getTimelineUpdates(final Double afterEpochTimeMs, final Promise promise) {
99
+ if (rejectIfNotInitialized(promise)) {
100
+ return;
101
+ }
93
102
 
94
- @ReactMethod
95
- public void getTimelineUpdates(final Double afterEpochTimeMs, final Promise promise) {
96
- if (rejectIfNotInitialized(promise)) {
97
- return;
103
+ Date afterDate = new Date(afterEpochTimeMs.longValue());
104
+ List<Event> events = mEventTimelineApi.getTimelineUpdates(afterDate);
105
+ promise.resolve(onDeviceTypesConverter.convertEvents(events));
98
106
  }
99
107
 
100
- Date afterDate = new Date(afterEpochTimeMs.longValue());
101
- List<Event> events = mEventTimelineApi.getTimelineUpdates(afterDate);
102
- promise.resolve(onDeviceTypesConverter.convertEvents(events));
103
- }
108
+ @ReactMethod
109
+ public void getTimelineEvents(final Double fromEpochTimeMs, final Double toEpochTimeMs, final Promise promise) {
110
+ if (rejectIfNotInitialized(promise)) {
111
+ return;
112
+ }
104
113
 
105
- @ReactMethod
106
- public void getTimelineEvents(final Double fromEpochTimeMs, final Double toEpochTimeMs, final Promise promise) {
107
- if (rejectIfNotInitialized(promise)) {
108
- return;
114
+ Date fromDate = new Date(fromEpochTimeMs.longValue());
115
+ Date toDate = new Date(toEpochTimeMs.longValue());
116
+ List<Event> events = mEventTimelineApi.getTimelineEvents(fromDate, toDate);
117
+ promise.resolve(onDeviceTypesConverter.convertEvents(events));
109
118
  }
110
119
 
111
- Date fromDate = new Date(fromEpochTimeMs.longValue());
112
- Date toDate = new Date(toEpochTimeMs.longValue());
113
- List<Event> events = mEventTimelineApi.getTimelineEvents(fromDate, toDate);
114
- promise.resolve(onDeviceTypesConverter.convertEvents(events));
115
- }
120
+ @ReactMethod
121
+ public void getTimelineEvent(final String eventId, final Promise promise) {
122
+ if (rejectIfNotInitialized(promise)) {
123
+ return;
124
+ }
116
125
 
117
- @ReactMethod
118
- public void getTimelineEvent(final String eventId, final Promise promise) {
119
- if (rejectIfNotInitialized(promise)) {
120
- return;
126
+ Event event = mEventTimelineApi.getTimelineEvent(eventId);
127
+ promise.resolve(event == null ? null : onDeviceTypesConverter.convertEvent(event));
121
128
  }
122
129
 
123
- Event event = mEventTimelineApi.getTimelineEvent(eventId);
124
- promise.resolve(event == null ? null : onDeviceTypesConverter.convertEvent(event));
125
- }
130
+ @ReactMethod
131
+ public void setTransportTags(ReadableMap tags, final Promise promise) {
132
+ if (rejectIfNotInitialized(promise)) {
133
+ return;
134
+ }
135
+
136
+ try {
137
+ mEventTimelineApi.setTransportTags(onDeviceTypesConverter.convertTransportTags(tags));
138
+ promise.resolve(null);
139
+ } catch (IllegalArgumentException | NoSentianceUserException e) {
140
+ promise.reject(E_TRANSPORT_TAG_ERROR, e.getMessage());
141
+ } catch (Exception e) {
142
+ promise.reject(e);
143
+ }
144
+ }
126
145
  }
@@ -6,6 +6,7 @@ import static com.sentiance.react.bridge.core.SentianceConverter.JS_KEY_LONGITUD
6
6
  import static com.sentiance.react.bridge.core.SentianceConverter.JS_KEY_TIMESTAMP;
7
7
 
8
8
  import com.facebook.react.bridge.Arguments;
9
+ import com.facebook.react.bridge.ReadableMap;
9
10
  import com.facebook.react.bridge.WritableArray;
10
11
  import com.facebook.react.bridge.WritableMap;
11
12
  import com.sentiance.sdk.ondevice.api.GeoLocation;
@@ -16,136 +17,151 @@ import com.sentiance.sdk.ondevice.api.event.TransportEvent;
16
17
  import com.sentiance.sdk.ondevice.api.venue.Venue;
17
18
 
18
19
  import java.util.List;
20
+ import java.util.Map;
19
21
 
20
22
  public class OnDeviceTypesConverter {
21
- public static final String JS_KEY_ID = "id";
22
- public static final String JS_KEY_START_TIME = "startTime";
23
- public static final String JS_KEY_START_TIME_EPOCH = "startTimeEpoch";
24
- public static final String JS_KEY_END_TIME = "endTime";
25
- public static final String JS_KEY_END_TIME_EPOCH = "endTimeEpoch";
26
- public static final String JS_KEY_LAST_UPDATE_TIME = "lastUpdateTime";
27
- public static final String JS_KEY_LAST_UPDATE_TIME_EPOCH = "lastUpdateTimeEpoch";
28
- public static final String JS_KEY_DURATION_SECONDS = "durationInSeconds";
29
- public static final String JS_KEY_TYPE = "type";
30
- public static final String JS_KEY_LOCATION = "location";
31
- public static final String JS_KEY_VENUE = "venue";
32
- public static final String JS_KEY_SIGNIFICANCE = "significance";
33
- public static final String JS_KEY_TRANSPORT_MODE = "transportMode";
34
- public static final String JS_KEY_WAYPOINTS = "waypoints";
35
- public static final String JS_KEY_DISTANCE = "distance";
36
- public static final String JS_KEY_SPEED_IN_MPS = "speedInMps";
37
- public static final String JS_KEY_SPEED_LIMIT_IN_MPS = "speedLimitInMps";
38
- public static final String JS_KEY_HAS_UNLIMITED_SPEED_LIMIT = "hasUnlimitedSpeedLimit";
39
- public static final String JS_KEY_IS_SPEED_LIMIT_INFO_SET = "isSpeedLimitInfoSet";
40
-
41
- public WritableMap convertGeoLocation(GeoLocation location) {
42
- WritableMap locationMap = Arguments.createMap();
43
-
44
- locationMap.putDouble(JS_KEY_LATITUDE, location.getLatitude());
45
- locationMap.putDouble(JS_KEY_LONGITUDE, location.getLongitude());
46
- locationMap.putInt(JS_KEY_ACCURACY, location.getAccuracyInMeters());
47
-
48
- return locationMap;
49
- }
50
-
51
- public WritableArray convertEvents(List<Event> events) {
52
- WritableArray array = Arguments.createArray();
53
- for (Event event : events) {
54
- array.pushMap(convertEvent(event));
55
- }
56
- return array;
57
- }
58
-
59
- public WritableMap convertEvent(Event event) {
60
- WritableMap map = Arguments.createMap();
61
-
62
- map.putString(JS_KEY_ID, event.getId());
63
- map.putString(JS_KEY_START_TIME, event.getStartTime().toString());
64
- map.putDouble(JS_KEY_START_TIME_EPOCH, event.getStartTime().getEpochTime());
65
- if (event.getEndTime() != null) {
66
- map.putString(JS_KEY_END_TIME, event.getEndTime().toString());
67
- map.putDouble(JS_KEY_END_TIME_EPOCH, event.getEndTime().getEpochTime());
68
-
69
- Long durationInSeconds = event.getDurationInSeconds();
70
- if (durationInSeconds != null) {
71
- map.putDouble(JS_KEY_DURATION_SECONDS, durationInSeconds);
72
- }
23
+ public static final String JS_KEY_ID = "id";
24
+ public static final String JS_KEY_START_TIME = "startTime";
25
+ public static final String JS_KEY_START_TIME_EPOCH = "startTimeEpoch";
26
+ public static final String JS_KEY_END_TIME = "endTime";
27
+ public static final String JS_KEY_END_TIME_EPOCH = "endTimeEpoch";
28
+ public static final String JS_KEY_LAST_UPDATE_TIME = "lastUpdateTime";
29
+ public static final String JS_KEY_LAST_UPDATE_TIME_EPOCH = "lastUpdateTimeEpoch";
30
+ public static final String JS_KEY_DURATION_SECONDS = "durationInSeconds";
31
+ public static final String JS_KEY_TYPE = "type";
32
+ public static final String JS_KEY_LOCATION = "location";
33
+ public static final String JS_KEY_VENUE = "venue";
34
+ public static final String JS_KEY_SIGNIFICANCE = "significance";
35
+ public static final String JS_KEY_TRANSPORT_MODE = "transportMode";
36
+ public static final String JS_KEY_WAYPOINTS = "waypoints";
37
+ public static final String JS_KEY_DISTANCE = "distance";
38
+ public static final String JS_KEY_SPEED_IN_MPS = "speedInMps";
39
+ public static final String JS_KEY_SPEED_LIMIT_IN_MPS = "speedLimitInMps";
40
+ public static final String JS_KEY_HAS_UNLIMITED_SPEED_LIMIT = "hasUnlimitedSpeedLimit";
41
+ public static final String JS_KEY_IS_SPEED_LIMIT_INFO_SET = "isSpeedLimitInfoSet";
42
+ public static final String JS_KEY_TRANSPORT_TAGS = "transportTags";
43
+
44
+ private final TransportTagsConverter transportTagsConverter;
45
+
46
+ public OnDeviceTypesConverter() {
47
+ transportTagsConverter = new TransportTagsConverter();
73
48
  }
74
49
 
75
- map.putString(JS_KEY_LAST_UPDATE_TIME, event.getLastUpdateTime().toString());
76
- map.putDouble(JS_KEY_LAST_UPDATE_TIME_EPOCH, event.getLastUpdateTime().getEpochTime());
50
+ public WritableMap convertGeoLocation(GeoLocation location) {
51
+ WritableMap locationMap = Arguments.createMap();
77
52
 
78
- map.putString(JS_KEY_TYPE, event.getEventType().toString());
53
+ locationMap.putDouble(JS_KEY_LATITUDE, location.getLatitude());
54
+ locationMap.putDouble(JS_KEY_LONGITUDE, location.getLongitude());
55
+ locationMap.putInt(JS_KEY_ACCURACY, location.getAccuracyInMeters());
79
56
 
80
- if (event instanceof StationaryEvent) {
81
- addStationaryEventInfo(map, (StationaryEvent) event);
82
- } else if (event instanceof TransportEvent) {
83
- addTransportEventInfo(map, (TransportEvent) event);
57
+ return locationMap;
84
58
  }
85
59
 
86
- return map;
87
- }
88
-
89
- private void addStationaryEventInfo(WritableMap map, StationaryEvent event) {
90
- if (event.getLocation() != null) {
91
- map.putMap(JS_KEY_LOCATION, convertGeoLocation(event.getLocation()));
60
+ public WritableArray convertEvents(List<Event> events) {
61
+ WritableArray array = Arguments.createArray();
62
+ for (Event event : events) {
63
+ array.pushMap(convertEvent(event));
64
+ }
65
+ return array;
92
66
  }
93
- map.putMap(JS_KEY_VENUE, convertVenue(event.getVenue()));
94
- }
95
67
 
96
- public WritableMap convertVenue(Venue venue) {
97
- WritableMap venueMap = Arguments.createMap();
68
+ public WritableMap convertEvent(Event event) {
69
+ WritableMap map = Arguments.createMap();
70
+
71
+ map.putString(JS_KEY_ID, event.getId());
72
+ map.putString(JS_KEY_START_TIME, event.getStartTime().toString());
73
+ map.putDouble(JS_KEY_START_TIME_EPOCH, event.getStartTime().getEpochTime());
74
+ if (event.getEndTime() != null) {
75
+ map.putString(JS_KEY_END_TIME, event.getEndTime().toString());
76
+ map.putDouble(JS_KEY_END_TIME_EPOCH, event.getEndTime().getEpochTime());
77
+
78
+ Long durationInSeconds = event.getDurationInSeconds();
79
+ if (durationInSeconds != null) {
80
+ map.putDouble(JS_KEY_DURATION_SECONDS, durationInSeconds);
81
+ }
82
+ }
83
+
84
+ map.putString(JS_KEY_LAST_UPDATE_TIME, event.getLastUpdateTime().toString());
85
+ map.putDouble(JS_KEY_LAST_UPDATE_TIME_EPOCH, event.getLastUpdateTime().getEpochTime());
86
+
87
+ map.putString(JS_KEY_TYPE, event.getEventType().toString());
88
+
89
+ if (event instanceof StationaryEvent) {
90
+ addStationaryEventInfo(map, (StationaryEvent) event);
91
+ } else if (event instanceof TransportEvent) {
92
+ addTransportEventInfo(map, (TransportEvent) event);
93
+ }
98
94
 
99
- if (venue.getLocation() != null) {
100
- venueMap.putMap(JS_KEY_LOCATION, convertGeoLocation(venue.getLocation()));
95
+ return map;
101
96
  }
102
- venueMap.putString(JS_KEY_SIGNIFICANCE, venue.getSignificance().name());
103
- venueMap.putString(JS_KEY_TYPE, venue.getType().name());
104
97
 
105
- return venueMap;
106
- }
98
+ private void addStationaryEventInfo(WritableMap map, StationaryEvent event) {
99
+ if (event.getLocation() != null) {
100
+ map.putMap(JS_KEY_LOCATION, convertGeoLocation(event.getLocation()));
101
+ }
102
+ map.putMap(JS_KEY_VENUE, convertVenue(event.getVenue()));
103
+ }
104
+
105
+ public WritableMap convertVenue(Venue venue) {
106
+ WritableMap venueMap = Arguments.createMap();
107
107
 
108
- private void addTransportEventInfo(WritableMap map, TransportEvent event) {
109
- map.putString(JS_KEY_TRANSPORT_MODE, event.getTransportMode().toString());
110
- map.putArray(JS_KEY_WAYPOINTS, convertWaypointList(event.getWaypoints()));
108
+ if (venue.getLocation() != null) {
109
+ venueMap.putMap(JS_KEY_LOCATION, convertGeoLocation(venue.getLocation()));
110
+ }
111
+ venueMap.putString(JS_KEY_SIGNIFICANCE, venue.getSignificance().name());
112
+ venueMap.putString(JS_KEY_TYPE, venue.getType().name());
111
113
 
112
- if (event.getDistanceInMeters() != null) {
113
- map.putInt(JS_KEY_DISTANCE, event.getDistanceInMeters());
114
+ return venueMap;
114
115
  }
115
- }
116
116
 
117
- public WritableArray convertWaypoints(List<Waypoint> waypointList) {
118
- WritableArray array = Arguments.createArray();
119
- for (Waypoint waypoint : waypointList) {
120
- array.pushMap(convertWaypoint(waypoint));
117
+ private void addTransportEventInfo(WritableMap map, TransportEvent event) {
118
+ map.putString(JS_KEY_TRANSPORT_MODE, event.getTransportMode().toString());
119
+ map.putArray(JS_KEY_WAYPOINTS, convertWaypointList(event.getWaypoints()));
120
+
121
+ if (event.getDistanceInMeters() != null) {
122
+ map.putInt(JS_KEY_DISTANCE, event.getDistanceInMeters());
123
+ }
124
+
125
+ Map<String, String> transportTags = event.getTags();
126
+ map.putMap(JS_KEY_TRANSPORT_TAGS, transportTagsConverter.convertFrom(transportTags));
121
127
  }
122
- return array;
123
- }
124
-
125
- public WritableMap convertWaypoint(Waypoint waypoint) {
126
- WritableMap waypointMap = Arguments.createMap();
127
-
128
- waypointMap.putDouble(JS_KEY_LATITUDE, waypoint.getLatitude());
129
- waypointMap.putDouble(JS_KEY_LONGITUDE, waypoint.getLongitude());
130
- waypointMap.putInt(JS_KEY_ACCURACY, waypoint.getAccuracyInMeters());
131
- waypointMap.putDouble(JS_KEY_TIMESTAMP, waypoint.getTimestamp());
132
- if (waypoint.hasSpeed()) {
133
- waypointMap.putDouble(JS_KEY_SPEED_IN_MPS, waypoint.getSpeedInMps());
128
+
129
+ public WritableArray convertWaypoints(List<Waypoint> waypointList) {
130
+ WritableArray array = Arguments.createArray();
131
+ for (Waypoint waypoint : waypointList) {
132
+ array.pushMap(convertWaypoint(waypoint));
133
+ }
134
+ return array;
134
135
  }
135
- if (waypoint.isSpeedLimitInfoSet() && !waypoint.hasUnlimitedSpeedLimit()) {
136
- waypointMap.putDouble(JS_KEY_SPEED_LIMIT_IN_MPS, waypoint.getSpeedLimitInMps());
136
+
137
+ public WritableMap convertWaypoint(Waypoint waypoint) {
138
+ WritableMap waypointMap = Arguments.createMap();
139
+
140
+ waypointMap.putDouble(JS_KEY_LATITUDE, waypoint.getLatitude());
141
+ waypointMap.putDouble(JS_KEY_LONGITUDE, waypoint.getLongitude());
142
+ waypointMap.putInt(JS_KEY_ACCURACY, waypoint.getAccuracyInMeters());
143
+ waypointMap.putDouble(JS_KEY_TIMESTAMP, waypoint.getTimestamp());
144
+ if (waypoint.hasSpeed()) {
145
+ waypointMap.putDouble(JS_KEY_SPEED_IN_MPS, waypoint.getSpeedInMps());
146
+ }
147
+ if (waypoint.isSpeedLimitInfoSet() && !waypoint.hasUnlimitedSpeedLimit()) {
148
+ waypointMap.putDouble(JS_KEY_SPEED_LIMIT_IN_MPS, waypoint.getSpeedLimitInMps());
149
+ }
150
+ waypointMap.putBoolean(JS_KEY_IS_SPEED_LIMIT_INFO_SET, waypoint.isSpeedLimitInfoSet());
151
+ waypointMap.putBoolean(JS_KEY_HAS_UNLIMITED_SPEED_LIMIT, waypoint.hasUnlimitedSpeedLimit());
152
+
153
+ return waypointMap;
137
154
  }
138
- waypointMap.putBoolean(JS_KEY_IS_SPEED_LIMIT_INFO_SET, waypoint.isSpeedLimitInfoSet());
139
- waypointMap.putBoolean(JS_KEY_HAS_UNLIMITED_SPEED_LIMIT, waypoint.hasUnlimitedSpeedLimit());
140
155
 
141
- return waypointMap;
142
- }
156
+ private WritableArray convertWaypointList(List<Waypoint> waypointList) {
157
+ WritableArray array = Arguments.createArray();
158
+ for (Waypoint waypoint : waypointList) {
159
+ array.pushMap(convertWaypoint(waypoint));
160
+ }
161
+ return array;
162
+ }
143
163
 
144
- private WritableArray convertWaypointList(List<Waypoint> waypointList) {
145
- WritableArray array = Arguments.createArray();
146
- for (Waypoint waypoint : waypointList) {
147
- array.pushMap(convertWaypoint(waypoint));
164
+ public Map<String, String> convertTransportTags(ReadableMap tags) {
165
+ return transportTagsConverter.convertFrom(tags);
148
166
  }
149
- return array;
150
- }
151
167
  }
@@ -0,0 +1,42 @@
1
+ package com.sentiance.react.bridge.eventtimeline.converters;
2
+
3
+ import com.facebook.react.bridge.Arguments;
4
+ import com.facebook.react.bridge.ReadableMap;
5
+ import com.facebook.react.bridge.ReadableMapKeySetIterator;
6
+ import com.facebook.react.bridge.WritableMap;
7
+
8
+ import java.util.HashMap;
9
+ import java.util.Map;
10
+ import java.util.Set;
11
+
12
+ /**
13
+ * Utility converter to handle conversions from/to React Native maps and standard Java hashmaps.
14
+ */
15
+ public class TransportTagsConverter {
16
+ public Map<String, String> convertFrom(ReadableMap tags) {
17
+ Map<String, String> map = new HashMap<>();
18
+ ReadableMapKeySetIterator iterator = tags.keySetIterator();
19
+ while (iterator.hasNextKey()) {
20
+ String key = iterator.nextKey();
21
+ String value = tags.getString(key);
22
+
23
+ if (value == null) {
24
+ throw new IllegalArgumentException("Cannot get string value for key: " + key);
25
+ }
26
+
27
+ map.put(key, value);
28
+ }
29
+ return map;
30
+ }
31
+
32
+ public WritableMap convertFrom(Map<String, String> tags) {
33
+ WritableMap writableMap = Arguments.createMap();
34
+ Set<String> keys = tags.keySet();
35
+
36
+ for (String key : keys) {
37
+ writableMap.putString(key, tags.get(key));
38
+ }
39
+
40
+ return writableMap;
41
+ }
42
+ }
@@ -0,0 +1,3 @@
1
+ export class TransportTaggingError extends Error {
2
+ constructor(message: string);
3
+ }
@@ -0,0 +1,13 @@
1
+ export const E_TRANSPORT_TAG_ERROR = "E_TRANSPORT_TAG_ERROR";
2
+
3
+ class TransportTaggingError extends Error {
4
+ constructor(message) {
5
+ super(message);
6
+ this.name = "TransportTaggingError";
7
+ }
8
+ }
9
+
10
+ module.exports = {
11
+ TransportTaggingError,
12
+ E_TRANSPORT_TAG_ERROR
13
+ }
package/lib/index.d.ts CHANGED
@@ -18,6 +18,7 @@ declare module "@sentiance-react-native/event-timeline" {
18
18
  transportMode: TransportMode | null;
19
19
  waypoints: Waypoint[];
20
20
  distance?: number; // in meters
21
+ transportTags: TransportTags;
21
22
  }
22
23
 
23
24
  export interface GeoLocation {
@@ -96,11 +97,48 @@ declare module "@sentiance-react-native/event-timeline" {
96
97
  isSpeedLimitInfoSet: boolean;
97
98
  }
98
99
 
100
+ export type TransportTags = { [key: string]: string };
101
+
99
102
  export interface SentianceEventTimeline {
100
103
  getTimelineUpdates(afterEpochTimeMs: number): Promise<Event[]>;
101
104
  getTimelineEvents(fromEpochTimeMs: number, toEpochTimeMs: number): Promise<Event[]>;
102
105
  getTimelineEvent(eventId: string): Promise<Event | null>;
103
106
  addTimelineUpdateListener(onTimelineUpdated: (event: Event) => void): Promise<EmitterSubscription>;
107
+
108
+ /**
109
+ * Sets the tags that will be assigned to a detected transport.
110
+ *
111
+ * @remarks
112
+ * The provided tags will be assigned to a transport at the moment the transport ends. When you
113
+ * receive an {@link Event} representing the ended transport, it will include these tags.
114
+ *
115
+ * The supplied tags are persisted and applied to future transports, even after the app is restarted.
116
+ * By calling this method again, you will replace the tags that will be assigned to future transports.
117
+ *
118
+ * You can include up to 6 tags (key-value pairs), and each tag component (key or value) must
119
+ * be at most 256 characters.
120
+ *
121
+ * @example Setting custom transport tags
122
+ * try {
123
+ * await SentianceEventTimeline.setTransportTags({
124
+ * key1: "value1",
125
+ * key2: "value2"
126
+ * });
127
+ * console.log('Transport tags have been set.');
128
+ * } catch (error) {
129
+ * if (error instanceof TransportTagsError) {
130
+ * console.error(`Failed to set transport tags: ${error.message}`);
131
+ * } else {
132
+ * console.error(`Error: ${error.message}`);
133
+ * }
134
+ * }
135
+ *
136
+ * @param tags The transport tags to set
137
+ *
138
+ * @throws TransportTaggingError if the supplied tags count is more than 6, or if one of the tag components exceeds
139
+ * the 256 characters limit.
140
+ */
141
+ setTransportTags(tags: TransportTags): Promise<void>;
104
142
  }
105
143
 
106
144
  /**
package/lib/index.js CHANGED
@@ -1,17 +1,18 @@
1
- const {NativeModules, Platform} = require("react-native");
2
- const {varToString} = require("@sentiance-react-native/core/lib/utils");
1
+ const { NativeModules, Platform } = require("react-native");
2
+ const { varToString } = require("@sentiance-react-native/core/lib/utils");
3
3
  const SentianceEventEmitter = require("@sentiance-react-native/core/lib/SentianceEventEmitter");
4
- const {createEventListener} = require("@sentiance-react-native/core/lib/SentianceEventListenerUtils");
5
- const {SentianceEventTimeline, SentianceCore} = NativeModules;
4
+ const { createEventListener } = require("@sentiance-react-native/core/lib/SentianceEventListenerUtils");
5
+ const { TransportTaggingError, E_TRANSPORT_TAG_ERROR } = require("./errors/errors");
6
+ const { SentianceEventTimeline, SentianceCore } = NativeModules;
6
7
 
7
8
  const TIMELINE_UPDATE_EVENT = "SENTIANCE_TIMELINE_UPDATE_EVENT";
8
9
 
9
10
  let didLocateNativeModule = true;
10
11
  let eventTimelineModule = {};
11
- if (Platform.OS === 'android') {
12
+ if (Platform.OS === "android") {
12
13
  if (!SentianceEventTimeline) {
13
14
  didLocateNativeModule = false;
14
- const nativeModuleName = varToString({SentianceEventTimeline});
15
+ const nativeModuleName = varToString({ SentianceEventTimeline });
15
16
  console.error(`Could not locate the native ${nativeModuleName} module.
16
17
  Make sure that your native code is properly linked, and that the module name you specified is correct.`);
17
18
  } else {
@@ -20,7 +21,7 @@ if (Platform.OS === 'android') {
20
21
  } else {
21
22
  if (!SentianceCore) {
22
23
  didLocateNativeModule = false;
23
- const nativeModuleName = varToString({SentianceCore});
24
+ const nativeModuleName = varToString({ SentianceCore });
24
25
  console.error(`Could not locate the native ${nativeModuleName} module.
25
26
  Make sure that your native code is properly linked, and that the module name you specified is correct.`);
26
27
  } else {
@@ -44,11 +45,23 @@ const getTimelineEvent = (eventId) => eventTimelineModule.getTimelineEvent(event
44
45
 
45
46
  const addTimelineUpdateListener = eventTimelineModule._addTimelineUpdateListener;
46
47
 
48
+ const setTransportTags = async (tags) => {
49
+ try {
50
+ return await eventTimelineModule.setTransportTags(tags);
51
+ } catch (e) {
52
+ if (e.code === E_TRANSPORT_TAG_ERROR) {
53
+ throw new TransportTaggingError(e.message);
54
+ }
55
+ throw e;
56
+ }
57
+ };
58
+
47
59
  module.exports = {
48
60
  getTimelineUpdates,
49
61
  getTimelineEvents,
50
62
  getTimelineEvent,
51
- addTimelineUpdateListener
63
+ addTimelineUpdateListener,
64
+ setTransportTags
52
65
  };
53
66
  module.exports.events = {
54
67
  TIMELINE_UPDATE_EVENT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentiance-react-native/event-timeline",
3
- "version": "6.9.1-rc.1",
3
+ "version": "6.10.0-alpha.1",
4
4
  "description": "The Sentiance Event Timeline library",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -14,7 +14,7 @@
14
14
  "sentiance"
15
15
  ],
16
16
  "peerDependencies": {
17
- "@sentiance-react-native/core": "6.9.1-rc.1"
17
+ "@sentiance-react-native/core": "6.10.0-alpha.1"
18
18
  },
19
19
  "author": "",
20
20
  "license": "",