@chat21/chat21-web-widget 5.0.59-rc.2 → 5.0.59-rc.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # chat21-web-widget ver 5.0
2
2
 
3
+ ### 5.0.59-rc.4
4
+ - bug-fixed: texarea remains disabled if messages array has the last (non ordered) timestamp message set with 'disabledTextArea' set to true
5
+
6
+ ### 5.0.59-rc.3
7
+ - bug-fixed: if mobileMarginX or MobileMarginY is set, widget do not fit on fullscreen once is opened
8
+
3
9
  ### 5.0.59-rc.2
4
10
  - added: handler for buttons in last-message component
5
11
  - changed: tooltip custom directive
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-web-widget",
3
3
  "author": "Tiledesk SRL",
4
- "version": "5.0.59-rc.2",
4
+ "version": "5.0.59-rc.4",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -1,3 +1,4 @@
1
+ import { ScriptService } from './../chat21-core/providers/scripts/script.service';
1
2
  import { TYPE_DIRECT } from './../chat21-core/utils/constants';
2
3
  /** ANGULAR MODULES */
3
4
  import { AfterViewInit, Component, ElementRef, HostListener, NgZone, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
@@ -113,6 +114,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
113
114
  private appStorageService: AppStorageService,
114
115
  private translatorService: TranslatorService,
115
116
  private translateService: CustomTranslateService,
117
+ private scriptService: ScriptService,
116
118
  public chatManager: ChatManager,
117
119
  private tiledeskRequestsService: TiledeskRequestsService,
118
120
  public tiledeskAuthService: TiledeskAuthService,
@@ -123,220 +125,222 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
123
125
  public imageRepoService: ImageRepoService,
124
126
  public typingService: TypingService,
125
127
  public presenceService: PresenceService,
126
- public uploadService: UploadService
128
+ public uploadService: UploadService
127
129
  ){}
128
130
 
129
- ngOnInit(): void {
130
- this.logger.info('[APP-CONF]---------------- ngOnInit: APP.COMPONENT ---------------- ')
131
- this.initWidgetParamiters();
132
- }
131
+ ngOnInit(): void {
132
+ this.logger.info('[APP-CONF]---------------- ngOnInit: APP.COMPONENT ---------------- ')
133
+ this.initWidgetParamiters();
134
+ }
133
135
 
