@situm/react-native 3.15.20 → 3.16.1-beta.0

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.
Files changed (66) hide show
  1. package/android/src/main/java/com/situm/plugin/PluginHelper.java +42 -0
  2. package/android/src/main/java/com/situm/plugin/SitumMapper.java +5 -0
  3. package/android/src/main/java/com/situm/plugin/SitumPlugin.java +2 -0
  4. package/android/src/main/java/com/situm/plugin/SitumPluginImpl.java +33 -7
  5. package/android/src/main/java/com/situm/plugin/tts/TextToSpeechManager.java +87 -0
  6. package/ios/RNSitumReactNativePlugin.xcodeproj/project.pbxproj +6 -0
  7. package/ios/RNSitumReactNativePlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  8. package/ios/RNSitumReactNativePlugin.xcodeproj/project.xcworkspace/xcuserdata/situm.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  9. package/ios/RNSitumReactNativePlugin.xcodeproj/xcuserdata/situm.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  10. package/ios/SitumPlugin.m +47 -0
  11. package/ios/SitumTextToSpeechSpeaker.h +27 -0
  12. package/ios/SitumTextToSpeechSpeaker.m +82 -0
  13. package/lib/commonjs/sdk/index.js +19 -0
  14. package/lib/commonjs/sdk/index.js.map +1 -1
  15. package/lib/commonjs/sdk/nativeInterface.js.map +1 -1
  16. package/lib/commonjs/sdk/types/index.js +6 -0
  17. package/lib/commonjs/sdk/types/index.js.map +1 -1
  18. package/lib/commonjs/wayfinding/components/MapView.js +68 -28
  19. package/lib/commonjs/wayfinding/components/MapView.js.map +1 -1
  20. package/lib/commonjs/wayfinding/hooks/index.js +7 -6
  21. package/lib/commonjs/wayfinding/hooks/index.js.map +1 -1
  22. package/lib/commonjs/wayfinding/store/index.js +27 -4
  23. package/lib/commonjs/wayfinding/store/index.js.map +1 -1
  24. package/lib/commonjs/wayfinding/utils/index.js.map +1 -1
  25. package/lib/commonjs/wayfinding/utils/mapper.js +3 -0
  26. package/lib/commonjs/wayfinding/utils/mapper.js.map +1 -1
  27. package/lib/module/sdk/index.js +19 -0
  28. package/lib/module/sdk/index.js.map +1 -1
  29. package/lib/module/sdk/nativeInterface.js.map +1 -1
  30. package/lib/module/sdk/types/index.js +6 -0
  31. package/lib/module/sdk/types/index.js.map +1 -1
  32. package/lib/module/wayfinding/components/MapView.js +46 -6
  33. package/lib/module/wayfinding/components/MapView.js.map +1 -1
  34. package/lib/module/wayfinding/hooks/index.js +7 -6
  35. package/lib/module/wayfinding/hooks/index.js.map +1 -1
  36. package/lib/module/wayfinding/store/index.js +26 -5
  37. package/lib/module/wayfinding/store/index.js.map +1 -1
  38. package/lib/module/wayfinding/utils/index.js.map +1 -1
  39. package/lib/module/wayfinding/utils/mapper.js +3 -0
  40. package/lib/module/wayfinding/utils/mapper.js.map +1 -1
  41. package/lib/typescript/sdk/index.d.ts +9 -1
  42. package/lib/typescript/sdk/index.d.ts.map +1 -1
  43. package/lib/typescript/sdk/nativeInterface.d.ts +5 -2
  44. package/lib/typescript/sdk/nativeInterface.d.ts.map +1 -1
  45. package/lib/typescript/sdk/types/index.d.ts +25 -2
  46. package/lib/typescript/sdk/types/index.d.ts.map +1 -1
  47. package/lib/typescript/wayfinding/components/MapView.d.ts +6 -3
  48. package/lib/typescript/wayfinding/components/MapView.d.ts.map +1 -1
  49. package/lib/typescript/wayfinding/hooks/index.d.ts.map +1 -1
  50. package/lib/typescript/wayfinding/store/index.d.ts +22 -2
  51. package/lib/typescript/wayfinding/store/index.d.ts.map +1 -1
  52. package/lib/typescript/wayfinding/types/index.d.ts +11 -1
  53. package/lib/typescript/wayfinding/types/index.d.ts.map +1 -1
  54. package/lib/typescript/wayfinding/utils/index.d.ts.map +1 -1
  55. package/lib/typescript/wayfinding/utils/mapper.d.ts +2 -1
  56. package/lib/typescript/wayfinding/utils/mapper.d.ts.map +1 -1
  57. package/package.json +2 -2
  58. package/src/sdk/index.ts +21 -0
  59. package/src/sdk/nativeInterface.ts +7 -1
  60. package/src/sdk/types/index.ts +26 -2
  61. package/src/wayfinding/components/MapView.tsx +85 -16
  62. package/src/wayfinding/hooks/index.ts +7 -6
  63. package/src/wayfinding/store/index.tsx +64 -7
  64. package/src/wayfinding/types/index.ts +14 -3
  65. package/src/wayfinding/utils/index.ts +4 -1
  66. package/src/wayfinding/utils/mapper.ts +7 -3
