surveysparrow-ionic-plugin 2.0.2-beta.1 → 2.0.2-beta.3

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 (32) hide show
  1. package/dist/angular-ui/esm2022/spotchecks/SpotCheckComponent.mjs +87 -58
  2. package/dist/angular-ui/esm2022/spotchecks/SpotCheckEventListener.mjs +26 -0
  3. package/dist/angular-ui/esm2022/spotchecks/api.mjs +1 -1
  4. package/dist/angular-ui/esm2022/spotchecks/helpers.mjs +6 -3
  5. package/dist/angular-ui/esm2022/spotchecks/index.mjs +2 -1
  6. package/dist/angular-ui/fesm2022/angular-ui.mjs +116 -61
  7. package/dist/angular-ui/fesm2022/angular-ui.mjs.map +1 -1
  8. package/dist/angular-ui/spotchecks/SpotCheckComponent.d.ts +10 -4
  9. package/dist/angular-ui/spotchecks/SpotCheckEventListener.d.ts +16 -0
  10. package/dist/angular-ui/spotchecks/index.d.ts +1 -0
  11. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckComponent.d.ts +10 -4
  12. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckComponent.js +82 -55
  13. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckComponent.js.map +1 -1
  14. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckEventListener.d.ts +16 -0
  15. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckEventListener.js +28 -0
  16. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckEventListener.js.map +1 -0
  17. package/dist/esm/angular-ui/lib/spotchecks/api.js.map +1 -1
  18. package/dist/esm/angular-ui/lib/spotchecks/helpers.js +5 -2
  19. package/dist/esm/angular-ui/lib/spotchecks/helpers.js.map +1 -1
  20. package/dist/esm/angular-ui/lib/spotchecks/index.d.ts +1 -0
  21. package/dist/esm/angular-ui/lib/spotchecks/index.js +1 -0
  22. package/dist/esm/angular-ui/lib/spotchecks/index.js.map +1 -1
  23. package/dist/plugin.cjs.js +110 -54
  24. package/dist/plugin.cjs.js.map +1 -1
  25. package/dist/plugin.js +110 -54
  26. package/dist/plugin.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/angular-ui/lib/spotchecks/SpotCheckComponent.ts +94 -62
  29. package/src/angular-ui/lib/spotchecks/SpotCheckEventListener.ts +50 -0
  30. package/src/angular-ui/lib/spotchecks/api.ts +2 -2
  31. package/src/angular-ui/lib/spotchecks/helpers.ts +6 -4
  32. package/src/angular-ui/lib/spotchecks/index.ts +3 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "surveysparrow-ionic-plugin",
3
- "version": "2.0.2-beta.1",
3
+ "version": "2.0.2-beta.3",
4
4
  "description": "SurveySparrow SDK enables you to collect feedback from your mobile app. Embed the Classic, Chat & NPS surveys in your ionic application seamlessly with few lines of code.",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.cjs.js",
@@ -7,6 +7,8 @@ import {
7
7
  ElementRef,
8
8
  AfterViewInit,
9
9
  HostListener,
10
+ NgZone,
11
+ ChangeDetectorRef,
10
12
  } from '@angular/core';
11
13
  import { CommonModule } from '@angular/common';
12
14
  import { Subscription } from 'rxjs';