134
- ngAfterViewInit(): void {
135
- this.logger.info('[APP-CONF]---------------- ngAfterViewInit: APP.COMPONENT ---------------- ')
136
- this.ngZone.run(() => {
137
- const that = this;
138
- const subChangedConversation = this.conversationsHandlerService.conversationChanged.subscribe((conversation) => {
139
- // that.ngZone.run(() => {
140
- if (conversation) {
141
- this.onImageLoaded(conversation)
142
- this.onConversationLoaded(conversation)
136
+ ngAfterViewInit(): void {
137
+ this.logger.info('[APP-CONF]---------------- ngAfterViewInit: APP.COMPONENT ---------------- ')
138
+ this.ngZone.run(() => {
139
+ const that = this;
140
+ const subChangedConversation = this.conversationsHandlerService.conversationChanged.subscribe((conversation) => {
141
+ // that.ngZone.run(() => {
142
+ if (conversation) {
143
+ this.onImageLoaded(conversation)
144
+ this.onConversationLoaded(conversation)
143
145
 
144
- if(conversation.recipient === this.g.senderId && isUserBanned(conversation)){
145
- that.disposeWidget();
146
+ if(conversation.recipient === this.g.senderId && isUserBanned(conversation)){
147
+ that.disposeWidget();
148
+ return;
149
+ }
150
+
151
+ if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
152
+ that.manageTabNotification();
153
+ }
154
+
155
+ if (that.g.isOpen === true) {
156
+ that.g.setParameter('displayEyeCatcherCard', 'none');
157
+
158
+ this.logger.debug('[APP-COMP] obsChangeConversation ::: ', conversation);
159
+ if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
160
+ return;
161
+ }
162
+
163
+ } else {
164
+ // if(conversation.is_new && isJustRecived(this.g.startedAt.getTime(), conversation.timestamp)){
165
+ //widget closed
166
+ if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
167
+ that.lastConversation = conversation;
168
+ that.g.isOpenNewMessage = true;
169
+ that.logger.debug('[APP-COMP] lastconversationnn', that.lastConversation)
170
+ }
171
+
172
+
173
+ let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
174
+ that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
175
+ // }
176
+ }
177
+
178
+ that.triggerOnConversationUpdated(conversation);
179
+ } else {
180
+ this.logger.debug('[APP-COMP] oBSconversationChanged null: errorrr')
146
181
  return;
147
182
  }
148
-
149
- if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
150
- that.manageTabNotification();
151
- }
183
+
184
+ // });
185
+ });
186
+ this.subscriptions.push(subChangedConversation);
152
187
 
153
- if (that.g.isOpen === true) {
188
+ const subAddedConversation = this.conversationsHandlerService.conversationAdded.subscribe((conversation) => {
189
+ // that.ngZone.run(() => {
190
+ if (that.g.isOpen === true && conversation) {
154
191
  that.g.setParameter('displayEyeCatcherCard', 'none');
155
-
156
- this.logger.debug('[APP-COMP] obsChangeConversation ::: ', conversation);
192
+ that.triggerOnConversationUpdated(conversation);
193
+ that.logger.debug('[APP-COMP] obsAddedConversation ::: ', conversation);
157
194
  if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
158
195
  return;
159
196
  }
160
-
161
- } else {
162
- // if(conversation.is_new && isJustRecived(this.g.startedAt.getTime(), conversation.timestamp)){
163
- //widget closed
164
- if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
197
+ if (conversation.is_new) {
198
+ that.manageTabNotification()
199
+ // this.soundMessage();
200
+ }
201
+ if(this.g.isOpen === false){
165
202
  that.lastConversation = conversation;
166
203
  that.g.isOpenNewMessage = true;
167
- that.logger.debug('[APP-COMP] lastconversationnn', that.lastConversation)
168
204
  }
169
-
205
+ } else {
206
+ //widget closed
170
207
 
171
208
  let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
172
209
  that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
173
- // }
174
210
  }
175
-
176
- that.triggerOnConversationUpdated(conversation);
177
- } else {
178
- this.logger.debug('[APP-COMP] oBSconversationChanged null: errorrr')
179
- return;
180
- }
181
-
182
- // });
183
- });
184
- this.subscriptions.push(subChangedConversation);
185
-
186
- const subAddedConversation = this.conversationsHandlerService.conversationAdded.subscribe((conversation) => {
187
- // that.ngZone.run(() => {
188
- if (that.g.isOpen === true && conversation) {
189
- that.g.setParameter('displayEyeCatcherCard', 'none');
190
- that.triggerOnConversationUpdated(conversation);
191
- that.logger.debug('[APP-COMP] obsAddedConversation ::: ', conversation);
192
- if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
193
- return;
211
+ // that.manageTabNotification()
212
+ // });
213
+ if(conversation){
214
+ this.onImageLoaded(conversation)
215
+ this.onConversationLoaded(conversation)
194
216
  }
195
- if (conversation.is_new) {
196
- that.manageTabNotification()
197
- // this.soundMessage();
217
+
218
+ });
219
+ this.subscriptions.push(subAddedConversation);
220
+
221
+ const subAddedArchivedConversations = this.archivedConversationsService.archivedConversationAdded.subscribe((conversation) => {
222
+ // that.ngZone.run(() => {
223
+ if (conversation) {
224
+ that.triggerOnConversationUpdated(conversation);
225
+ this.onImageLoaded(conversation)
226
+ this.onConversationLoaded(conversation)
198
227
  }
199
- if(this.g.isOpen === false){
200
- that.lastConversation = conversation;
201
- that.g.isOpenNewMessage = true;
228
+ // });
229
+ });
230
+ this.subscriptions.push(subAddedArchivedConversations);
231
+
232
+ const subRemovedArchivedConversations = this.archivedConversationsService.archivedConversationRemoved.subscribe((conversation) => {
233
+ // that.ngZone.run(() => {
234
+ if (conversation) {
235
+ this.isConversationArchived = false;
236
+ that.triggerOnConversationUpdated(conversation);
202
237
  }
203
- } else {
204
- //widget closed
238
+ // });
239
+ });
240
+ this.subscriptions.push(subRemovedArchivedConversations);
205
241
 
206
- let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
207
- that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
208
- }
209
- // that.manageTabNotification()
210
- // });
211
- if(conversation){
212
- this.onImageLoaded(conversation)
213
- this.onConversationLoaded(conversation)
214
- }
215
-
216
242
  });
217
- this.subscriptions.push(subAddedConversation);
243
+ this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
244
+ this.tiledeskAuthService.initialize(this.appConfigService.getConfig().apiUrl)
245
+ this.tiledeskRequestsService.initialize(this.appConfigService.getConfig().apiUrl, this.g.projectid)
246
+ this.messagingAuthService.initialize();
247
+ this.chatManager.initialize();
248
+ this.uploadService.initialize();
249
+ }
218
250
 
219
- const subAddedArchivedConversations = this.archivedConversationsService.archivedConversationAdded.subscribe((conversation) => {
220
- // that.ngZone.run(() => {
221
- if (conversation) {
222
- that.triggerOnConversationUpdated(conversation);
223
- this.onImageLoaded(conversation)
224
- this.onConversationLoaded(conversation)
225
- }
226
- // });
227
- });
228
- this.subscriptions.push(subAddedArchivedConversations);
251
+ private initWidgetParamiters(){
252
+ const that = this;
253
+ const obsSettingsService = this.globalSettingsService.obsSettingsService.subscribe((resp) => {
254
+ if(resp){
255
+
256
+ // /** INIT */
257
+ this.logger.setLoggerConfig(this.g.isLogEnabled, this.g.logLevel)
258
+ this.tabTitle = this.g.windowContext.window.document.title
259
+ this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
260
+ this.logger.debug('[APP-COMP] check if token is passed throw url: ', this.g.jwt);
261
+ /**CHECK IF JWT IS IN URL PARAMETERS */
262
+ if (this.g.jwt) {
263
+ // logging in with custom token from url
264
+ // add JWY token to localstorage and authenticate with it this.logger.debug('[APP-COMP] token from url. isShown:', this.g.isShown, 'autostart:', this.g.autoStart)
265
+ this.logger.debug('[APP-COMP] ---------------- logging in with custom token from url ---------------- ');
266
+ // this.g.autoStart = false;
267
+ const storedTiledeskToken = this.appStorageService.getItem('tiledeskToken')
268
+ storedTiledeskToken === this.g.jwt? null: this.appStorageService.setItem('tiledeskToken', this.g.jwt);
269
+ this.g.tiledeskToken = this.g.jwt;
270
+ // this.signInWithCustomToken(this.g.jwt) // moved to authenticate() in else(tiledeskToken)
271
+ }
229
272
 
230
- const subRemovedArchivedConversations = this.archivedConversationsService.archivedConversationRemoved.subscribe((conversation) => {
231
- // that.ngZone.run(() => {
232
- if (conversation) {
233
- this.isConversationArchived = false;
234
- that.triggerOnConversationUpdated(conversation);
273
+ /** INIT LABELS TRANSLATIONS */
274
+ this.translatorService.initI18n().then((result) => {
275
+ this.logger.debug('[APP-COMP] »»»» APP-COMPONENT.TS initI18n result', result);
276
+ const browserLang = this.translatorService.getLanguage();
277
+ // moment.locale(browserLang)
278
+ dayjs.locale(browserLang)
279
+ this.translatorService.translate(this.g);
280
+ }).then(() => {
281
+ /** INIT */
282
+ that.initAll();
283
+ /** TRIGGER ONBEFORE INIT */
284
+ that.triggerOnBeforeInit();
285
+ /** AUTH */
286
+ that.setAuthSubscription();
287
+ /** SCRIPT LOAD */
288
+ that.loadCustomScript(this.appConfigService.getConfig())
289
+ })
290
+
235
291
  }
236
- // });
237
292
  });
238
- this.subscriptions.push(subRemovedArchivedConversations);
239
-
240
- });
241
- this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
242
- this.tiledeskAuthService.initialize(this.appConfigService.getConfig().apiUrl)
243
- this.tiledeskRequestsService.initialize(this.appConfigService.getConfig().apiUrl, this.g.projectid)
244
- this.messagingAuthService.initialize();
245
- this.chatManager.initialize();
246
- this.uploadService.initialize();
247
- }
248
-
249
- private initWidgetParamiters(){
250
- const that = this;
251
- const obsSettingsService = this.globalSettingsService.obsSettingsService.subscribe((resp) => {
252
- if(resp){
253
-
254
- // /** INIT */
255
- this.logger.setLoggerConfig(this.g.isLogEnabled, this.g.logLevel)
256
- this.tabTitle = this.g.windowContext.window.document.title
257
- this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
258
- this.logger.debug('[APP-COMP] check if token is passed throw url: ', this.g.jwt);
259
- /**CHECK IF JWT IS IN URL PARAMETERS */
260
- if (this.g.jwt) {
261
- // logging in with custom token from url
262
- // add JWY token to localstorage and authenticate with it this.logger.debug('[APP-COMP] token from url. isShown:', this.g.isShown, 'autostart:', this.g.autoStart)
263
- this.logger.debug('[APP-COMP] ---------------- logging in with custom token from url ---------------- ');
264
- // this.g.autoStart = false;
265
- const storedTiledeskToken = this.appStorageService.getItem('tiledeskToken')
266
- storedTiledeskToken === this.g.jwt? null: this.appStorageService.setItem('tiledeskToken', this.g.jwt);
267
- this.g.tiledeskToken = this.g.jwt;
268
- // this.signInWithCustomToken(this.g.jwt) // moved to authenticate() in else(tiledeskToken)
269
- }
270
-
271
- /** INIT LABELS TRANSLATIONS */
272
- this.translatorService.initI18n().then((result) => {
273
- this.logger.debug('[APP-COMP] »»»» APP-COMPONENT.TS initI18n result', result);
274
- const browserLang = this.translatorService.getLanguage();
275
- // moment.locale(browserLang)
276
- dayjs.locale(browserLang)
277
- this.translatorService.translate(this.g);
278
- }).then(() => {
279
- /** INIT */
280
- that.initAll();
281
- /** TRIGGER ONBEFORE INIT */
282
- that.triggerOnBeforeInit();
283
- /** AUTH */
284
- that.setAuthSubscription();
285
- })
286
-
287
- }
288
- });
289
- this.subscriptions.push(obsSettingsService);
290
- this.globalSettingsService.initWidgetParamiters(this.g, this.el);
293
+ this.subscriptions.push(obsSettingsService);
294
+ this.globalSettingsService.initWidgetParamiters(this.g, this.el);
291
295
 
292
- // SET AUDIO
293
- this.audio = new Audio();
294
- this.audio.src = this.g.baseLocation + URL_SOUND_LIST_CONVERSATION;
295
- this.audio.load();
296
- }
296
+ // SET AUDIO
297
+ this.audio = new Audio();
298
+ this.audio.src = this.g.baseLocation + URL_SOUND_LIST_CONVERSATION;
299
+ this.audio.load();
300
+ }
297
301
 
298
- private initAll() {
299
- this.addComponentToWindow(this.ngZone);
302
+ private initAll() {
303
+ this.addComponentToWindow(this.ngZone);
300
304
 
301
- //INIT TRIGGER-HANDLER
302
- this.triggerHandler.setElement(this.el)
303
- this.triggerHandler.setWindowContext(this.g.windowContext)
305
+ //INIT TRIGGER-HANDLER
306
+ this.triggerHandler.setElement(this.el)
307
+ this.triggerHandler.setWindowContext(this.g.windowContext)
304
308
 
305
- // /** TRANSLATION LOADER: */
306
- // // this.translatorService.translate(this.g);
307
- // this.translatorService.initI18n().then((result) => {
308
- // this.g.wdLog(['»»»» APP-COMPONENT.TS initI18n result', result]);
309
- // this.translatorService.translate(this.g);
310
- // });
309
+ // /** TRANSLATION LOADER: */
310
+ // // this.translatorService.translate(this.g);
311
+ // this.translatorService.initI18n().then((result) => {
312
+ // this.g.wdLog(['»»»» APP-COMPONENT.TS initI18n result', result]);
313
+ // this.translatorService.translate(this.g);
314
+ // });
311
315
 
312
- /** SET ATTRIBUTES */
313
- const attributes = this.setAttributesFromStorageService();
314
- if (attributes) {
315
- this.g.attributes = attributes;
316
- }
317
- this.setStyleMap()
316
+ /** SET ATTRIBUTES */
317
+ const attributes = this.setAttributesFromStorageService();
318
+ if (attributes) {
319
+ this.g.attributes = attributes;
320
+ }
321
+ this.setStyleMap()
318
322
 
319
- // ------------------------------- //
323
+ // ------------------------------- //
320
324
 
321
- // ------------------------------- //
322
- /**
323
- * INIZIALIZE GLOBALS :
324
- * create settings object used in trigger
325
- * set isMobile
326
- * set attributes
327
- */
328
- this.g.initialize();
329
- // ------------------------------- //
325
+ // ------------------------------- //
326
+ /**
327
+ * INIZIALIZE GLOBALS :
328
+ * create settings object used in trigger
329
+ * set isMobile
330
+ * set attributes
331
+ */
332
+ this.g.initialize();
333
+ // ------------------------------- //
330
334
 
331
- this.removeFirebasewebsocketFromLocalStorage();
332
- // this.triggerLoadParamsEvent();
333
- // this.addComponentToWindow(this.ngZone); // forse dovrebbe stare prima di tutti i triggers
335
+ this.removeFirebasewebsocketFromLocalStorage();
336
+ // this.triggerLoadParamsEvent();
337
+ // this.addComponentToWindow(this.ngZone); // forse dovrebbe stare prima di tutti i triggers
334
338
 
335
- this.initLauncherButton();
336
- this.triggerLoadParamsEvent(); // first trigger
337
- //this.setAvailableAgentsStatus();
339
+ this.initLauncherButton();
340
+ this.triggerLoadParamsEvent(); // first trigger
341
+ //this.setAvailableAgentsStatus();
338
342
 
339
- }
343
+ }
340
344
 
341
345
  // ========= begin:: SUBSCRIPTIONS ============//
342
346
  private async setAuthSubscription(){
@@ -2064,6 +2068,13 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
2064
2068
  this.el.nativeElement.style.setProperty('--button-in-msg-font-size', this.g.buttonFontSize)
2065
2069
  }
2066
2070
 
2071
+
2072
+ private loadCustomScript(config){
2073
+ if(config.hasOwnProperty("globalRemoteJSSrc")){
2074
+ this.scriptService.buildScriptArray(config['globalRemoteJSSrc'])
2075
+ }
2076
+ }
2077
+
2067
2078
  // ========= begin:: DESTROY ALL SUBSCRIPTIONS ============//
2068
2079
  /** elimino tutte le sottoscrizioni */
2069
2080
  ngOnDestroy() {
@@ -62,10 +62,11 @@ import { TranslateModule } from '@ngx-translate/core';
62
62
  import { PickerModule } from '@ctrl/ngx-emoji-mart';
63
63
  import { LoggerModule, NGXLogger, NgxLoggerLevel } from "ngx-logger";
64
64
 
65
- //DIRECTIVES
65
+ //DIRECTIVES-PIPES
66
66
  import { HtmlEntitiesEncodePipe } from './pipe/html-entities-encode.pipe';
67
67
  import { MarkedPipe } from './pipe/marked.pipe';
68
68
  import { SafeHtmlPipe } from './pipe/safe-html.pipe';
69
+ import { TooltipDirective } from 'src/app/directives/tooltip.directive';
69
70
 
70
71
  //LOGGER SERVICES
71
72
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
@@ -128,7 +129,7 @@ import { WaitingService } from './providers/waiting.service';
128
129
  import { StarRatingWidgetService } from './providers/star-rating-widget.service';
129
130
  import { LikeUnlikeComponent } from './component/message/like-unlike/like-unlike.component';
130
131
  import { Rules } from './utils/rules';
131
- import { TooltipDirective } from 'src/app/directives/tooltip.directive';
132
+ import { ScriptService } from 'src/chat21-core/providers/scripts/script.service';
132
133
 
133
134
 
134
135
  const appInitializerFn = (appConfig: AppConfigService, logger: NGXLogger) => {
@@ -381,7 +382,8 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
381
382
  TranslatorService,
382
383
  CustomTranslateService,
383
384
  Triggerhandler,
384
- WaitingService
385
+ WaitingService,
386
+ ScriptService
385
387
  ],
386
388
  bootstrap: [AppComponent]
387
389
  })
@@ -1,7 +1,7 @@
1
1
  <!-- LOGO-->
2
2
  <div id="hiddenFooter" *ngIf="!hideTextAreaContent && poweredBy" class="fade-in-bottom"
3
3
  [class.hideTextReply]="hideTextReply">
4
- <div tabindex="-1" class="c21-powered-by" [innerHTML]="poweredBy"></div>
4
+ <div tabindex="-1" class="c21-powered-by" [innerHTML]="poweredBy" (click)="managePoweredBy($event)"></div>
5
5
  </div>
6
6
 
7
7
  <!-- TEXTAREA + ICONS: conv active-->
@@ -596,4 +596,47 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
596
596
  }
597
597
  }
598
598
 
599
+
600
+
601
+ managePoweredBy(event: Event){
602
+ event.stopPropagation();
603
+ this.segmentLogoClick()
604
+ let target = (event.target as Element) || (event.srcElement as Element) || (event.currentTarget as Element)
605
+ if(target.parentElement.tagName === 'A' && target.parentElement.hasAttribute('href')){
606
+ window.open(target.parentElement.getAttribute('href'), '_blank')
607
+ }
608
+ }
609
+
610
+
611
+ private segmentLogoClick(){
612
+ let that = this
613
+ if(window['analytics']){
614
+ try {
615
+ window['analytics'].page("Widget Conversation Page, LogoClick", {});
616
+ } catch (err) {
617
+ this.logger.error('Event:Signed In [page] error', err);
618
+ }
619
+
620
+ try {
621
+ window['analytics'].identify(that.senderId, {
622
+ name: that.userFullname,
623
+ email: that.userEmail,
624
+ logins: 5,
625
+ });
626
+ } catch (err) {
627
+ this.logger.error('Event:LogoClick [identify] error', err);
628
+ }
629
+ // Segments
630
+ try {
631
+ window['analytics'].track('LogoClick', {
632
+ "username": that.userFullname,
633
+ "userId": that.userEmail,
634
+ "attributes": that.attributes
635
+ });
636
+ } catch (err) {
637
+ this.logger.error('Event:LogoClick [track] error', err);
638
+ }
639
+ }
640
+ }
641
+
599
642
  }
