react-native-pointr 10.7.1 → 10.9.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.
@@ -7,3 +7,12 @@ export {
7
7
  usePointrSiteClick,
8
8
  } from './usePointrEvents';
9
9
  export { usePointrGeofences } from './usePointrGeofences';
10
+ export { usePointrData } from './usePointrData';
11
+ export { usePointrSite } from './usePointrSite';
12
+ export {
13
+ usePointrDataManagerStart,
14
+ usePointrDataManagerCompleteAll,
15
+ usePointrDataManagerBeginProcessing,
16
+ usePointrDataManagerEndProcessing,
17
+ usePointrDataManagerReady,
18
+ } from './usePointrDataEvents';
@@ -0,0 +1,94 @@
1
+ import { useEffect, useState, useCallback } from 'react';
2
+ import {
3
+ loadDataForSite,
4
+ isSiteContentReady,
5
+ } from '../managers/PTRDataManager';
6
+ import { pointrSdk } from '../api/PointrSdk';
7
+ import type { PTRDataManagerReadyEvent } from '../types/events';
8
+
9
+ /**
10
+ * Hook that manages a site's data lifecycle.
11
+ *
12
+ * It demonstrates the {@link loadDataForSite} and {@link isSiteContentReady}
13
+ * data-manager methods: on mount it triggers data management for the site and
14
+ * checks the current readiness, then keeps `isReady` in sync by listening for
15
+ * the `OnDataManagerReadyForSite` event emitted once all data is available.
16
+ *
17
+ * @param siteId - Site identifier to manage data for
18
+ * @param options - Optional flags forwarded to the data manager
19
+ * @param options.shouldRespectCachePolicy - When `true` (default), respects the
20
+ * internal cache; when `false`, forces a fresh data update.
21
+ * @param options.isExternalIdentifier - When `false` (default), `siteId` is the
22
+ * internal identifier; when `true`, it is the external identifier.
23
+ * @returns `{ isReady, loading, error, reload }`
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const { isReady, loading, reload } = usePointrData(SITE_ID);
28
+ *
29
+ * if (loading) return <Spinner />;
30
+ * return isReady ? <Map siteId={SITE_ID} /> : <Button onPress={reload} title="Load" />;
31
+ * ```
32
+ */
33
+ export function usePointrData(
34
+ siteId?: string,
35
+ options?: {
36
+ shouldRespectCachePolicy?: boolean;
37
+ isExternalIdentifier?: boolean;
38
+ }
39
+ ) {
40
+ const [isReady, setIsReady] = useState(false);
41
+ const [loading, setLoading] = useState(false);
42
+ const [error, setError] = useState<Error | null>(null);
43
+
44
+ const shouldRespectCachePolicy = options?.shouldRespectCachePolicy ?? true;
45
+ const isExternalIdentifier = options?.isExternalIdentifier ?? false;
46
+
47
+ const load = useCallback(
48
+ async (id: string) => {
49
+ if (!id) return;
50
+ setLoading(true);
51
+ setError(null);
52
+ try {
53
+ await loadDataForSite(id, shouldRespectCachePolicy, isExternalIdentifier);
54
+ const ready = await isSiteContentReady(id, isExternalIdentifier);
55
+ setIsReady(ready);
56
+ } catch (err) {
57
+ setError(err as Error);
58
+ } finally {
59
+ setLoading(false);
60
+ }
61
+ },
62
+ [shouldRespectCachePolicy, isExternalIdentifier]
63
+ );
64
+
65
+ // Trigger data management whenever the target site changes.
66
+ useEffect(() => {
67
+ if (siteId) {
68
+ load(siteId);
69
+ }
70
+ }, [siteId, load]);
71
+
72
+ // Keep `isReady` in sync once the data manager reports the site is ready.
73
+ useEffect(() => {
74
+ if (!siteId) return;
75
+ const subscription = pointrSdk.onDataManagerReady(
76
+ (event: PTRDataManagerReadyEvent) => {
77
+ const readySiteId = isExternalIdentifier
78
+ ? event.site.externalIdentifier
79
+ : event.site.identifier;
80
+ if (readySiteId === siteId) {
81
+ setIsReady(true);
82
+ }
83
+ }
84
+ );
85
+ return () => subscription.remove();
86
+ }, [siteId, isExternalIdentifier]);
87
+
88
+ return {
89
+ isReady,
90
+ loading,
91
+ error,
92
+ reload: () => siteId && load(siteId),
93
+ };
94
+ }
@@ -0,0 +1,74 @@
1
+ import { useEffect } from 'react';
2
+ import { pointrSdk } from '../api/PointrSdk';
3
+ import type {
4
+ PTRDataManagerStartEvent,
5
+ PTRDataManagerCompleteAllEvent,
6
+ PTRDataManagerBeginProcessingEvent,
7
+ PTRDataManagerEndProcessingEvent,
8
+ PTRDataManagerReadyEvent,
9
+ } from '../types/events';
10
+
11
+ /**
12
+ * Hook to listen for data-management-start events.
13
+ * @param callback - Called when the data manager starts managing a site's data
14
+ */
15
+ export function usePointrDataManagerStart(
16
+ callback: (event: PTRDataManagerStartEvent) => void
17
+ ) {
18
+ useEffect(() => {
19
+ const subscription = pointrSdk.onDataManagerStart(callback);
20
+ return () => subscription.remove();
21
+ }, [callback]);
22
+ }
23
+
24
+ /**
25
+ * Hook to listen for data-management-complete-all events.
26
+ * @param callback - Called when all data processing for a site completes
27
+ */
28
+ export function usePointrDataManagerCompleteAll(
29
+ callback: (event: PTRDataManagerCompleteAllEvent) => void
30
+ ) {
31
+ useEffect(() => {
32
+ const subscription = pointrSdk.onDataManagerCompleteAll(callback);
33
+ return () => subscription.remove();
34
+ }, [callback]);
35
+ }
36
+
37
+ /**
38
+ * Hook to listen for begin-processing events for a specific data type.
39
+ * @param callback - Called when a specific data type starts being processed
40
+ */
41
+ export function usePointrDataManagerBeginProcessing(
42
+ callback: (event: PTRDataManagerBeginProcessingEvent) => void
43
+ ) {
44
+ useEffect(() => {
45
+ const subscription = pointrSdk.onDataManagerBeginProcessing(callback);
46
+ return () => subscription.remove();
47
+ }, [callback]);
48
+ }
49
+
50
+ /**
51
+ * Hook to listen for end-processing events for a specific data type.
52
+ * @param callback - Called when a specific data type finishes being processed
53
+ */
54
+ export function usePointrDataManagerEndProcessing(
55
+ callback: (event: PTRDataManagerEndProcessingEvent) => void
56
+ ) {
57
+ useEffect(() => {
58
+ const subscription = pointrSdk.onDataManagerEndProcessing(callback);
59
+ return () => subscription.remove();
60
+ }, [callback]);
61
+ }
62
+
63
+ /**
64
+ * Hook to listen for site-ready events (all data available to display a site).
65
+ * @param callback - Called when a site becomes ready to display
66
+ */
67
+ export function usePointrDataManagerReady(
68
+ callback: (event: PTRDataManagerReadyEvent) => void
69
+ ) {
70
+ useEffect(() => {
71
+ const subscription = pointrSdk.onDataManagerReady(callback);
72
+ return () => subscription.remove();
73
+ }, [callback]);
74
+ }
@@ -0,0 +1,73 @@
1
+ import { useEffect, useState, useCallback } from 'react';
2
+ import { getSite, getBuildings } from '../managers/PTRSiteManager';
3
+ import type { PTRSite, PTRBuilding } from '../types/PTRSite';
4
+
5
+ /**
6
+ * Hook that loads a site and its buildings.
7
+ *
8
+ * It demonstrates the {@link getSite} and {@link getBuildings} site-manager
9
+ * methods: whenever the target site changes it fetches the site and, if found,
10
+ * its buildings.
11
+ *
12
+ * @param siteId - Site identifier to load
13
+ * @param options - Optional flags forwarded to the site manager
14
+ * @param options.isExternalIdentifier - When `false` (default), `siteId` is the
15
+ * internal identifier; when `true`, it is the external identifier.
16
+ * @returns `{ site, buildings, loading, error, refetch }`
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * const { site, buildings, loading } = usePointrSite(SITE_ID);
21
+ *
22
+ * if (loading) return <Spinner />;
23
+ * return <Text>{site?.name} — {buildings.length} buildings</Text>;
24
+ * ```
25
+ */
26
+ export function usePointrSite(
27
+ siteId?: string,
28
+ options?: { isExternalIdentifier?: boolean }
29
+ ) {
30
+ const [site, setSite] = useState<PTRSite | null>(null);
31
+ const [buildings, setBuildings] = useState<PTRBuilding[]>([]);
32
+ const [loading, setLoading] = useState(false);
33
+ const [error, setError] = useState<Error | null>(null);
34
+
35
+ const isExternalIdentifier = options?.isExternalIdentifier ?? false;
36
+
37
+ const fetchSite = useCallback(
38
+ async (id: string) => {
39
+ if (!id) return;
40
+ setLoading(true);
41
+ setError(null);
42
+ try {
43
+ const fetchedSite = await getSite(id, isExternalIdentifier);
44
+ setSite(fetchedSite);
45
+ if (fetchedSite) {
46
+ const fetchedBuildings = await getBuildings(id, isExternalIdentifier);
47
+ setBuildings(fetchedBuildings);
48
+ } else {
49
+ setBuildings([]);
50
+ }
51
+ } catch (err) {
52
+ setError(err as Error);
53
+ } finally {
54
+ setLoading(false);
55
+ }
56
+ },
57
+ [isExternalIdentifier]
58
+ );
59
+
60
+ useEffect(() => {
61
+ if (siteId) {
62
+ fetchSite(siteId);
63
+ }
64
+ }, [siteId, fetchSite]);
65
+
66
+ return {
67
+ site,
68
+ buildings,
69
+ loading,
70
+ error,
71
+ refetch: () => siteId && fetchSite(siteId),
72
+ };
73
+ }
package/src/index.tsx CHANGED
@@ -41,11 +41,15 @@ export {
41
41
  PTRActionParamKeys,
42
42
  PTRSdkConfigKeys,
43
43
  PTRCommandNames,
44
+ PTREventPayloadKeys,
45
+ PTRModelKeys,
44
46
  } from './constants';