@@ -4,6 +4,7 @@ import React, {
4
4
  useCallback,
5
5
  useEffect,
6
6
  useImperativeHandle,
7
+ useMemo,
7
8
  useRef,
8
9
  useState,
9
10
  } from "react";
@@ -19,8 +20,16 @@ import type {
19
20
  WebViewErrorEvent,
20
21
  WebViewMessageEvent,
21
22
  } from "react-native-webview/lib/WebViewTypes";
23
+
22
24
  import SitumPlugin from "../../sdk";
23
25
  import useSitum from "../hooks";
26
+ import {
27
+ selectApiDomain,
28
+ selectUser,
29
+ setError,
30
+ setLocationStatus,
31
+ } from "../store";
32
+ import { useSelector } from "../store/utils";
24
33
  import {
25
34
  type CartographySelectionOptions,
26
35
  type MapViewDirectionsOptions,
@@ -40,7 +49,6 @@ import {
40
49
  import { ErrorName } from "../types/constants";
41
50
  import { sendMessageToViewer } from "../utils";
42
51
  import ViewerMapper from "../utils/mapper";
43
- import { setError, setLocationStatus } from "../store";
44
52
  const SITUM_BASE_DOMAIN = "https://maps.situm.com";
45
53
 
46
54
  const NETWORK_ERROR_CODE = {
@@ -64,10 +72,14 @@ export type MapViewConfiguration = {
64
72
  */
65
73
  viewerDomain?: string;
66
74
  /**
67
- * ** Required **
68
- * Your Situm API key. Find your API key at your [situm profile](https://dashboard.situm.com/accounts/profile)
75
+ * Your Situm API key. Find your API key at your [Situm dashboard's profile](https://dashboard.situm.com/accounts/profile)
76
+ *
77
+ * Since X.YY.ZZ version this parameter is not required. Instead, you should specify your apiKey
78
+ * at the root of your app with `SitumProvider.apiKey` for the correct usage of the plugin.
79
+ * If {@param situmApiKey} is specified, `SitumProvider.apiKey` will be ignored.
69
80
  */
70
- situmApiKey: string;
81
+ // TODO: set the version on the doc right before releasing this version.
82
+ situmApiKey?: string;
71
83
  /**
72
84
  * @deprecated Use `profile` instead.
73
85
  * A String identifier that allows you to remotely configure all map settings.
@@ -168,6 +180,9 @@ const MapView = React.forwardRef<MapViewRef, MapViewProps>(
168
180
  const [buildingIdentifier, setBuildingIdentifier] = useState<string>(
169
181
  configuration.buildingIdentifier,
170
182
  );
183
+
184
+ const user = useSelector(selectUser);
185
+ const apiDomain = useSelector(selectApiDomain);
171
186
  const {
172
187
  init,
173
188
  location,
@@ -496,6 +511,8 @@ const MapView = React.forwardRef<MapViewRef, MapViewProps>(
496
511
  webViewRef.current,
497
512
  ViewerMapper.initialConfiguration(style),
498
513
  );
514
+
515
+ _disableInternalWebViewTTSEngine();
499
516
  }
500
517
  }, [webViewRef, mapLoaded, style]);
501
518
 
@@ -556,6 +573,9 @@ const MapView = React.forwardRef<MapViewRef, MapViewProps>(
556
573
  case "viewer.navigation.stopped":
557
574
  SitumPlugin.updateNavigationState(eventParsed.payload);
558
575
  break;
576
+ case "ui.speak_aloud_text":
577
+ SitumPlugin.speakAloudText(eventParsed.payload);
578
+ break;
559
579
  default:
560
580
  break;
561
581
  }
@@ -580,8 +600,31 @@ const MapView = React.forwardRef<MapViewRef, MapViewProps>(
580
600
  return true;
581
601
  };
582
602
 
583
- const _effectiveProfile = () => {
584
- let effectiveProfile = configuration.profile;
603
+ const _effectiveApiKey = useMemo(() => {
604
+ const internalApiKey = user?.apiKey;
605
+ const configApiKey = configuration.situmApiKey;
606
+
607
+ if (!configApiKey && !internalApiKey) {
608
+ console.error(
609
+ "No apiKey was specified. Make sure to be authenticated either by specifying the SitumProvider.apiKey or by specifying the MapViewConfiguration.situmApiKey.",
610
+ );
611
+ }
612
+
613
+ return configApiKey ?? internalApiKey;
614
+ }, [user?.apiKey, configuration.situmApiKey]);
615
+
616
+ const _effectiveProfile = useMemo(() => {
617
+ let effectiveProfile: any = "";
618
+
619
+ if (
620
+ configuration.profile?.length === 0 &&
621
+ configuration.remoteIdentifier?.length === 0
622
+ ) {
623
+ effectiveProfile = "";
624
+ }
625
+
626
+ effectiveProfile = configuration.profile;
627
+
585
628
  if (
586
629
  configuration.remoteIdentifier &&
587
630
  configuration.remoteIdentifier.length > 0
@@ -589,26 +632,52 @@ const MapView = React.forwardRef<MapViewRef, MapViewProps>(
589
632
  console.warn(
590
633
  'Situm> MapView> [!] "remoteIdentifier" is deprecated. Use "profile" instead.',
591
634
  );
592
- if (!configuration.profile || configuration.profile.length == 0) {
635
+ if (!configuration.profile || configuration.profile.length === 0) {
593
636
  effectiveProfile = configuration.remoteIdentifier;
594
637
  }
595
638
  }
639
+
596
640
  return effectiveProfile;
641
+ }, [configuration.profile, configuration.remoteIdentifier]);
642
+
643
+ const _effectiveApiDomain = useMemo(() => {
644
+ let finalApiDomain = configuration.apiDomain ?? apiDomain;
645
+
646
+ if (!finalApiDomain) return "";
647
+
648
+ finalApiDomain = finalApiDomain.replace("https://", "");
649
+ finalApiDomain = finalApiDomain.replace("/", "");
650
+
651
+ return `&domain=${finalApiDomain}`;
652
+ }, [apiDomain, configuration.apiDomain]);
653
+
654
+ const _effectiveBuildingId = useMemo(() => {
655
+ let finalBuildingIdentifier = "";
656
+ const buildingId = configuration.buildingIdentifier;
657
+
658
+ if (buildingId && buildingId.length > 0) {
659
+ finalBuildingIdentifier = `&buildingid=${buildingId}`;
660
+ }
661
+
662
+ return finalBuildingIdentifier;
663
+ }, [configuration.buildingIdentifier]);
664
+
665
+ const _disableInternalWebViewTTSEngine = () => {
666
+ sendMessageToViewer(
667
+ webViewRef.current,
668
+ ViewerMapper.setConfigItems([
669
+ { key: "internal.tts.engine", value: "mobile" },
670
+ ]),
671
+ );
597
672
  };
598
673
 
599
674
  return (
600
675
  <WebView
601
676
  ref={webViewRef}
602
677
  source={{
603
- uri: `${configuration.viewerDomain || SITUM_BASE_DOMAIN}/${
604
- _effectiveProfile() ? `id/${_effectiveProfile()}` : ""
605
- }?&apikey=${
606
- configuration.situmApiKey
607
- }&wl=true&global=true&mode=embed${
608
- configuration.buildingIdentifier
609
- ? `&buildingid=${configuration.buildingIdentifier}`
610
- : ""
611
- }&show=rts`,
678
+ uri: `${configuration.viewerDomain || SITUM_BASE_DOMAIN}/${_effectiveProfile}?apikey=${
679
+ _effectiveApiKey
680
+ }${_effectiveApiDomain}${_effectiveBuildingId}&mode=embed`,
612
681
  }}
613
682
  style={StyleSheet.flatten([viewerStyles.webview, style])}
614
683
  limitsNavigationsToAppBoundDomains={true}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-case-declarations */
1
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
3
  import { useContext, useState } from "react";
3
4
 
@@ -66,15 +67,15 @@ export const useSitumInternal = () => {
66
67
  (internalCall: InternalCall) => {
67
68
  switch (internalCall.type) {
68
69
  case InternalCallType.LOCATION:
69
- let location = internalCall.get<Location>();
70
+ const receivedLocation = internalCall.get<Location>();
70
71
  dispatch(
71
72
  setLocation({
72
- ...location,
73
+ ...receivedLocation,
73
74
  }),
74
75
  );
75
76
  break;
76
77
  case InternalCallType.LOCATION_STATUS:
77
- let statusName = internalCall.get<string>();
78
+ const statusName = internalCall.get<string>();
78
79
  if (statusName in LocationStatusName) {
79
80
  dispatch(setLocationStatus(statusName));
80
81
  }
@@ -84,8 +85,8 @@ export const useSitumInternal = () => {
84
85
  dispatch(resetLocation());
85
86
  break;
86
87
  case InternalCallType.LOCATION_ERROR:
87
- let error = internalCall.get<Error>();
88
- dispatch(setError(error));
88
+ const receivedError = internalCall.get<Error>();
89
+ dispatch(setError(receivedError));
89
90
  break;
90
91
  case InternalCallType.NAVIGATION_START:
91
92
  dispatch(
@@ -104,7 +105,7 @@ export const useSitumInternal = () => {
104
105
  );
105
106
  break;
106
107
  case InternalCallType.NAVIGATION_PROGRESS:
107
- let progress = internalCall.get<NavigationProgress>();
108
+ const progress = internalCall.get<NavigationProgress>();
108
109
  dispatch(
109
110
  setNavigation({
110
111
  currentIndication: progress?.currentIndication,
@@ -1,6 +1,13 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import React, { createContext, type MutableRefObject, useReducer } from "react";
2
+ import React, {
3
+ createContext,
4
+ type MutableRefObject,
5
+ useEffect,
6
+ useReducer,
7
+ useState,
8
+ } from "react";
3
9
 
10
+ import SitumPlugin from "../../sdk";
4
11
  import {
5
12
  type Building,
6
13
  type Directions,
@@ -22,6 +29,7 @@ export interface State {
22
29
  webViewRef: MutableRefObject<undefined> | undefined;
23
30
  sdkInitialized: boolean;
24
31
  user?: User;
32
+ apiDomain?: string;
25
33
  location?: Location;
26
34
  locationStatus?: LocationStatusName;
27
35
  buildings: Building[] | null;
@@ -38,6 +46,7 @@ export const initialState: State = {
38
46
  webViewRef: undefined,
39
47
  sdkInitialized: false,
40
48
  user: undefined,
49
+ apiDomain: undefined,
41
50
  location: undefined,
42
51
  locationStatus: undefined,
43
52
  buildings: null,
@@ -101,7 +110,7 @@ const store = createStore<State>({
101
110
  },
102
111
  setBuildingIdentifier: (
103
112
  state: State,
104
- payload: State["buildingIdentifier"]
113
+ payload: State["buildingIdentifier"],
105
114
  ) => {
106
115
  return { ...state, buildingIdentifier: payload };
107
116
  },
@@ -120,6 +129,10 @@ export const selectUser = (state: State) => {
120
129
  return state.user;
121
130
  };
122
131
 
132
+ export const selectApiDomain = (state: State) => {
133
+ return state.apiDomain;
134
+ };
135
+
123
136
  export const selectLocation = (state: State) => {
124
137
  return state.location;
125
138
  };
@@ -181,7 +194,7 @@ export const {
181
194
  * Context specifically to store the only instance of our hook.
182
195
  */
183
196
  export const UseSitumContext = createContext<{ useSitum: any } | undefined>(
184
- undefined
197
+ undefined,
185
198
  );
186
199
 
187
200
  const UseSitumProvider: React.FC<{ children: React.ReactNode }> = ({
@@ -199,19 +212,56 @@ const UseSitumProvider: React.FC<{ children: React.ReactNode }> = ({
199
212
  };
200
213
 
201
214
  /**
202
- * Main context of the application, stores the plugins' state.
215
+ * Main context of the application, stores the plugin's state.
203
216
  */
204
217
  const SitumProvider: React.FC<
205
218
  React.PropsWithChildren<{
219
+ /**
220
+ * Your Situm email account.
221
+ */
206
222
  email?: string;
207
- apiKey?: string;
223
+ /**
224
+ * Your Situm API key. Find your API key at your [Situm dashboard's profile](https://dashboard.situm.com/accounts/profile)
225
+ *
226
+ * When specifying a valid situm API key in this parameter, you won't need to call later on the `SitumPlugin.init()` & `SitumPlugin.setApiKey()` methods,
227
+ * and also you won't need to specify `MapViewConfiguration.situmApiKey` when configuring your MapView.
228
+ */
229
+ apiKey: string;
230
+ /**
231
+ * Set the API domain that will be used by the native SDKs and MapView to obtain the situm's data.
232
+ *
233
+ * When specifying a valid domain in this parameter, you won't need to call later on the `SitumPlugin.setDashboardURL()` method,
234
+ * and also you won't need to specify `MapViewConfiguration.apiDomain` when configuring your MapView.
235
+ *
236
+ * Defaults to "api.situm.com"
237
+ */
238
+ apiDomain?: string;
208
239
  }>
209
- > = ({ email, apiKey, children }) => {
240
+ > = ({ email, apiKey, apiDomain, children }) => {
210
241
  const [state, dispatch] = useReducer(store.reducer, {
211
242
  ...store.initialState,
212
243
  user: { email, apiKey },
244
+ apiDomain: apiDomain,
213
245
  });
214
246
 
247
+ const [isInitialized, setIsInitialized] = useState(false);
248
+
249
+ useEffect(() => {
250
+ try {
251
+ SitumPlugin.init();
252
+ apiDomain && SitumPlugin.setDashboardURL(apiDomain);
253
+ if (!apiKey) {
254
+ throw new Error(
255
+ "Please specify SitumProvider.apiKey to be able to successfully use SitumPlugin and MapView.",
256
+ );
257
+ }
258
+ SitumPlugin.setApiKey(apiKey);
259
+ } catch (e) {
260
+ console.error(`SitumProvider > Could not initialize ${e}`);
261
+ }
262
+ setIsInitialized(true);
263
+ }, [apiKey, apiDomain]);
264
+
215
265
  return (
216
266
  <SitumContext.Provider
217
267
  value={{
@@ -219,7 +269,14 @@ const SitumProvider: React.FC<
219
269
  dispatch,
220
270
  }}
221
271
  >
222
- <UseSitumProvider>{children}</UseSitumProvider>
272
+ {/**
273
+ * Make sure to execute first SitumProvider's initialization & authentication useEffect(),
274
+ * before letting children components rendering MapView or calling SitumPlugin methods.
275
+ *
276
+ * If we directly let the `children` render, the children's useEffect() will execute before SitumProvider's useEffect().
277
+ * This causes a crash when the children wants to access SitumPlugin before it is initialized.
278
+ */}
279
+ <UseSitumProvider>{isInitialized ? children : <></>}</UseSitumProvider>
223
280
  </SitumContext.Provider>
224
281
  );
225
282
  };
@@ -1,6 +1,5 @@
1
- import { AccessibilityMode } from "../../sdk/types/constants";
2
-
3
1
  import type { DirectionsRequest, Point } from "../../sdk/types";
2
+ import { AccessibilityMode } from "../../sdk/types/constants";
4
3
  export type { MapViewConfiguration, MapViewProps } from "../components/MapView";
5
4
  import { ErrorName } from "./constants";
6
5
 
@@ -33,7 +32,7 @@ export interface MapViewRef {
33
32
  */
34
33
  selectFloor: (
35
34
  floorIdentifier: number,
36
- options?: CartographySelectionOptions
35
+ options?: CartographySelectionOptions,
37
36
  ) => void;
38
37
  /**
39
38
  * Define the {@link MapViewDirectionsOptions} that the routes calculated by the MapView will use.
@@ -221,3 +220,15 @@ export interface SearchFilter {
221
220
  export interface CartographySelectionOptions {
222
221
  fitCamera?: boolean;
223
222
  }
223
+
224
+ export interface ViewerConfigItem {
225
+ /**
226
+ * A dot notation key referring to all the keys related to internal ConfigState of the viewer.
227
+ */
228
+ key: string;
229
+
230
+ /**
231
+ * The value that we want to set for the corresponding ConfigState key.
232
+ */
233
+ value: any;
234
+ }
@@ -1,6 +1,9 @@
1
1
  import WebView from "react-native-webview";
2
2
 
3
- export const sendMessageToViewer = (viewer: WebView | null, message: string) => {
3
+ export const sendMessageToViewer = (
4
+ viewer: WebView | null,
5
+ message: string,
6
+ ) => {
4
7
  if (!viewer) return;
5
8
  viewer.injectJavaScript(`window.postMessage(${message})`);
6
9
  };
@@ -18,6 +18,7 @@ import type {
18
18
  Navigation,
19
19
  OnNavigationResult,
20
20
  SearchFilter,
21
+ ViewerConfigItem,
21
22
  } from "../types";
22
23
 
23
24
  export const createPoint = (payload: any): Point => {
@@ -72,8 +73,8 @@ export const createNavigationRequest = (payload: any): NavigationRequest => {
72
73
 
73
74
  return Object.fromEntries(
74
75
  Object.entries(navigationRequest || {}).filter(
75
- ([_, value]) => value !== undefined
76
- )
76
+ ([_, value]) => value !== undefined,
77
+ ),
77
78
  );
78
79
  };
79
80
 
@@ -113,7 +114,7 @@ const ViewerMapper = {
113
114
  },
114
115
  selectFloor: (
115
116
  floorIdentifier: number,
116
- options?: CartographySelectionOptions
117
+ options?: CartographySelectionOptions,
117
118
  ) => {
118
119
  return mapperWrapper(`cartography.select_floor`, {
119
120
  identifier: floorIdentifier,
@@ -213,6 +214,9 @@ const ViewerMapper = {
213
214
  poiCategoryIdentifier: searchFilter.poiCategoryIdentifier,
214
215
  });
215
216
  },
217
+ setConfigItems: (configItems: ViewerConfigItem[]) => {
218
+ return mapperWrapper(`app.set_config_item`, configItems);
219
+ },
216
220
  };
217
221
 
218
222
  export default ViewerMapper;