@convep_mobilogy/react-native-qms-plugin 1.8.3 → 1.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.
Files changed (62) hide show
  1. package/QmsPlugin.podspec +2 -4
  2. package/QmsPluginFramework.podspec +12 -0
  3. package/README.md +183 -4
  4. package/android/build.gradle +12 -2
  5. package/android/consumer-rules.pro +13 -0
  6. package/ios/QmsPlugin/QmsDashboardViewManager.mm +82 -29
  7. package/ios/QmsPlugin/QmsModule.mm +1296 -1
  8. package/ios/QmsPlugin/UIViewController+QmsAnalytics.m +3 -1
  9. package/lib/module/QmsDashboardView.android.js +121 -9
  10. package/lib/module/QmsDashboardView.android.js.map +1 -1
  11. package/lib/module/QmsPlugin.js +57 -0
  12. package/lib/module/QmsPlugin.js.map +1 -1
  13. package/lib/typescript/src/QmsDashboardView.android.d.ts.map +1 -1
  14. package/lib/typescript/src/QmsPlugin.d.ts +137 -0
  15. package/lib/typescript/src/QmsPlugin.d.ts.map +1 -1
  16. package/lib/typescript/src/index.d.ts +1 -1
  17. package/lib/typescript/src/index.d.ts.map +1 -1
  18. package/package.json +7 -4
  19. package/src/QmsDashboardView.android.tsx +156 -11
  20. package/src/QmsPlugin.ts +312 -0
  21. package/src/index.tsx +13 -1
  22. package/ios/QmsPluginFramework.xcframework/Info.plist +0 -44
  23. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Assets.car +0 -0
  24. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Headers/QmsPlugin.h +0 -43
  25. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Headers/QmsPluginFramework.h +0 -17
  26. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Info.plist +0 -0
  27. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Modules/module.modulemap +0 -6
  28. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Bold.ttf +0 -0
  29. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-BoldItalic.ttf +0 -0
  30. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-ExtraBold.ttf +0 -0
  31. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-ExtraLight.ttf +0 -0
  32. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Italic.ttf +0 -0
  33. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Light.ttf +0 -0
  34. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Medium.ttf +0 -0
  35. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Regular.ttf +0 -0
  36. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-SemiBold.ttf +0 -0
  37. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/Montserrat-Thin.ttf +0 -0
  38. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework +0 -0
  39. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/_CodeSignature/CodeResources +0 -289
  40. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/bm.json +0 -781
  41. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/cn.json +0 -782
  42. package/ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/en.json +0 -782
  43. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Assets.car +0 -0
  44. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Headers/QmsPlugin.h +0 -43
  45. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Headers/QmsPluginFramework.h +0 -17
  46. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Info.plist +0 -0
  47. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Modules/module.modulemap +0 -6
  48. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Bold.ttf +0 -0
  49. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-BoldItalic.ttf +0 -0
  50. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-ExtraBold.ttf +0 -0
  51. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-ExtraLight.ttf +0 -0
  52. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Italic.ttf +0 -0
  53. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Light.ttf +0 -0
  54. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Medium.ttf +0 -0
  55. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Regular.ttf +0 -0
  56. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-SemiBold.ttf +0 -0
  57. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/Montserrat-Thin.ttf +0 -0
  58. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/QmsPluginFramework +0 -0
  59. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/_CodeSignature/CodeResources +0 -289
  60. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/bm.json +0 -781
  61. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/cn.json +0 -782
  62. package/ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/en.json +0 -782
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import { DeviceEventEmitter, NativeModules, View } from 'react-native';
3
3
  import type {
4
4
  QmsActiveAccountPayload,
@@ -27,9 +27,91 @@ const { QmsModule } = NativeModules as {
27
27
  setAccentColor?: (hexColor?: string) => void;
28
28
  setFontFamily?: (fontFamily?: string) => void;
29
29
  setPushToken?: (pushToken?: string) => void;
30
+ consumePendingLogout?: () => Promise<boolean>;
30
31
  };
31
32
  };
32
33
 