45
47
  export type {
46
48
  PTRActionParamKey,
47
49
  PTRSdkConfigKey,
48
50
  PTRCommandName,
51
+ PTREventPayloadKey,
52
+ PTRModelKey,
49
53
  } from './constants';
50
54
 
51
55
  // ─── React Hooks ───────────────────────────────────────────────────────────────
@@ -57,6 +61,13 @@ export {
57
61
  usePointrBuildingClick,
58
62
  usePointrSiteClick,
59
63
  usePointrGeofences,
64
+ usePointrData,
65
+ usePointrSite,
66
+ usePointrDataManagerStart,
67
+ usePointrDataManagerCompleteAll,
68
+ usePointrDataManagerBeginProcessing,
69
+ usePointrDataManagerEndProcessing,
70
+ usePointrDataManagerReady,
60
71
  } from './hooks';
61
72
 
62
73
  // ─── Components ────────────────────────────────────────────────────────────────
@@ -91,6 +102,12 @@ export type {
91
102
  PTRGeofence,
92
103
  PTRGeofenceNotification,
93
104
  PTRMapCommandResponse,
105
+ PTRDataType,
106
+ PTRDataManagerStartEvent,
107
+ PTRDataManagerCompleteAllEvent,
108
+ PTRDataManagerBeginProcessingEvent,
109
+ PTRDataManagerEndProcessingEvent,
110
+ PTRDataManagerReadyEvent,
94
111
  } from './types/events';