@@ -15,6 +17,7 @@ import { closeSpotCheck, closeSpotCheckAndHandleSurveyEnd, getSpotcheckComponent
15
17
  import { SpotcheckState } from './types';
16
18
  import { getSpotcheckStateService } from './helpers';
17
19
  import { SpotcheckStateService } from './SpotcheckStateService';
20
+ import { getSpotCheckEventListener } from './SpotCheckEventListener';
18
21
  import axios from 'axios';
19
22
 
20
23
  @Component({
@@ -43,7 +46,11 @@ export class WebViewComponent implements OnInit, AfterViewInit {
43
46
  safeUrl: SafeResourceUrl | null = null;
44
47
  @ViewChild('iframeRef') iframe!: ElementRef<HTMLIFrameElement>;
45
48
 
46
- constructor(private sanitizer: DomSanitizer) {}
49
+ constructor(
50
+ private sanitizer: DomSanitizer,
51
+ private ngZone: NgZone,
52
+ private cdr: ChangeDetectorRef,
53
+ ) { }
47
54
  ngOnInit() {
48
55
  if (this.url) {
49
56
  this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
@@ -71,13 +78,15 @@ export class WebViewComponent implements OnInit, AfterViewInit {
71
78
  private setupIframeLoadListener() {
72
79
  const iframe = this.iframe.nativeElement;
73
80
  iframe.addEventListener('load', () => {
74
- this.injectNativeBridgeAdapters(iframe);
75
- const stateService = getSpotcheckStateService();
76
- if (this.webviewType === 'classic') {
77
- stateService.setState({ isClassicLoading: false });
78
- } else {
79
- stateService.setState({ isChatLoading: false });
80
- }
81
+ this.ngZone.run(() => {
82
+ this.injectNativeBridgeAdapters(iframe);
83
+ const stateService = getSpotcheckStateService();
84
+ if (this.webviewType === 'classic') {
85
+ stateService.setState({ isClassicLoading: false });
86
+ } else {
87
+ stateService.setState({ isChatLoading: false });
88
+ }
89
+ });
81
90
  });
82
91
  }
83
92
 
@@ -85,17 +94,17 @@ export class WebViewComponent implements OnInit, AfterViewInit {
85
94
  if (iframe && iframe.contentWindow) {
86
95
  try {
87
96
  const iframeWindow = iframe.contentWindow as any;
88
-
97
+
89
98
  if (!iframeWindow.SsAndroidSdk) {
90
99
  iframeWindow.SsAndroidSdk = {
91
- shareData: function() {},
92
- sendPartialSubmissionData: function() {}
100
+ shareData: function () { },
101
+ sendPartialSubmissionData: function () { }
93
102
  };
94
103
  }
95
104
 
96
105
  if (!iframeWindow.Android) {
97
106
  iframeWindow.Android = {
98
- onMessageReceive: function() {}
107
+ onMessageReceive: function () { }
99
108
  };
100
109
  }
101
110
 
@@ -103,13 +112,13 @@ export class WebViewComponent implements OnInit, AfterViewInit {
103
112
  iframeWindow.webkit = {
104
113
  messageHandlers: {
105
114
  surveyResponse: {
106
- postMessage: function() {}
115
+ postMessage: function () { }
107
116
  },
108
117
  spotCheckData: {
109
- postMessage: function() {}
118
+ postMessage: function () { }
110
119
  },
111
120
  flutterSpotCheckData: {
112
- postMessage: function() {}
121
+ postMessage: function () { }
113
122
  }
114
123
  }
115
124
  };
@@ -117,56 +126,62 @@ export class WebViewComponent implements OnInit, AfterViewInit {
117
126
 
118
127
  if (!iframeWindow.flutterSpotCheckData) {
119
128
  iframeWindow.flutterSpotCheckData = {
120
- postMessage: function() {}
129
+ postMessage: function () { }
121
130
  };
122
131
  }
123
- } catch (error) {}
132
+ } catch (error) { }
124
133
  }
125
134
  }
126
135
 
127
136
  @HostListener('window:message', ['$event'])
128
137
  onMessage(event: MessageEvent) {
129
- const stateService = getSpotcheckStateService();
130
- const { data } = event;
131
- switch (data.type) {
132
- case 'slideInFrame':
133
- if (data.mounted) {
134
- stateService.setState({ isMounted: true });
135
- }
136
- break;
138
+ this.ngZone.run(() => {
139
+ const stateService = getSpotcheckStateService();
140
+ const { data } = event;
141
+ switch (data.type) {
142
+ case 'slideInFrame':
143
+ if (data.mounted) {
144
+ stateService.setState({ isMounted: true });
145
+ }
146
+ break;
147
+
148
+ case 'resizeWindow':
149
+ if (data.size) {
150
+ stateService.setState({
151
+ currentQuestionHeight: data.size.height,
152
+ });
153
+ } else if (data.isCloseButtonEnabled) {
154
+ stateService.setState({
155
+ isCloseButtonEnabled: data.isCloseButtonEnabled,
156
+ });
157
+ }
158
+ break;
137
159
 
138
- case 'resizeWindow':
139
- if (data.size) {
140
- stateService.setState({
141
- currentQuestionHeight: data.size.height,
142
- });
143
- } else if (data.isCloseButtonEnabled) {
144
- stateService.setState({
145
- isCloseButtonEnabled: data.isCloseButtonEnabled,
160
+ case 'surveyCompleted':
161
+ closeSpotCheckAndHandleSurveyEnd().then(() => {
162
+ getSpotCheckEventListener().emit('surveyCompleted', data.response);
163
+ this.cdr.detectChanges();
146
164
  });
147
- }
148
- break;
165
+ break;
149
166
 
150
- case 'surveyCompleted':
151
- closeSpotCheckAndHandleSurveyEnd();
152
- // spotchecksListener.emitSurveyCompleted(data.response);
153
- break;
167
+ case 'surveyLoadStarted':
168
+ getSpotCheckEventListener().emit('surveyLoadStarted', data.surveyDetails);
169
+ break;
154
170
 
155
- case 'surveyLoadStarted':
156
- // spotchecksListener.emitSurveyLoadStarted(data.surveyDetails);
157
- break;
158
171
 
159
- case 'classicLoadEvent':
160
- stateService.setState({ isClassicLoadEventReceived: true });
161
- break;
172
+ case 'classicLoadEvent':
173
+ stateService.setState({ isClassicLoadEventReceived: true });
174
+ break;
162
175
 
163
- case 'chatLoadEvent':
164
- stateService.setState({ isChatLoadEventReceived: true });
165
- break;
176
+ case 'chatLoadEvent':
177
+ stateService.setState({ isChatLoadEventReceived: true });
178
+ break;
166
179
 
167
- default:
168
- break;
169
- }
180
+ default:
181
+ break;
182
+ }
183
+ this.cdr.detectChanges();
184
+ });
170
185
  }
171
186
  }
172
187
 
@@ -214,24 +229,30 @@ export class CloseSVGComponent {
214
229
  export class CloseButtonComponent implements OnDestroy {
215
230
  @Input() size: number = 30;
216
231
  @Input() strokeWidth: number = 1.2;
217
-
232
+
218
233
  state: SpotcheckState;
219
234
  private stateService: SpotcheckStateService;
220
235
  private stateSubscription!: Subscription;
221
-
236
+
222
237
  isVisible: boolean = false;
223
238
  isMiniCard: boolean = false;
224
239
  stroke: string = 'black';
225
-
226
- constructor() {
240
+
241
+ constructor(
242
+ private ngZone: NgZone,
243
+ private cdr: ChangeDetectorRef,
244
+ ) {
227
245
  this.stateService = getSpotcheckStateService();
228
246
  this.state = this.stateService.getState();
229
247
  this.updateComponentState();
230
248
 
231
249
  this.stateSubscription = this.stateService.state$.subscribe(
232
250
  (newState: SpotcheckState) => {
233
- this.state = newState;
234
- this.updateComponentState();
251
+ this.ngZone.run(() => {
252
+ this.state = newState;
253
+ this.updateComponentState();
254
+ this.cdr.detectChanges();
255
+ });
235
256
  }
236
257
  );
237
258
  }
@@ -258,6 +279,9 @@ export class CloseButtonComponent implements OnDestroy {
258
279
  onClick = async () => {
259
280
  await closeSpotCheck();
260
281
  handleSurveyEnd();
282
+ this.ngZone.run(() => {
283
+ this.cdr.detectChanges();
284
+ });
261
285
  };
262
286
  }
263
287
 
@@ -276,16 +300,22 @@ export class SpotCheckComponent implements OnInit, OnDestroy {
276
300
  componentStyles: any = {};
277
301
  avatarUrl: string = '';
278
302
 
279
- constructor() {
303
+ constructor(
304
+ private ngZone: NgZone,
305
+ private cdr: ChangeDetectorRef,
306
+ ) {
280
307
  this.spotcheckStateService = getSpotcheckStateService();
281
308
  this.state = this.spotcheckStateService.getState();
282
309
  this.updateComponentStyles();
283
310
 
284
311
  this.stateSubscription = this.spotcheckStateService.state$.subscribe(
285
312
  (newState: SpotcheckState) => {
286
- this.state = newState;
287
- this.updateComponentStyles();
288
- this.avatarUrl = this.state.avatarUrl || "https://static.surveysparrow.com/application/images/profile.png";
313
+ this.ngZone.run(() => {
314
+ this.state = newState;
315
+ this.updateComponentStyles();
316
+ this.avatarUrl = this.state.avatarUrl || "https://static.surveysparrow.com/application/images/profile.png";
317
+ this.cdr.detectChanges();
318
+ });
289
319
  }
290
320
  );
291
321
  }
@@ -308,9 +338,11 @@ export class SpotCheckComponent implements OnInit, OnDestroy {
308
338
  try {
309
339
  const domainName = this.state.domainName;
310
340
  const targetToken = this.state.targetToken;
311
- const response = await axios.get(
341
+
342
+ const response = await axios.get<any>(
312
343
  `https://${domainName}/api/internal/spotcheck/widget/${targetToken}/init`
313
344
  );
345
+
314
346
  const data = response.data;
315
347
 
316
348
  if (data.filteredSpotChecks && data.filteredSpotChecks.length > 0) {
@@ -0,0 +1,50 @@
1
+ import { Subject } from 'rxjs';
2
+ import type { Subscription } from 'rxjs';
3
+
4
+ export type SpotCheckEventType =
5
+ | 'surveyCompleted'
6
+ | 'surveyDismissed'
7
+ | 'surveyLoadStarted';
8
+
9
+ export interface SpotCheckEvent {
10
+ type: SpotCheckEventType;
11
+ data?: any;
12
+ }
13
+
14
+ type EventCallback = (data?: any) => void;
15
+
16
+ class SpotCheckEventListenerService {
17
+ private eventSubject = new Subject<SpotCheckEvent>();
18
+ private event$ = this.eventSubject.asObservable();
19
+
20
+ emit(type: SpotCheckEventType, data?: any): void {
21
+ this.eventSubject.next({ type, data });
22
+ }
23
+
24
+ addListener(
25
+ eventType: SpotCheckEventType,
26
+ callback: EventCallback
27
+ ): Subscription {
28
+ return this.event$.subscribe((event: SpotCheckEvent) => {
29
+ if (event.type === eventType) {
30
+ callback(event.data);
31
+ }
32
+ });
33
+ }
34
+ }
35
+
36
+ let globalInstance: SpotCheckEventListenerService;
37
+
38
+ export const getSpotCheckEventListener = (): SpotCheckEventListenerService => {
39
+ if (!globalInstance) {
40
+ globalInstance = new SpotCheckEventListenerService();
41
+ }
42
+ return globalInstance;
43
+ };
44
+
45
+ export const addSpotCheckListener = (
46
+ eventType: SpotCheckEventType,
47
+ callback: EventCallback
48
+ ): Subscription => {
49
+ return getSpotCheckEventListener().addListener(eventType, callback);
50
+ };
@@ -65,7 +65,7 @@ export const sendTrackScreenRequest = async ({
65
65
  };
66
66
 
67
67
  const url = `https://${state.domainName}/api/internal/spotcheck/widget/${state.targetToken}/properties?isSpotCheck=true&sdk=IONIC`;
68
- const response = await axios.post(url, payload, {
68
+ const response = await axios.post<any>(url, payload, {
69
69
  headers: {
70
70
  'Content-Type': 'application/json',
71
71
  },
@@ -212,7 +212,7 @@ export const sendTrackEventRequest = async ({ screen, event }: TrackEventProps)
212
212
  const url = `https://${state.domainName}/api/internal/spotcheck/widget/${state.targetToken}/eventTrigger?isSpotCheck=true`;
213
213
 
214
214
  try {
215
- const response = await axios.post(url, payload, {
215
+ const response = await axios.post<any>(url, payload, {
216
216
  headers: {
217
217
  'Content-Type': 'application/json',
218
218
  },
@@ -3,6 +3,7 @@ import { Device } from '@capacitor/device';
3
3
  import { SpotcheckState } from './types';
4
4
  import axios from 'axios';
5
5
  import { SpotcheckStateService } from './SpotcheckStateService';
6
+ import { getSpotCheckEventListener } from './SpotCheckEventListener';
6
7
 
7
8
  let globalSpotcheckStateService: SpotcheckStateService;
8
9
  let globalOS: string | null = null;
@@ -122,7 +123,7 @@ export const setAppearance = async (
122
123
  spotcheckStateService.setState(updatedState);
123
124
 
124
125
  try {
125
- const response = await axios.get(fullSpotcheckURL);
126
+ const response = await axios.get<any>(fullSpotcheckURL);
126
127
  const themeInfo = response.data?.config?.generatedCSS;
127
128
  const theme_payload = { type: 'THEME_UPDATE_SPOTCHECK', themeInfo };
128
129
  state = spotcheckStateService.getState();
@@ -261,8 +262,10 @@ export const closeSpotCheck = async () => {
261
262
  body: JSON.stringify(payload),
262
263
  }
263
264
  );
264
-
265
- if (response.status != 200) {
265
+ if(response.status == 200) {
266
+ getSpotCheckEventListener().emit('surveyDismissed');
267
+ }
268
+ else{
266
269
  console.log(`Error: ${response.status}`);
267
270
  }
268
271
  } catch (error) {
@@ -407,6 +410,5 @@ export const getSpotcheckComponentCssStyles = (state: SpotcheckState) => {
407
410
  };
408
411
 
409
412
  export const closeSpotCheckAndHandleSurveyEnd = async () => {
410
- await closeSpotCheck();
411
413
  handleSurveyEnd();
412
414
  };
@@ -1,4 +1,7 @@
1
1
  export { initializeSpotChecks, trackScreen, trackEvent } from './SpotCheck';
2
+ export {
3
+ addSpotCheckListener,
4
+ } from './SpotCheckEventListener';
2
5
  export type {
3
6
  UserDetails,
4
7
  Variables,