34
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
35
+ value != null && typeof value === 'object' && !Array.isArray(value);
36
+
37
+ const parseRecord = (value: unknown): Record<string, unknown> | null => {
38
+ if (isRecord(value)) {
39
+ return value;
40
+ }
41
+ if (typeof value !== 'string') {
42
+ return null;
43
+ }
44
+ const trimmed = value.trim();
45
+ if (!trimmed.startsWith('{')) {
46
+ return null;
47
+ }
48
+ try {
49
+ const parsed = JSON.parse(trimmed);
50
+ return isRecord(parsed) ? parsed : null;
51
+ } catch {
52
+ return null;
53
+ }
54
+ };
55
+
56
+ const mergeRecord = (
57
+ target: Record<string, unknown>,
58
+ source: Record<string, unknown> | null
59
+ ) => {
60
+ if (!source) {
61
+ return;
62
+ }
63
+ Object.entries(source).forEach(([key, value]) => {
64
+ if (value != null && target[key] == null) {
65
+ target[key] = value;
66
+ }
67
+ });
68
+ };
69
+
70
+ const normalizeNotificationPayload = (
71
+ rawPayload?: Record<string, unknown> | null
72
+ ): Record<string, unknown> | null => {
73
+ if (!rawPayload || Object.keys(rawPayload).length === 0) {
74
+ return rawPayload ?? null;
75
+ }
76
+
77
+ const normalized: Record<string, unknown> = { ...rawPayload };
78
+ const nestedKeys = [
79
+ 'Data',
80
+ 'data',
81
+ 'payload',
82
+ 'notificationData',
83
+ 'remoteMessage',
84
+ 'message',
85
+ ];
86
+
87
+ nestedKeys.forEach((key) => {
88
+ const nested = parseRecord(rawPayload[key]);
89
+ mergeRecord(normalized, nested);
90
+ mergeRecord(normalized, parseRecord(nested?.Data));
91
+ mergeRecord(normalized, parseRecord(nested?.data));
92
+ mergeRecord(normalized, parseRecord(nested?.payload));
93
+ mergeRecord(normalized, parseRecord(nested?.notificationData));
94
+ });
95
+
96
+ const notification = parseRecord(rawPayload.notification);
97
+ if (notification) {
98
+ if (normalized.title == null && notification.title != null) {
99
+ normalized.title = notification.title;
100
+ }
101
+ if (normalized.body == null && notification.body != null) {
102
+ normalized.body = notification.body;
103
+ }
104
+ if (normalized.message == null && notification.body != null) {
105
+ normalized.message = notification.body;
106
+ }
107
+ }
108
+ if (normalized.message == null && normalized.body != null) {
109
+ normalized.message = normalized.body;
110
+ }
111
+
112
+ return normalized;
113
+ };
114
+
33
115
  export const QmsDashboardView: React.FC<QmsDashboardViewProps> = ({
34
116
  style,
35
117
  onClose,
@@ -58,12 +140,82 @@ export const QmsDashboardView: React.FC<QmsDashboardViewProps> = ({
58
140
  owner_version,
59
141
  payload,
60
142
  }) => {
143
+ const onLogoutRef = useRef(onLogout);
144
+ const logoutDeliveredRef = useRef(false);
145
+ const [logoutGate, setLogoutGate] = useState<
146
+ 'checking' | 'clear' | 'blocked'
147
+ >('checking');
148
+
149
+ useEffect(() => {
150
+ onLogoutRef.current = onLogout;
151
+ }, [onLogout]);
152
+
61
153
  useEffect(() => {
154
+ let mounted = true;
155
+
156
+ const deliverLogout = () => {
157
+ if (logoutDeliveredRef.current) return;
158
+ logoutDeliveredRef.current = true;
159
+ if (mounted) {
160
+ setLogoutGate('blocked');
161
+ }
162
+ onLogoutRef.current?.();
163
+ };
164
+
165
+ const consumePendingLogout = QmsModule?.consumePendingLogout;
166
+ const subscription = DeviceEventEmitter.addListener(
167
+ 'QmsSdkOnLogout',
168
+ () => {
169
+ if (mounted) {
170
+ setLogoutGate('blocked');
171
+ }
172
+ if (consumePendingLogout) {
173
+ consumePendingLogout().catch(() => false).finally(deliverLogout);
174
+ } else {
175
+ deliverLogout();
176
+ }
177
+ }
178
+ );
179
+
180
+ // A final-account logout may recreate the React host, making the event sent
181
+ // to the previous ReactContext impossible to receive. Consume the persisted
182
+ // handoff only after this component and its callback are ready.
183
+ if (consumePendingLogout) {
184
+ consumePendingLogout()
185
+ .then((wasPending) => {
186
+ if (wasPending) {
187
+ deliverLogout();
188
+ } else if (mounted) {
189
+ setLogoutGate('clear');
190
+ }
191
+ })
192
+ .catch(() => {
193
+ if (mounted) {
194
+ setLogoutGate('clear');
195
+ }
196
+ });
197
+ } else {
198
+ setLogoutGate('clear');
199
+ }
200
+
201
+ return () => {
202
+ mounted = false;
203
+ subscription.remove();
204
+ };
205
+ }, []);
206
+
207
+ useEffect(() => {
208
+ if (logoutGate !== 'clear') {
209
+ return;
210
+ }
211
+
62
212
  const resolvedClientID = clientID ?? ClientID ?? '';
63
213
  const resolvedClientCode = clientCode ?? ClientCode ?? '';
64
214
  const resolvedToken = user_token ?? token ?? userToken ?? '';
65
215
  const resolvedOwnerVersion = ownerVersion ?? owner_version ?? '';
66
- const hasPayload = payload != null && Object.keys(payload).length > 0;
216
+ const normalizedPayload = normalizeNotificationPayload(payload);
217
+ const hasPayload =
218
+ normalizedPayload != null && Object.keys(normalizedPayload).length > 0;
67
219
 
68
220
  if (autoShow && QmsModule?.showQms) {
69
221
  if (QmsModule?.setOwnerVersion) {
@@ -93,7 +245,7 @@ export const QmsDashboardView: React.FC<QmsDashboardViewProps> = ({
93
245
  resolvedClientID,
94
246
  resolvedClientCode,
95
247
  isOrigin,
96
- payload
248
+ normalizedPayload
97
249
  );
98
250
  } else {
99
251
  QmsModule.showQms(
@@ -123,6 +275,7 @@ export const QmsDashboardView: React.FC<QmsDashboardViewProps> = ({
123
275
  ownerVersion,
124
276
  owner_version,
125
277
  payload,
278
+ logoutGate,
126
279
  ]);
127
280
 
128
281
  useEffect(() => {
@@ -165,14 +318,6 @@ export const QmsDashboardView: React.FC<QmsDashboardViewProps> = ({
165
318
  return () => subscription.remove();
166
319
  }, [onClose]);
167
320
 
168
- useEffect(() => {
169
- if (!onLogout) return;
170
- const subscription = DeviceEventEmitter.addListener('QmsSdkOnLogout', () =>
171
- onLogout()
172
- );
173
- return () => subscription.remove();
174
- }, [onLogout]);
175
-
176
321
  useEffect(() => {
177
322
  if (!onActiveAccountChange) return;
178
323
  const subscription = DeviceEventEmitter.addListener(
package/src/QmsPlugin.ts CHANGED
@@ -6,8 +6,184 @@ export type InAppNotificationPayload = {
6
6
  data?: Record<string, unknown>;
7
7
  };
8
8
 
9
+ type DirectLaunchPayload = {
10
+ userToken?: string;
11
+ token?: string;
12
+ user_token?: string;
13
+ userId?: string | number;
14
+ USER_ID?: string | number;
15
+ user_id?: string | number;
16
+ createdBy?: string | number;
17
+ created_by?: string | number;
18
+ created_by_id?: string | number;
19
+ userName?: string;
20
+ USER_NAME?: string;
21
+ user_name?: string;
22
+ createdByName?: string;
23
+ created_by_name?: string;
24
+ userEmail?: string;
25
+ USER_EMAIL?: string;
26
+ user_email?: string;
27
+ email?: string;
28
+ userAvatar?: string;
29
+ USER_AVATAR?: string;
30
+ user_avatar?: string;
31
+ avatar?: string;
32
+ profilePicture?: string;
33
+ profile_picture?: string;
34
+ icPassport?: string;
35
+ IC_PASSPORT?: string;
36
+ ic_passport?: string;
37
+ clientID?: string;
38
+ ClientID?: string;
39
+ clientCode?: string;
40
+ ClientCode?: string;
41
+ isOrigin?: boolean;
42
+ themePrimaryColor?: string;
43
+ primaryColor?: string;
44
+ THEME_PRIMARY_COLOR?: string;
45
+ PRIMARY_COLOR?: string;
46
+ themeHeaderBackgroundColor?: string;
47
+ headerBackgroundColor?: string;
48
+ themeHeaderColor?: string;
49
+ headerColor?: string;
50
+ THEME_HEADER_BACKGROUND_COLOR?: string;
51
+ HEADER_BACKGROUND_COLOR?: string;
52
+ THEME_HEADER_COLOR?: string;
53
+ HEADER_COLOR?: string;
54
+ themeHeaderTextColor?: string;
55
+ headerTextColor?: string;
56
+ THEME_HEADER_TEXT_COLOR?: string;
57
+ HEADER_TEXT_COLOR?: string;
58
+ themeHeaderIconColor?: string;
59
+ headerIconColor?: string;
60
+ THEME_HEADER_ICON_COLOR?: string;
61
+ HEADER_ICON_COLOR?: string;
62
+ themeAccentColor?: string;
63
+ accentColor?: string;
64
+ THEME_ACCENT_COLOR?: string;
65
+ ACCENT_COLOR?: string;
66
+ };
67
+
68
+ type SelectedUnitPayload = {
69
+ drawingPlanId?: string | number;
70
+ DRAWING_PLAN_ID?: string | number;
71
+ drawing_plan_id?: string | number;
72
+ plan_id?: string | number;
73
+ unitId?: string | number;
74
+ unit_id?: string | number;
75
+ unitName?: string;
76
+ UNIT_NAME?: string;
77
+ unit_name?: string;
78
+ projectId?: string | number;
79
+ PROJECT_ID?: string | number;
80
+ project_id?: string | number;
81
+ projectName?: string;
82
+ PROJECT_NAME?: string;
83
+ project_name?: string;
84
+ };
85
+
86
+ export type OpenAddIssuePayload = DirectLaunchPayload &
87
+ SelectedUnitPayload & {
88
+ issueLimitStatus?: string;
89
+ ISSUE_LIMIT_STATUS?: string;
90
+ issueLimitWarningText?: string;
91
+ ISSUE_LIMIT_WARNING_TEXT?: string;
92
+ issueLimitErrorText?: string;
93
+ ISSUE_LIMIT_ERROR_TEXT?: string;
94
+ };
95
+
96
+ export type OpenThirdPartyLinkPayload = DirectLaunchPayload &
97
+ SelectedUnitPayload & {
98
+ lotId?: string | number;
99
+ LOT_ID?: string | number;
100
+ lot_id?: string | number;
101
+ unitLotId?: string | number;
102
+ unit_lot_id?: string | number;
103
+ userId?: string | number;
104
+ USER_ID?: string | number;
105
+ user_id?: string | number;
106
+ createdBy?: string | number;
107
+ created_by?: string | number;
108
+ };
109
+
110
+ export type OpenPropertyInfoPayload = DirectLaunchPayload & SelectedUnitPayload;
111
+ export type OpenAccessItemPayload = DirectLaunchPayload & SelectedUnitPayload;
112
+ export type OpenProjectUpdatePayload = DirectLaunchPayload &
113
+ SelectedUnitPayload;
114
+ export type OpenInboxPayload = DirectLaunchPayload & SelectedUnitPayload;
115
+ export type OpenIssueListPayload = DirectLaunchPayload & SelectedUnitPayload;
116
+ export type OpenDraftIssuesPayload = DirectLaunchPayload & SelectedUnitPayload;
117
+ export type GetDraftIssueCountPayload = DirectLaunchPayload &
118
+ SelectedUnitPayload;
119
+ export type OpenPoaSignOffPayload = DirectLaunchPayload & SelectedUnitPayload;
120
+ export type OpenMakeAppointmentPayload = DirectLaunchPayload &
121
+ SelectedUnitPayload & {
122
+ preferredAppointmentType?: string;
123
+ PREFERRED_APPOINTMENT_TYPE?: string;
124
+ preferred_appointment_type?: string;
125
+ };
126
+ export type OpenAppointmentListPayload = DirectLaunchPayload &
127
+ SelectedUnitPayload & {
128
+ handoverStatus?: string;
129
+ handover_status?: string;
130
+ readyToHandover?: string | boolean | number;
131
+ ready_to_handover?: string | boolean | number;
132
+ clearanceLetter?: string | boolean | number;
133
+ clearance_letter?: string | boolean | number;
134
+ clearanceLetterIssuanceMessage?: string;
135
+ clearance_letter_issuance_message?: string;
136
+ ownerHandover?: string | boolean | number;
137
+ owner_handover?: string | boolean | number;
138
+ ownerAppointmentAlert?: string;
139
+ owner_appointment_alert?: string;
140
+ ownerJointInspection?: string | boolean | number;
141
+ owner_joint_inspection?: string | boolean | number;
142
+ };
143
+
144
+ type DirectNativeMethod = (
145
+ userToken?: string,
146
+ clientID?: string,
147
+ clientCode?: string,
148
+ isOrigin?: boolean,
149
+ options?: Record<string, unknown> | null
150
+ ) => Promise<boolean>;
151
+
152
+ type DirectNativeCountMethod = (
153
+ userToken?: string,
154
+ clientID?: string,
155
+ clientCode?: string,
156
+ isOrigin?: boolean,
157
+ options?: Record<string, unknown> | null
158
+ ) => Promise<number>;
159
+
160
+ type DirectMethodName =
161
+ | 'openAddIssue'
162
+ | 'openThirdPartyLink'
163
+ | 'openPropertyInfo'
164
+ | 'openAccessItem'
165
+ | 'openProjectUpdate'
166
+ | 'openInbox'
167
+ | 'openIssueList'
168
+ | 'openDraftIssues'
169
+ | 'openPoaSignOff'
170
+ | 'openMakeAppointment'
171
+ | 'openAppointmentList';
172
+
9
173
  const { QmsModule } = NativeModules as {
10
174
  QmsModule?: {
175
+ openAddIssue?: DirectNativeMethod;
176
+ openThirdPartyLink?: DirectNativeMethod;
177
+ openPropertyInfo?: DirectNativeMethod;
178
+ openAccessItem?: DirectNativeMethod;
179
+ openProjectUpdate?: DirectNativeMethod;
180
+ openInbox?: DirectNativeMethod;
181
+ openIssueList?: DirectNativeMethod;
182
+ openDraftIssues?: DirectNativeMethod;
183
+ getDraftIssueCount?: DirectNativeCountMethod;
184
+ openPoaSignOff?: DirectNativeMethod;
185
+ openMakeAppointment?: DirectNativeMethod;
186
+ openAppointmentList?: DirectNativeMethod;
11
187
  emitInAppNotification?: (title?: string, body?: string) => void;
12
188
  emitInAppNotificationWithPayload?: (
13
189
  title?: string,
@@ -17,7 +193,142 @@ const { QmsModule } = NativeModules as {
17
193
  };
18
194
  };
19
195
 
196
+ function resolveCredentials(payload: DirectLaunchPayload) {
197
+ return {
198
+ token: payload.userToken ?? payload.token ?? payload.user_token ?? '',
199
+ clientID: payload.clientID ?? payload.ClientID ?? '',
200
+ clientCode: payload.clientCode ?? payload.ClientCode ?? '',
201
+ isOrigin: payload.isOrigin ?? false,
202
+ };
203
+ }
204
+
205
+ function callDirectMethod<T extends DirectLaunchPayload>(
206
+ methodName: DirectMethodName,
207
+ unavailableMessage: string,
208
+ payload: T
209
+ ): Promise<boolean> {
210
+ const method = QmsModule?.[methodName];
211
+ if (!method) {
212
+ return Promise.reject(new Error(unavailableMessage));
213
+ }
214
+
215
+ const credentials = resolveCredentials(payload);
216
+ return method(
217
+ credentials.token,
218
+ credentials.clientID,
219
+ credentials.clientCode,
220
+ credentials.isOrigin,
221
+ payload as Record<string, unknown>
222
+ );
223
+ }
224
+
20
225
  export const QmsPlugin = {
226
+ openAddIssue(payload: OpenAddIssuePayload): Promise<boolean> {
227
+ return callDirectMethod(
228
+ 'openAddIssue',
229
+ 'QMS openAddIssue is not available.',
230
+ payload
231
+ );
232
+ },
233
+
234
+ openThirdPartyLink(payload: OpenThirdPartyLinkPayload): Promise<boolean> {
235
+ return callDirectMethod(
236
+ 'openThirdPartyLink',
237
+ 'QMS openThirdPartyLink is not available.',
238
+ payload
239
+ );
240
+ },
241
+
242
+ openPropertyInfo(payload: OpenPropertyInfoPayload): Promise<boolean> {
243
+ return callDirectMethod(
244
+ 'openPropertyInfo',
245
+ 'QMS openPropertyInfo is not available.',
246
+ payload
247
+ );
248
+ },
249
+
250
+ openAccessItem(payload: OpenAccessItemPayload): Promise<boolean> {
251
+ return callDirectMethod(
252
+ 'openAccessItem',
253
+ 'QMS openAccessItem is not available.',
254
+ payload
255
+ );
256
+ },
257
+
258
+ openProjectUpdate(payload: OpenProjectUpdatePayload): Promise<boolean> {
259
+ return callDirectMethod(
260
+ 'openProjectUpdate',
261
+ 'QMS openProjectUpdate is not available.',
262
+ payload
263
+ );
264
+ },
265
+
266
+ openInbox(payload: OpenInboxPayload): Promise<boolean> {
267
+ return callDirectMethod(
268
+ 'openInbox',
269
+ 'QMS openInbox is not available.',
270
+ payload
271
+ );
272
+ },
273
+
274
+ openIssueList(payload: OpenIssueListPayload): Promise<boolean> {
275
+ return callDirectMethod(
276
+ 'openIssueList',
277
+ 'QMS openIssueList is not available.',
278
+ payload
279
+ );
280
+ },
281
+
282
+ openDraftIssues(payload: OpenDraftIssuesPayload): Promise<boolean> {
283
+ return callDirectMethod(
284
+ 'openDraftIssues',
285
+ 'QMS openDraftIssues is not available.',
286
+ payload
287
+ );
288
+ },
289
+
290
+ getDraftIssueCount(payload: GetDraftIssueCountPayload): Promise<number> {
291
+ const method = QmsModule?.getDraftIssueCount;
292
+ if (!method) {
293
+ return Promise.reject(
294
+ new Error('QMS getDraftIssueCount is not available.')
295
+ );
296
+ }
297
+
298
+ const credentials = resolveCredentials(payload);
299
+ return method(
300
+ credentials.token,
301
+ credentials.clientID,
302
+ credentials.clientCode,
303
+ credentials.isOrigin,
304
+ payload as Record<string, unknown>
305
+ ).then((count: number) => Number(count) || 0);
306
+ },
307
+
308
+ openPoaSignOff(payload: OpenPoaSignOffPayload): Promise<boolean> {
309
+ return callDirectMethod(
310
+ 'openPoaSignOff',
311
+ 'QMS openPoaSignOff is not available.',
312
+ payload
313
+ );
314
+ },
315
+
316
+ openMakeAppointment(payload: OpenMakeAppointmentPayload): Promise<boolean> {
317
+ return callDirectMethod(
318
+ 'openMakeAppointment',
319
+ 'QMS openMakeAppointment is not available.',
320
+ payload
321
+ );
322
+ },
323
+
324
+ openAppointmentList(payload: OpenAppointmentListPayload): Promise<boolean> {
325
+ return callDirectMethod(
326
+ 'openAppointmentList',
327
+ 'QMS openAppointmentList is not available.',
328
+ payload
329
+ );
330
+ },
331
+
21
332
  emitInAppNotification(payload: InAppNotificationPayload): void {
22
333
  if (QmsModule?.emitInAppNotificationWithPayload) {
23
334
  QmsModule.emitInAppNotificationWithPayload(
@@ -27,6 +338,7 @@ export const QmsPlugin = {
27
338
  );
28
339
  return;
29
340
  }
341
+
30
342
  QmsModule?.emitInAppNotification?.(
31
343
  payload.title ?? 'Notification',
32
344
  payload.body ?? ''
package/src/index.tsx CHANGED
@@ -4,4 +4,16 @@ export type {
4
4
  QmsDashboardViewProps,
5
5
  } from './QmsDashboardView.types';
6
6
  export { QmsPlugin } from './QmsPlugin';
7
- export type { InAppNotificationPayload } from './QmsPlugin';
7
+ export type {
8
+ InAppNotificationPayload,
9
+ OpenAccessItemPayload,
10
+ OpenAddIssuePayload,
11
+ OpenAppointmentListPayload,
12
+ OpenInboxPayload,
13
+ OpenIssueListPayload,
14
+ OpenMakeAppointmentPayload,
15
+ OpenPoaSignOffPayload,
16
+ OpenProjectUpdatePayload,
17
+ OpenPropertyInfoPayload,
18
+ OpenThirdPartyLinkPayload,
19
+ } from './QmsPlugin';
@@ -1,44 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>AvailableLibraries</key>
6
- <array>
7
- <dict>
8
- <key>BinaryPath</key>
9
- <string>QmsPluginFramework.framework/QmsPluginFramework</string>
10
- <key>LibraryIdentifier</key>
11
- <string>ios-arm64</string>
12
- <key>LibraryPath</key>
13
- <string>QmsPluginFramework.framework</string>
14
- <key>SupportedArchitectures</key>
15
- <array>
16
- <string>arm64</string>
17
- </array>
18
- <key>SupportedPlatform</key>
19
- <string>ios</string>
20
- </dict>
21
- <dict>
22
- <key>BinaryPath</key>
23
- <string>QmsPluginFramework.framework/QmsPluginFramework</string>
24
- <key>LibraryIdentifier</key>
25
- <string>ios-arm64_x86_64-simulator</string>
26
- <key>LibraryPath</key>
27
- <string>QmsPluginFramework.framework</string>
28
- <key>SupportedArchitectures</key>
29
- <array>
30
- <string>arm64</string>
31
- <string>x86_64</string>
32
- </array>
33
- <key>SupportedPlatform</key>
34
- <string>ios</string>
35
- <key>SupportedPlatformVariant</key>
36
- <string>simulator</string>
37
- </dict>
38
- </array>
39
- <key>CFBundlePackageType</key>
40
- <string>XFWK</string>
41
- <key>XCFrameworkFormatVersion</key>
42
- <string>1.0</string>
43
- </dict>
44
- </plist>
@@ -1,43 +0,0 @@
1
- //QmsPlugin.h
2
- #import <Foundation/Foundation.h>
3
- #import <UIKit/UIKit.h>
4
-
5
- NS_ASSUME_NONNULL_BEGIN
6
-
7
- @interface QmsPluginUI : NSObject
8
-
9
- + (UIViewController *)makeViewController;
10
-
11
- /// Fetches project list data and presents DashboardViewController fully configured
12
- /// for the given FCM deep-link payload. The payload must contain at minimum
13
- /// `project_id` and `plan_id`. Auth/base-URL must already be configured in APIConfig
14
- /// (i.e. the SDK has already been initialised by the user opening the app).
15
- ///
16
- /// @param payload The FCM notification data dictionary.
17
- /// @param presenter The view controller from which the dashboard will be presented modally.
18
- + (void)presentDashboardFromPayload:(NSDictionary *)payload
19
- fromViewController:(UIViewController *)presenter;
20
-
21
- /// Configures APIConfig with the project/plan context from the payload, then
22
- /// presents AppointmentDetailsViewController modally. The payload must contain
23
- /// `project_id`, `plan_id`, and `appointment_id` (or `id` as a fallback).
24
- /// Auth/base-URL must already be configured in APIConfig.
25
- ///
26
- /// @param payload The FCM notification data dictionary.
27
- /// @param presenter The view controller from which the appointment screen will be presented.
28
- + (void)presentAppointmentFromPayload:(NSDictionary *)payload
29
- fromViewController:(UIViewController *)presenter;
30
-
31
- /// Fetches the issue list, finds the matching issue by `issue_id` from the payload,
32
- /// and presents IssueDetailViewController fully configured. The payload must contain
33
- /// at minimum `project_id`, `plan_id`, and `issue_id`. Auth/base-URL must already
34
- /// be configured in APIConfig.
35
- ///
36
- /// @param payload The FCM notification data dictionary.
37
- /// @param presenter The view controller from which the issue screen will be presented.
38
- + (void)presentIssueFromPayload:(NSDictionary *)payload
39
- fromViewController:(UIViewController *)presenter;
40
-
41
- @end
42
-
43
- NS_ASSUME_NONNULL_END
@@ -1,17 +0,0 @@
1
- //
2
- // QmsPluginFramework.h
3
- // QmsPluginFramework
4
- //
5
-
6
- #import <Foundation/Foundation.h>
7
- #import <UIKit/UIKit.h>
8
-
9
- //! Project version number for QmsPluginFramework.
10
- FOUNDATION_EXPORT double QmsPluginFrameworkVersionNumber;
11
-
12
- //! Project version string for QmsPluginFramework.
13
- FOUNDATION_EXPORT const unsigned char QmsPluginFrameworkVersionString[];
14
-
15
- // Public headers
16
- #import <QmsPluginFramework/QmsPlugin.h>
17
-
@@ -1,6 +0,0 @@
1
- framework module QmsPluginFramework {
2
- umbrella header "QmsPluginFramework.h"
3
- export *
4
-
5
- module * { export * }
6
- }