@@ -144,7 +144,7 @@
144
144
  <!-- FOOTER -->
145
145
  <div class="c21-footer fade-in-bottom-footer">
146
146
  <div id="c21-powered-by" (mouseover)="hover=true" (mouseleave)="hover=false">
147
- <div tabindex="-1" class="c21-powered-by" [innerHTML]="g.poweredBy"></div>
147
+ <div tabindex="-1" class="c21-powered-by" [innerHTML]="g.poweredBy" (click)="managePoweredBy($event)"></div>
148
148
  <!-- <div class="build_version">{{g.BUILD_VERSION}}</div> -->
149
149
  </div>
150
150
  <chat-menu-options *ngIf="!hideSettings"
@@ -1,3 +1,4 @@
1
+ import { TiledeskAuthService } from './../../../chat21-core/providers/tiledesk/tiledesk-auth.service';
1
2
  import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
2
3
  import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
3
4
  import { ConversationModel } from '../../../chat21-core/models/conversation';
@@ -47,6 +48,7 @@ export class HomeComponent implements OnInit, AfterViewInit {
47
48
 
48
49
  constructor(
49
50
  public g: Globals,
51
+ private tiledeskAuthService : TiledeskAuthService,
50
52
  private customTranslateService: CustomTranslateService,
51
53
  ) {
52
54
 
@@ -85,6 +87,49 @@ export class HomeComponent implements OnInit, AfterViewInit {
85
87
  }
86
88
 
87
89
 
90
+ managePoweredBy(event: Event){
91
+ event.stopPropagation();
92
+ this.segmentLogoClick()
93
+ let target = (event.target as Element) || (event.srcElement as Element) || (event.currentTarget as Element)
94
+ if(target.parentElement.tagName === 'A' && target.parentElement.hasAttribute('href')){
95
+ window.open(target.parentElement.getAttribute('href'), '_blank')
96
+ }
97
+ }
98
+
99
+
100
+ private segmentLogoClick(){
101
+ let that = this
102
+ let user = this.tiledeskAuthService.getCurrentUser()
103
+ if(window['analytics']){
104
+ try {
105
+ window['analytics'].page("Widget Home Page, LogoClick", {});
106
+ } catch (err) {
107
+ this.logger.error('Event:Signed In [page] error', err);
108
+ }
109
+
110
+ try {
111
+ window['analytics'].identify(user.uid, {
112
+ name: user.firstname + ' ' + user.lastname,
113
+ email: user.email,
114
+ logins: 5,
115
+ });
116
+ } catch (err) {
117
+ this.logger.error('Event:LogoClick [identify] error', err);
118
+ }
119
+ // Segments
120
+ try {
121
+ window['analytics'].track('LogoClick', {
122
+ "username": user.firstname + ' ' + user.lastname,
123
+ "userId": user.uid,
124
+ "attributes": that.g.attributes
125
+ });
126
+ } catch (err) {
127
+ this.logger.error('Event:LogoClick [track] error', err);
128
+ }
129
+ }
130
+ }
131
+
132
+
88
133
 
89
134
 
90
135
 
@@ -369,6 +369,7 @@ export class GlobalSettingsService {
369
369
  this.globals.isMobile? marginX= this.globals.mobileMarginX: marginX = this.globals.marginX
370
370
  divTiledeskiframe.style.right = marginX;
371
371
  }
372
+
372
373
  if (this.globals.isMobile) {
373
374
  divTiledeskiframe.style.bottom = this.globals.mobileMarginY
374
375
  } else {
@@ -587,6 +587,18 @@ export class Globals {
587
587
  } else if(!isOpen && chat21conversationsEL){
588
588
  chat21conversationsEL.classList.remove('isMobile')
589
589
  }
590
+
591
+
592
+ //customize position for 'tiledeskdiv' for mobile
593
+ if(isOpen && this.isMobile && divTiledeskWidget){
594
+ divTiledeskWidget.style.right = '0px'
595
+ divTiledeskWidget.style.bottom = '0px'
596
+ } else if(!isOpen && this.isMobile && divTiledeskWidget){
597
+ divTiledeskWidget.style.bottom = this.marginY
598
+ this.align === 'left'? divTiledeskWidget.style.left = this.mobileMarginX : divTiledeskWidget.style.right = this.mobileMarginX;
599
+ }
600
+
601
+
590
602
  }
591
603
 
592
604
  setWidgetPreviewContainerSize(width: number, height: number){
@@ -17,7 +17,7 @@ export abstract class NotificationsService {
17
17
  }
18
18
  }
19
19
 
20
- abstract initialize(tenant: string, vapidKey: string): void;
20
+ abstract initialize(tenant: string, vapidKey: string, platform: string): void;
21
21
  abstract getNotificationPermissionAndSaveToken(currentUserUid: string): void;
22
22
  abstract removeNotificationsInstance(callback: (string) => void): void;
23
23
 
@@ -184,7 +184,7 @@ export class ChatManager {
184
184
  getConversationHandlerByConversationId(conversationId): any {
185
185
  let handler = null;
186
186
  this.handlers.forEach(conv => {
187
- // this.logger.('[CHAT MANAGER]forEach ***', conversationId, this.handlers, conv);
187
+ this.logger.log('[CHAT MANAGER]forEach ***', conversationId, this.handlers, conv);
188
188
  if (conv.conversationWith === conversationId) {
189
189
  handler = conv;
190
190
  return;
@@ -1,79 +1,82 @@
1
- import { LoggerInstance } from './../logger/loggerInstance';
2
1
  import { Injectable } from '@angular/core';
3
2
  // services
4
3
  import { NotificationsService } from '../abstract/notifications.service';
5
-
4
+ import { LoggerInstance } from '../logger/loggerInstance';
5
+ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
6
6
  // firebase
7
- // import firebase from 'firebase/app';
7
+ // import * as firebase from 'firebase/app';
8
+ import firebase from "firebase/app";
9
+ import 'firebase/messaging';
10
+ import 'firebase/auth';
8
11
 
9
- import { LoggerService } from '../abstract/logger.service';
12
+ @Injectable({ providedIn: 'root' })
10
13
 
11
- // @Injectable({ providedIn: 'root' })
12
- @Injectable()
13
14
  export class FirebaseNotifications extends NotificationsService {
14
-
15
- // public BUILD_VERSION: string;
15
+
16
16
  private FCMcurrentToken: string;
17
17
  private userId: string;
18
18
  private tenant: string;
19
19
  private vapidkey: string;
20
- private firebase: any;
21
-
20
+ private platform: string;
22
21
  private logger: LoggerService = LoggerInstance.getInstance();
23
22
  constructor() {
24
23
  super();
25
24
  }
26
25
 
27
- async initialize(tenant: string, vapId: string) {
26
+ initialize(tenant: string, vapId: string, platform: string): void {
28
27
  this.tenant = tenant
29
28
  this.vapidkey = vapId
30
- this.logger.debug('[FIREBASE-NOTIFICATIONS] initialize - tenant ', this.tenant)
31
-
32
- const { default: firebase} = await import("firebase/app");
33
- this.firebase = firebase
29
+ platform === 'desktop'? this.platform = 'ionic' : this.platform = platform
30
+ this.logger.log('[FIREBASE-NOTIFICATIONS] initialize - tenant ', this.tenant, this.platform)
34
31
 
35
32
  if (!('serviceWorker' in navigator)) {
36
33
  // , disable or hide UI.
37
34
  this.logger.error("[FIREBASE-NOTIFICATIONS] initialize - Service Worker isn't supported on this browser", navigator)
38
35
  return;
39
36
  }
40
- if (('serviceWorker' in navigator)) {
41
- // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser ", navigator)
42
- navigator.serviceWorker.getRegistrations().then((serviceWorkerRegistrations) => {
43
- this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser serviceWorkerRegistrations", serviceWorkerRegistrations)
44
- if (serviceWorkerRegistrations.length > 0) {
45
- serviceWorkerRegistrations.forEach(registration => {
46
- this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registration ", registration)
47
- // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations scriptURL", registrations.active.scriptURL)
48
- // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations state", registrations.active.state)
49
-
50
- });
51
- } else {
52
- this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser - !not registered",)
37
+ // if (('serviceWorker' in navigator)) {
38
+ // navigator.serviceWorker.register('firebase-messaging-sw.js')
39
+ // .then(function (registration) {
40
+ // console.log('[FIREBASE-NOTIFICATIONS] initialize serviceWorker Registration successful, scope is:', registration.scope);
53
41
 
54
- }
55
- });
56
- }
42
+
43
+ // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser ", navigator)
44
+ // // navigator.serviceWorker.getRegistrations().then((serviceWorkerRegistrations) => {
45
+ // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser serviceWorkerRegistrations", serviceWorkerRegistrations)
46
+ // // if (serviceWorkerRegistrations.length > 0) {
47
+ // // serviceWorkerRegistrations.forEach(registration => {
48
+ // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registration ", registration)
49
+ // // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations scriptURL", registrations.active.scriptURL)
50
+ // // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations state", registrations.active.state)
51
+
52
+ // // });
53
+ // // } else {
54
+ // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser - !not registered",)
55
+ // // // navigator.serviceWorker.register('http://localhost:8101/firebase-messaging-sw.js')
56
+ // // // .then(function (registration) {
57
+ // // // console.log('Service worker successfully registered.');
58
+ // // // return registration;
59
+ // // // }).catch(function (err) {
60
+ // // // console.error('Unable to register service worker.', err);
61
+ // // // });
62
+ // // }
63
+ // // });
64
+ // }).catch(function (err) {
65
+ // console.log('Service worker registration failed, error:', err);
66
+ // });
67
+ // }
57
68
  }
58
69
 
70
+
71
+
59
72
  getNotificationPermissionAndSaveToken(currentUserUid) {
60
73
  // this.tenant = this.getTenant();
61
- this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - tenant ', this.tenant)
62
- this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - currentUserUid ', currentUserUid)
74
+ this.logger.log('initialize FROM [APP-COMP] - [FIREBASE-NOTIFICATIONS] calling requestPermission - tenant ', this.tenant, ' currentUserUid ', currentUserUid)
75
+ // this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - currentUserUid ', currentUserUid)
63
76
  this.userId = currentUserUid;
64
- // Service Worker explicit registration to explicitly define sw location at a path
65
- // const swRegistration = async () => {
66
- // try {
67
- // await navigator.serviceWorker.register('http://localhost:8101/firebase-messaging-sw.js');
68
- // } catch (error) {
69
- // console.error(error);
70
- // }
71
- // }
72
-
73
77
 
74
-
75
- if (this.firebase.messaging.isSupported()) {
76
- const messaging = this.firebase.messaging();
78
+ if (firebase.messaging.isSupported()) {
79
+ const messaging = firebase.messaging();
77
80
  // messaging.requestPermission()
78
81
  Notification.requestPermission().then((permission) => {
79
82
  if (permission === 'granted') {
@@ -91,46 +94,136 @@ export class FirebaseNotifications extends NotificationsService {
91
94
  });
92
95
  } else {
93
96
  this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> FIREBASE MESSAGING IS NOT SUPPORTED')
97
+
98
+ // if(this.platform == 'android' || this.platform === 'ios'){
99
+ // this.logger.log('[MQTTNotificationService] >>>> FIREBASE MESSAGING: use FCM plugin')
100
+ // this.fcm.onTokenRefresh().subscribe(FCMtoken => {
101
+ // // Register your new token in your back-end if you want
102
+ // // backend.registerToken(token);
103
+ // this.FCMcurrentToken = FCMtoken;
104
+ // console.log("[MQTTNotificationService] FCM: onTokenRefresh --->", FCMtoken);
105
+ // this.updateToken(FCMtoken, currentUserUid)
106
+ // });
107
+ // this.fcm.requestPushPermission().then((permission) => {
108
+ // console.log("[MQTTNotificationService] FCM: requestPushPermission --->", permission);
109
+ // if(permission === true){
110
+ // this.fcm.getToken().then(FCMtoken => {
111
+ // console.log("[MQTTNotificationService] FCM: getToken --->", FCMtoken);
112
+ // this.FCMcurrentToken = FCMtoken;
113
+ // this.updateToken(FCMtoken, currentUserUid)
114
+ // });
115
+ // }
116
+ // });
117
+
118
+ // }
94
119
  }
95
120
  }
96
121
 
122
+
123
+ // getNotificationPermissionAndSaveToken(currentUserUid) {
124
+ // // this.tenant = this.getTenant();
125
+ // this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - tenant ', this.tenant)
126
+ // this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - currentUserUid ', currentUserUid)
127
+ // this.userId = currentUserUid;
128
+ // const messaging = firebase.messaging();
129
+ // if (firebase.messaging.isSupported()) {
130
+ // // messaging.requestPermission()
131
+ // Notification.requestPermission().then((permission) => {
132
+ // if (permission === 'granted') {
133
+ // this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> requestPermission Notification permission granted.');
134
+ // messaging.getToken({ vapidKey: 'BOsgS2ADwspKdWAmiFDZXEYqY1HSYADVfJT3j67wsySh3NxaViJqoabPJH8WM02wb5r8cQIm5TgM0UK047Z1D1c'}).then((currentToken) => {
135
+ // if (currentToken) {
136
+ // this.sendTokenToServer(currentToken);
137
+ // // updateUIForPushEnabled(currentToken);
138
+
139
+ // } else {
140
+ // // Show permission request UI
141
+ // console.log('No registration token available. Request permission to generate one.');
142
+ // // ...
143
+ // }
144
+ // }).catch((err) => {
145
+ // console.log('An error occurred while retrieving token. ', err);
146
+ // // ...
147
+ // });
148
+
149
+ // resetUI()
150
+
151
+ // } else {
152
+ // this.logger.error('Unable to get permission to notify.');
153
+ // }
154
+ // })
155
+
156
+ // }
157
+ // }
158
+
159
+ // sendTokenToServer(currentToken) {
160
+ // if (!this.isTokenSentToServer()) {
161
+ // console.log('Sending token to server...');
162
+ // // TODO(developer): Send the current token to your server.
163
+ // this.setTokenSentToServer(true);
164
+ // } else {
165
+ // console.log('Token already sent to server so won\'t send it again ' +
166
+ // 'unless it changes');
167
+ // }
168
+ // }
169
+
170
+ // isTokenSentToServer() {
171
+ // return window.localStorage.getItem('sentToServer') === '1';
172
+ // }
173
+
174
+ // setTokenSentToServer(sent) {
175
+ // window.localStorage.setItem('sentToServer', sent ? '1' : '0');
176
+ // }
177
+
97
178
  removeNotificationsInstance(callback: (string) => void) {
98
179
  var self = this;
99
- this.firebase.auth().onAuthStateChanged(function (user) {
100
- if (user) {
101
- self.logger.debug('[FIREBASE-NOTIFICATIONS] - User is signed in. ', user)
102
-
103
- } else {
104
- self.logger.debug('[FIREBASE-NOTIFICATIONS] - No user is signed in. ', user)
105
- }
106
- });
107
-
108
- this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > this.userId', this.userId);
109
- this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > FCMcurrentToken', this.FCMcurrentToken);
110
- // this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > this.tenant', this.tenant);
111
- const urlNodeFirebase = '/apps/' + this.tenant
112
- const connectionsRefinstancesId = urlNodeFirebase + '/users/' + this.userId + '/instances/'
113
- this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRefinstancesId ', connectionsRefinstancesId);
180
+ // firebase.auth().onAuthStateChanged(function (user) {
181
+ // if (user) {
182
+ // self.logger.debug('[FIREBASE-NOTIFICATIONS] - FB User is signed in. ', user)
183
+ // self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > this.userId', self.userId);
184
+ // self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > FCMcurrentToken', self.FCMcurrentToken);
185
+ // // this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > this.tenant', this.tenant);
186
+ // } else {
187
+ // self.logger.debug('[FIREBASE-NOTIFICATIONS] - No FB user is signed in. ', user)
188
+ // }
189
+ // });
190
+ const urlNodeFirebase = '/apps/' + self.tenant
191
+ const connectionsRefinstancesId = urlNodeFirebase + '/users/' + self.userId + '/instances/'
192
+ self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRefinstancesId ', connectionsRefinstancesId);
114
193
  let connectionsRefURL = '';
115
194
  if (connectionsRefinstancesId) {
116
- connectionsRefURL = connectionsRefinstancesId + this.FCMcurrentToken;
117
- const connectionsRef = this.firebase.database().ref().child(connectionsRefURL);
118
- this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRef ', connectionsRef);
119
- this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRef url ', connectionsRefURL);
195
+ connectionsRefURL = connectionsRefinstancesId + self.FCMcurrentToken;
196
+ const connectionsRef = firebase.database().ref().child(connectionsRefURL);
197
+ self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRef ', connectionsRef);
198
+ self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRef url ', connectionsRefURL);
120
199
  connectionsRef.off()
121
200
  connectionsRef.remove()
122
201
  .then(() => {
123
- this.logger.log("[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > Remove succeeded.")
202
+ self.logger.log("[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > Remove succeeded.")
124
203
  callback('success')
125
204
  }).catch((error) => {
126
- this.logger.error("[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance Remove failed: " + error.message)
205
+ self.logger.error("[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance Remove failed: " + error.message)
127
206
  callback('error')
128
207
  }).finally(() => {
129
- this.logger.log('[FIREBASE-NOTIFICATIONS] COMPLETED');
208
+ self.logger.log('[FIREBASE-NOTIFICATIONS] COMPLETED');
130
209
  })
131
210
  }
211
+
132
212
  }
133
213
 
214
+ // removeNotificationsInstance() {
215
+ // let promise = new Promise((resolve, reject) => {
216
+ // this.appStoreService.getInstallation(this.projectId).then((res) => {
217
+ // console.log("Get Installation Response: ", res);
218
+ // resolve(res);
219
+ // }).catch((err) => {
220
+ // console.error("Error getting installation: ", err);
221
+ // reject(err);
222
+ // })
223
+ // })
224
+ // return promise;
225
+ // }
226
+
134
227
 
135
228
  // ********** PRIVATE METHOD - START ****************//
136
229
  private updateToken(FCMcurrentToken, currentUserUid) {
@@ -149,14 +242,14 @@ export class FirebaseNotifications extends NotificationsService {
149
242
  const device_model = {
150
243
  device_model: navigator.userAgent,
151
244
  language: navigator.language,
152
- platform: 'ionic',
245
+ platform: this.platform,
153
246
  platform_version: this.BUILD_VERSION
154
247
  }
155
248
 
156
249
  updates[connectionsRefinstancesId + connection] = device_model;
157
250
 
158
251
  this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> getPermission > updateToken in DB', updates);
159
- this.firebase.database().ref().update(updates)
252
+ firebase.database().ref().update(updates)
160
253
  }
161
254
  // ********** PRIVATE METHOD - END ****************//
162
255
 
@@ -102,6 +102,7 @@ export class MQTTConversationHandler extends ConversationHandlerService {
102
102
  this.chat21Service.chatClient.lastMessages(this.conversationWith, (err, messages) => {
103
103
  if (!err) {
104
104
  this.logger.log('[MQTTConversationHandlerSERVICE] message lastMessages:', messages);
105
+ messages.sort(compareValues('timestamp', 'asc'));
105
106
  messages.forEach(message => {
106
107
  // this.addedMessage(msg);
107
108
  const msg: MessageModel = message;
@@ -1,49 +1,48 @@
1
-
2
1
  import { Injectable } from '@angular/core';
3
2
  // services
4
3
  import { NotificationsService } from '../abstract/notifications.service';
5
4
  import { LoggerInstance } from '../logger/loggerInstance';
6
5
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
7
-
8
6
  // firebase
9
- // import firebase from "firebase/app";
10
-
7
+ import firebase from "firebase/app";
8
+ import 'firebase/messaging';
9
+ import 'firebase/auth';
11
10
  // chat21
12
11
  import { Chat21Service } from './chat-service';
13
12
 
14
- // @Injectable({ providedIn: 'root' })
15
- @Injectable()
13
+ @Injectable({
14
+ providedIn: 'root'
15
+ })
16
16
  export class MQTTNotifications extends NotificationsService {
17
-
17
+
18
18
  // public BUILD_VERSION: string;
19
19
  private FCMcurrentToken: string;
20
20
  private userId: string;
21
21
  private tenant: string;
22
22
  private vapidkey: string;
23
- private firebase: any;
24
-
23
+ private platform: string;
25
24
  private logger: LoggerService = LoggerInstance.getInstance();
26
25
 
27
26
  constructor(
28
- public chat21Service: Chat21Service
27
+ public chat21Service: Chat21Service,
29
28
  ) {
30
29
  super();
31
30
  }
32
31
 
33
- async initialize(tenant: string, vapId: string) {
32
+ initialize(tenant: string, vapId: string, platform: string): void {
34
33
  this.tenant = tenant;
35
34
  this.vapidkey = vapId;
36
-
37
- const { default: firebase} = await import("firebase/app");
38
- this.firebase = firebase
39
-
35
+ platform === 'desktop'? this.platform = 'ionic' : this.platform = platform
36
+ this.logger.log('[MQTTNotificationService] initialize - tenant ', this.tenant, this.platform)
40
37
  return;
41
38
  }
42
39
 
43
40
  getNotificationPermissionAndSaveToken(currentUserUid) {
41
+ console.log("[MQTTNotificationService] getNotificationPermissionAndSaveToken()",currentUserUid);
44
42
  this.userId = currentUserUid;
45
- if (this.firebase.messaging.isSupported()) {
46
- const messaging = this.firebase.messaging();
43
+ if (firebase.messaging.isSupported()) {
44
+ console.log("[MQTTNotificationService] firebase.messaging.isSupported -> YES");
45
+ const messaging = firebase.messaging();
47
46
  // messaging.requestPermission()
48
47
  Notification.requestPermission().then((permission) => {
49
48
  if (permission === 'granted') {
@@ -61,6 +60,28 @@ export class MQTTNotifications extends NotificationsService {
61
60
  });
62
61
  } else {
63
62
  this.logger.log('[MQTTNotificationService] >>>> FIREBASE MESSAGING IS NOT SUPPORTED')
63
+
64
+ // if(this.platform == 'android' || this.platform === 'ios'){
65
+ // this.logger.log('[MQTTNotificationService] >>>> FIREBASE MESSAGING: use FCM plugin')
66
+ // this.fcm.onTokenRefresh().subscribe(FCMtoken => {
67
+ // // Register your new token in your back-end if you want
68
+ // // backend.registerToken(token);
69
+ // this.FCMcurrentToken = FCMtoken;
70
+ // console.log("[MQTTNotificationService] FCM: onTokenRefresh --->", FCMtoken);
71
+ // this.saveToken(FCMtoken, currentUserUid)
72
+ // });
73
+ // this.fcm.requestPushPermission().then((permission) => {
74
+ // console.log("[MQTTNotificationService] FCM: requestPushPermission --->", permission);
75
+ // if(permission === true){
76
+ // this.fcm.getToken().then(FCMtoken => {
77
+ // console.log("[MQTTNotificationService] FCM: getToken --->", FCMtoken);
78
+ // this.FCMcurrentToken = FCMtoken;
79
+ // this.saveToken(FCMtoken, currentUserUid)
80
+ // });
81
+ // }
82
+ // });
83
+
84
+ // }
64
85
  }
65
86
  }
66
87
 
@@ -83,7 +104,7 @@ export class MQTTNotifications extends NotificationsService {
83
104
  let connectionsRefURL = '';
84
105
  if (connectionsRefinstancesId) {
85
106
  connectionsRefURL = connectionsRefinstancesId + self.FCMcurrentToken;
86
- const connectionsRef = this.firebase.database().ref().child(connectionsRefURL);
107
+ const connectionsRef = firebase.database().ref().child(connectionsRefURL);
87
108
  self.logger.log('[MQTTNotificationService] >>>> connectionsRef ', connectionsRef);
88
109
  self.logger.log('[MQTTNotificationService] >>>> connectionsRef url ', connectionsRefURL);
89
110
  connectionsRef.off()
@@ -107,7 +128,7 @@ export class MQTTNotifications extends NotificationsService {
107
128
  const device_model = {
108
129
  device_model: navigator.userAgent,
109
130
  language: navigator.language,
110
- platform: 'ionic',
131
+ platform: this.platform,
111
132
  platform_version: this.BUILD_VERSION
112
133
  }
113
134
  this.chat21Service.chatClient.saveInstance(FCMcurrentToken,device_model,(err, response) => {
@@ -0,0 +1,12 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { ScriptService } from './script.service';
4
+
5
+ describe('ScriptService', () => {
6
+ beforeEach(() => TestBed.configureTestingModule({}));
7
+
8
+ it('should be created', () => {
9
+ const service: ScriptService = TestBed.get(ScriptService);
10
+ expect(service).toBeTruthy();
11
+ });
12
+ });
@@ -0,0 +1,71 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
4
+ import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
5
+
6
+ @Injectable({
7
+ providedIn: 'root'
8
+ })
9
+ export class ScriptService {
10
+
11
+ private scriptList: Array<{name: string, loaded: boolean, src: string}> = []
12
+ private logger: LoggerService = LoggerInstance.getInstance();
13
+
14
+ constructor(
15
+ public http: HttpClient,
16
+ ) { }
17
+
18
+ buildScriptArray(globalRemoteJSSrc: string){
19
+ this.logger.log('[SCRIPT-SERVICE] buildScriptArray globalRemoteJSSrc ', globalRemoteJSSrc);
20
+ if(!this.isEmpty(globalRemoteJSSrc)){
21
+ var scriptArray = globalRemoteJSSrc.split(",")
22
+
23
+ let count = 0;
24
+ scriptArray.forEach(element => {
25
+ count = count + 1;
26
+ this.scriptList.push({name: element.split('/').pop(), loaded: false, src: element})
27
+ });
28
+ this.logger.log('[SCRIPT-SERVICE] buildScriptArray ', this.scriptList);
29
+ this.load()
30
+
31
+ }
32
+ }
33
+
34
+ load() {
35
+ this.logger.log('[SCRIPT-SERV] load ...scripts ', this.scriptList)
36
+ var promises: any[] = [];
37
+ this.scriptList.forEach((script) => promises.push(this.loadScript(script)));
38
+ return Promise.all(promises).catch((err) => {
39
+ // log that I have an error, return the entire array;
40
+ this.logger.error('A promise failed to resolve', err);
41
+
42
+ });
43
+ }
44
+
45
+
46
+ loadScript(currentScript){
47
+ this.logger.log('[SCRIPT-SERVICE] load script:', currentScript);
48
+ return new Promise((resolve, reject) => {
49
+ //resolve if already loaded
50
+ if (currentScript.loaded) {
51
+ resolve({ script: currentScript.name, loaded: true, status: 'Already Loaded' });
52
+ }
53
+ else {
54
+ //load script
55
+ let script = document.createElement('script')
56
+ script.type = 'text/javascript';
57
+ script.src = currentScript.src;
58
+ script.onload = () => {
59
+ currentScript.loaded = true;
60
+ resolve({ script: name, loaded: true, status: 'Loaded' });
61
+ }
62
+ script.onerror = (error: any) => resolve({ script: currentScript.name, loaded: false, status: 'Loaded' });
63
+ document.getElementsByTagName('head')[0].appendChild(script);
64
+ }
65
+ });
66
+ }
67
+
68
+ isEmpty(url: string) {
69
+ return (url === undefined || url == null || url.length <= 0) ? true : false;
70
+ }
71
+ }
@@ -38,12 +38,20 @@ export const BCK_COLOR_CONVERSATION_UNSELECTED = '#FFFFFF ';
38
38
 
39
39
  export const TYPE_SUPPORT_GROUP = 'support-group';
40
40
  export const CHANNEL_TYPE_GROUP = 'group';
41
+ export const CHANNEL_TYPE_CHAT21 = 'chat21';
42
+ export const CHANNEL_TYPE_EMAIL = 'email';
43
+ export const CHANNEL_TYPE_FORM = 'form';
44
+ export const CHANNEL_TYPE_MESSANGER = 'messanger';
45
+ export const CHANNEL_TYPE_WHATSAPP = 'whatsapp';
46
+ export const CHANNEL_TYPE_TELEGRAM = 'telegram';
41
47
 
42
48
  // TYPES MESSAGES
43
49
  export const TYPE_MSG_TEXT = 'text';
44
50
  export const TYPE_MSG_IMAGE = 'image';
45
51
  export const TYPE_MSG_FILE = 'file';
46
52
  export const TYPE_MSG_BUTTON = 'button';
53
+ export const TYPE_MSG_EMAIL = 'email';
54
+ export const TYPE_MSG_FORM = 'form';
47
55
 
48
56
  export const MAX_WIDTH_IMAGES = 230;
49
57
  export const MIN_WIDTH_IMAGES = 130;