95
112
 
96
113
  export { PTRGeofenceEventType } from './types/events';
@@ -0,0 +1,57 @@
1
+ import { NativeModules } from 'react-native';
2
+
3
+ const { PTRNativeLibrary } = NativeModules;
4
+
5
+ /**
6
+ * Start data management for a specific site if the data is not already present.
7
+ * @param siteId - The identifier of the site
8
+ * @param shouldRespectCachePolicy - When `true` (default), waits until the
9
+ * cache expires if data is already present. When `false`, ignores the internal
10
+ * cache and triggers a data update immediately.
11
+ * @param isExternalIdentifier - When `false` (default), `siteId` is treated as
12
+ * the site's internal identifier. When `true`, it is treated as the external
13
+ * identifier.
14
+ * @returns Promise that resolves once data management has been triggered
15
+ * @throws Error if the site is not found or if the operation fails
16
+ */
17
+ export async function loadDataForSite(
18
+ siteId: string,
19
+ shouldRespectCachePolicy: boolean = true,
20
+ isExternalIdentifier: boolean = false
21
+ ): Promise<void> {
22
+ try {
23
+ await PTRNativeLibrary.loadDataForSite(
24
+ siteId,
25
+ shouldRespectCachePolicy,
26
+ isExternalIdentifier
27
+ );
28
+ } catch (error) {
29
+ console.error('Failed to load data for site:', error);
30
+ throw error;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Check whether all data is ready for use for a given site.
36
+ * @param siteId - The identifier of the site
37
+ * @param isExternalIdentifier - When `false` (default), `siteId` is treated as
38
+ * the site's internal identifier. When `true`, it is treated as the external
39
+ * identifier.
40
+ * @returns Promise that resolves with `true` if the site content is ready
41
+ * @throws Error if the site is not found or if the operation fails
42
+ */
43
+ export async function isSiteContentReady(
44
+ siteId: string,
45
+ isExternalIdentifier: boolean = false
46
+ ): Promise<boolean> {
47
+ try {
48
+ const isReady = await PTRNativeLibrary.isSiteContentReady(
49
+ siteId,
50
+ isExternalIdentifier
51
+ );
52
+ return isReady as boolean;
53
+ } catch (error) {
54
+ console.error('Failed to check site content readiness:', error);
55
+ throw error;
56
+ }
57
+ }
@@ -0,0 +1,143 @@
1
+ import { NativeModules } from 'react-native';
2
+ import type { PTRSite, PTRBuilding } from '../types/PTRSite';
3
+
4
+ const { PTRNativeLibrary } = NativeModules;
5
+
6
+ /**
7
+ * Get the name of the client.
8
+ * @returns Promise that resolves with the client name
9
+ * @throws Error if the operation fails
10
+ */
11
+ export async function getClientName(): Promise<string> {
12
+ try {
13
+ const clientName = await PTRNativeLibrary.getClientName();
14
+ return clientName as string;
15
+ } catch (error) {
16
+ console.error('Failed to get client name:', error);
17
+ throw error;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Get all available sites.
23
+ * @returns Promise that resolves with an array of sites
24
+ * @throws Error if the operation fails
25
+ */
26
+ export async function getSites(): Promise<PTRSite[]> {
27
+ try {
28
+ const sites = await PTRNativeLibrary.getSites();
29
+ return sites as PTRSite[];
30
+ } catch (error) {
31
+ console.error('Failed to get sites:', error);
32
+ throw error;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Get a single site by its identifier.
38
+ * @param siteId - The identifier of the site
39
+ * @param isExternalIdentifier - When `false` (default), `siteId` is treated as
40
+ * the internal identifier. When `true`, it is treated as the external identifier.
41
+ * @returns Promise that resolves with the site, or `null` if not found
42
+ * @throws Error if the operation fails
43
+ */
44
+ export async function getSite(
45
+ siteId: string,
46
+ isExternalIdentifier: boolean = false
47
+ ): Promise<PTRSite | null> {
48
+ try {
49
+ const site = await PTRNativeLibrary.getSite(siteId, isExternalIdentifier);
50
+ return (site as PTRSite) ?? null;
51
+ } catch (error) {
52
+ console.error('Failed to get site:', error);
53
+ throw error;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Get all buildings for a site.
59
+ * @param siteId - The identifier of the site
60
+ * @param isExternalIdentifier - When `false` (default), `siteId` is treated as
61
+ * the internal identifier. When `true`, it is treated as the external identifier.
62
+ * @returns Promise that resolves with an array of buildings
63
+ * @throws Error if the site is not found or if the operation fails
64
+ */
65
+ export async function getBuildings(
66
+ siteId: string,
67
+ isExternalIdentifier: boolean = false
68
+ ): Promise<PTRBuilding[]> {
69
+ try {
70
+ const buildings = await PTRNativeLibrary.getSiteBuildings(
71
+ siteId,
72
+ isExternalIdentifier
73
+ );
74
+ return buildings as PTRBuilding[];
75
+ } catch (error) {
76
+ console.error('Failed to get buildings:', error);
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Get a single building within a site by its identifier.
83
+ * @param siteId - The identifier of the site containing the building
84
+ * @param buildingId - The identifier of the building
85
+ * @param isExternalIdentifier - When `false` (default), both identifiers are
86
+ * treated as internal identifiers. When `true`, they are treated as external
87
+ * identifiers.
88
+ * @returns Promise that resolves with the building, or `null` if not found
89
+ * @throws Error if the operation fails
90
+ */
91
+ export async function getBuilding(
92
+ siteId: string,
93
+ buildingId: string,
94
+ isExternalIdentifier: boolean = false
95
+ ): Promise<PTRBuilding | null> {
96
+ try {
97
+ const building = await PTRNativeLibrary.getBuilding(
98
+ siteId,
99
+ buildingId,
100
+ isExternalIdentifier
101
+ );
102
+ return (building as PTRBuilding) ?? null;
103
+ } catch (error) {
104
+ console.error('Failed to get building:', error);
105
+ throw error;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Get the map data URL for a site.
111
+ * @param siteId - The identifier of the site
112
+ * @param isExternalIdentifier - When `false` (default), `siteId` is treated as
113
+ * the internal identifier. When `true`, it is treated as the external identifier.
114
+ * @returns Promise that resolves with the map URL, or `null` if unavailable
115
+ * @throws Error if the site is not found or if the operation fails
116
+ */
117
+ export async function getMapUrl(
118
+ siteId: string,
119
+ isExternalIdentifier: boolean = false
120
+ ): Promise<string | null> {
121
+ try {
122
+ const mapUrl = await PTRNativeLibrary.getMapUrl(siteId, isExternalIdentifier);
123
+ return (mapUrl as string) ?? null;
124
+ } catch (error) {
125
+ console.error('Failed to get map URL:', error);
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Get the URL for the map style JSON.
132
+ * @returns Promise that resolves with the style JSON URL, or `null` if unavailable
133
+ * @throws Error if the operation fails
134
+ */
135
+ export async function getStyleJsonUrl(): Promise<string | null> {
136
+ try {
137
+ const styleUrl = await PTRNativeLibrary.getStyleJsonUrl();
138
+ return (styleUrl as string) ?? null;
139
+ } catch (error) {
140
+ console.error('Failed to get style JSON URL:', error);
141
+ throw error;
142
+ }
143
+ }
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { PTRPosition } from './PTRPosition';
7
+ import type { PTRSite } from './PTRSite';
7
8
 
8
9
  /**
9
10
  * Position event payload
@@ -93,6 +94,78 @@ export interface PTRGeofenceEvent {
93
94
  readonly timestamp?: number;
94
95
  }
95
96
 
97
+ /**
98
+ * Type of data managed by the Pointr SDK data manager
99
+ */
100
+ export interface PTRDataType {
101
+ /** Numeric value of the data type */
102
+ readonly value: number;
103
+ /** Human-readable name of the data type (e.g. "Poi", "Maps") */
104
+ readonly name: string;
105
+ }
106
+
107
+ /**
108
+ * Emitted when the data manager starts data management for a site.
109
+ */
110
+ export interface PTRDataManagerStartEvent {
111
+ /** Site the data belongs to */
112
+ readonly site: PTRSite;
113
+ /** Whether the data is from the server (online) or a local bundle (offline) */
114
+ readonly isOnlineData: boolean;
115
+ }
116
+
117
+ /**
118
+ * Emitted when the data manager completes all processing for a site.
119
+ */
120
+ export interface PTRDataManagerCompleteAllEvent {
121
+ /** Site the data belongs to */
122
+ readonly site: PTRSite;
123
+ /** Whether all updates succeeded */
124
+ readonly isSuccessful: boolean;
125
+ /** Whether the data is from the server (online) or a local bundle (offline) */
126
+ readonly isOnlineData: boolean;
127
+ /** Error messages, if any */
128
+ readonly errors: string[];
129
+ }
130
+
131
+ /**
132
+ * Emitted when the data manager begins processing a specific data type.
133
+ */
134
+ export interface PTRDataManagerBeginProcessingEvent {
135
+ /** Site the data belongs to */
136
+ readonly site: PTRSite;
137
+ /** Type of data being processed (absent for global data) */
138
+ readonly dataType?: PTRDataType;
139
+ /** Whether the data is from the server (online) or a local bundle (offline) */
140
+ readonly isOnlineData: boolean;
141
+ }
142
+
143
+ /**
144
+ * Emitted when the data manager ends processing a specific data type.
145
+ */
146
+ export interface PTRDataManagerEndProcessingEvent {
147
+ /** Site the data belongs to */
148
+ readonly site: PTRSite;
149
+ /** Type of data that was processed (absent for global data) */
150
+ readonly dataType?: PTRDataType;
151
+ /** Whether the data is from the server (online) or a local bundle (offline) */
152
+ readonly isOnlineData: boolean;
153
+ /** Whether the update succeeded */
154
+ readonly isSuccessful: boolean;
155
+ /** Error messages, if any */
156
+ readonly errors: string[];
157
+ }
158
+
159
+ /**
160
+ * Emitted when all data needed to display a site is available.
161
+ * @remarks This does not mean the data is the latest, only that there is valid
162
+ * data to show. Both raster maps and tile maps are considered for this check.
163
+ */
164
+ export interface PTRDataManagerReadyEvent {
165
+ /** Site the data belongs to */
166
+ readonly site: PTRSite;
167
+ }
168
+
96
169
  /**
97
170
  * Map command response payload
98
171
  */