@snugdesk/avaya-ipo-widget 0.2.2 → 0.2.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.
package/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { NgZone, OnInit, OnDestroy, EventEmitter, ChangeDetectorRef, AfterViewInit, ElementRef, OnChanges, SimpleChanges } from '@angular/core';
2
+ import { NgZone, OnInit, OnDestroy, OnChanges, EventEmitter, ChangeDetectorRef, SimpleChanges, AfterViewInit, ElementRef } from '@angular/core';
3
3
  import * as i14 from '@angular/forms';
4
4
  import { FormGroup, FormBuilder } from '@angular/forms';
5
5
  import * as rxjs from 'rxjs';
6
6
  import { BehaviorSubject, Subject } from 'rxjs';
7
7
  import { HttpClient } from '@angular/common/http';
8
- import { SnugdeskAuthenticationService } from '@snugdesk/core';
8
+ import { SnugdeskAuthenticationService, AppSyncHelperService } from '@snugdesk/core';
9
9
  import * as i19 from 'ngx-intl-tel-input';
10
10
  import { CountryISO, SearchCountryField } from 'ngx-intl-tel-input';
11
11
  import * as i13 from '@angular/common';
@@ -69,7 +69,6 @@ declare class AvayaIPOService {
69
69
  private readonly DOM_TAGS;
70
70
  private configTemplate;
71
71
  private readonly agentStatusApiUrl;
72
- private readonly CALL_HISTORY_API_URL;
73
72
  private prewarmedStream?;
74
73
  private isSafari;
75
74
  private _rpcPatched;
@@ -191,7 +190,7 @@ declare class EntitiesSearchService {
191
190
  static ɵprov: i0.ɵɵInjectableDeclaration<EntitiesSearchService>;
192
191
  }
193
192
 
194
- declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
193
+ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy, OnChanges {
195
194
  private formBuilder;
196
195
  private avayaIPOService;
197
196
  private cdr;
@@ -200,8 +199,18 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
200
199
  private entitiesSearchService;
201
200
  private snugdeskAuthService;
202
201
  hostDarkMode: boolean;
202
+ get hostModeStandalone(): boolean;
203
+ get hostModePopup(): boolean;
203
204
  private readonly STORAGE_KEY;
204
205
  isVisible: boolean;
206
+ /**
207
+ * Render mode for the widget shell:
208
+ * - 'popup' (default): owns no dimensions — fills whatever box the host gives it (e.g. the snugdesk-app
209
+ * header popover), with a min-size guard and its own internal scroll. Preserves 100% of current behavior.
210
+ * - 'standalone': provides its own full-page frame — a centered card on desktop, full-bleed on mobile —
211
+ * for running the softphone independently.
212
+ */
213
+ displayMode: 'popup' | 'standalone';
205
214
  configurationMode?: string;
206
215
  avayaIPOServerIP?: string;
207
216
  avayaIPOServerPort?: number;
@@ -212,8 +221,35 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
212
221
  token?: string;
213
222
  tenantId: string;
214
223
  userId: string;
224
+ /**
225
+ * Optional Avaya IP Office credentials. When BOTH `extension` and `password` are supplied (via the
226
+ * host binding), the widget patches the login form and auto-logs-in once — no manual login needed.
227
+ * If they are not supplied, the widget falls back to any saved localStorage session, otherwise it
228
+ * shows the login form as before.
229
+ */
230
+ extension?: string;
231
+ password?: string;
232
+ /** Show/hide the History tab. Default true keeps current behavior. */
233
+ showHistory: boolean;
234
+ /** Show/hide the Contacts tab. Default true keeps current behavior. */
235
+ showContacts: boolean;
236
+ /**
237
+ * The bottom tab bar only earns its space when at least one of History/Contacts is visible.
238
+ * With both hidden only Keypad (the default view) would remain, so the whole bar is hidden.
239
+ */
240
+ get showTabBar(): boolean;
215
241
  notificationEvent: EventEmitter<number>;
242
+ /**
243
+ * Fires when an inbound call starts ringing, so the host app can open/focus the widget popover.
244
+ * Payload: the call id, the caller's number, and the resolved caller name (null if not yet known).
245
+ */
246
+ incomingCall: EventEmitter<{
247
+ callId: string;
248
+ number: string;
249
+ name: string | null;
250
+ }>;
216
251
  readonly avayaLogoUrl: string;
252
+ readonly widgetVersion: "0.2.3";
217
253
  isReconnectingInProgress: boolean;
218
254
  isFailoverInProgress: boolean;
219
255
  isFailbackInProgress: boolean;
@@ -227,6 +263,7 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
227
263
  private awlScriptPromise?;
228
264
  loginForm: FormGroup;
229
265
  activeTab: 'history' | 'contacts' | 'keypad' | 'settings';
266
+ private previousTab;
230
267
  private loginSub?;
231
268
  private incomingCallSub?;
232
269
  private callStateSub?;
@@ -239,11 +276,14 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
239
276
  authErrorMessage: string;
240
277
  authLoading: boolean;
241
278
  private hasInitialized;
279
+ private autoLoginAttempted;
242
280
  private callLogIndex;
243
281
  private pendingDisconnectSide;
244
282
  private callStartTimes;
245
283
  constructor(formBuilder: FormBuilder, avayaIPOService: AvayaIPOService, cdr: ChangeDetectorRef, countryService: CountryService, phoneNumberLookupService: PhoneNumberLookupService, entitiesSearchService: EntitiesSearchService, snugdeskAuthService: SnugdeskAuthenticationService);
246
284
  ngOnInit(): Promise<void>;
285
+ ngOnChanges(changes: SimpleChanges): void;
286
+ private ensureVisibleTab;
247
287
  private initAfterAuth;
248
288
  private authenticateWithToken;
249
289
  onAuthLoginClick(): Promise<void>;
@@ -251,6 +291,8 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
251
291
  onLogout(): void;
252
292
  private handleLoginStatus;
253
293
  selectTab(tab: 'history' | 'contacts' | 'keypad' | 'settings'): void;
294
+ /** Leave Settings and return to the screen the user came from (guards against a now-hidden tab). */
295
+ closeSettings(): void;
254
296
  onHistoryMakeCall(payload: {
255
297
  dialOut: string;
256
298
  name?: string;
@@ -260,6 +302,15 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
260
302
  dialOut: string;
261
303
  name?: string;
262
304
  }): void;
305
+ /**
306
+ * Public API — place an outbound call programmatically (e.g. click-to-call from the host app).
307
+ * Switches to the keypad view and dials `number`. Requires the widget to be registered;
308
+ * if it is still on the login screen the call is skipped with a warning.
309
+ *
310
+ * Usage from the host app (via @ViewChild(AvayaIPOWidgetComponent)):
311
+ * this.avayaWidget?.makeCall('9876543210');
312
+ */
313
+ makeCall(number: string): void;
263
314
  onPhoneEndCall(): void;
264
315
  onDeviceChange(change: {
265
316
  audioInputId: string;
@@ -274,17 +325,25 @@ declare class AvayaIPOWidgetComponent implements OnInit, OnDestroy {
274
325
  private getOpenSearchCallerName;
275
326
  private normalizePhoneForSearch;
276
327
  private persistSession;
328
+ private hasInputCredentials;
329
+ /**
330
+ * Auto-login when both `extension` and `password` are supplied via @Input. Fires at most once for the
331
+ * widget's lifetime (so a manual logout is respected and we never loop). Returns true if it kicked off
332
+ * a login, so the caller can skip the localStorage fallback.
333
+ */
334
+ private tryAutoLoginFromInputs;
277
335
  private restoreSession;
278
336
  private restoreThemePreference;
279
337
  private clearSession;
280
338
  private loadAwlScript;
281
339
  static ɵfac: i0.ɵɵFactoryDeclaration<AvayaIPOWidgetComponent, never>;
282
- static ɵcmp: i0.ɵɵComponentDeclaration<AvayaIPOWidgetComponent, "snugdesk-avaya-ipo-widget", never, { "isVisible": { "alias": "isVisible"; "required": false; }; "configurationMode": { "alias": "configurationMode"; "required": false; }; "avayaIPOServerIP": { "alias": "avayaIPOServerIP"; "required": false; }; "avayaIPOServerPort": { "alias": "avayaIPOServerPort"; "required": false; }; "avayaIPOServerStunServerIP": { "alias": "avayaIPOServerStunServerIP"; "required": false; }; "avayaIPOServerStunServerPort": { "alias": "avayaIPOServerStunServerPort"; "required": false; }; "avayaIPOServerTurnServerIP": { "alias": "avayaIPOServerTurnServerIP"; "required": false; }; "avayaIPOServerTurnServerPort": { "alias": "avayaIPOServerTurnServerPort"; "required": false; }; "token": { "alias": "token"; "required": false; }; "tenantId": { "alias": "tenantId"; "required": false; }; "userId": { "alias": "userId"; "required": false; }; }, { "notificationEvent": "notificationEvent"; }, never, never, false, never>;
340
+ static ɵcmp: i0.ɵɵComponentDeclaration<AvayaIPOWidgetComponent, "snugdesk-avaya-ipo-widget", never, { "isVisible": { "alias": "isVisible"; "required": false; }; "displayMode": { "alias": "displayMode"; "required": false; }; "configurationMode": { "alias": "configurationMode"; "required": false; }; "avayaIPOServerIP": { "alias": "avayaIPOServerIP"; "required": false; }; "avayaIPOServerPort": { "alias": "avayaIPOServerPort"; "required": false; }; "avayaIPOServerStunServerIP": { "alias": "avayaIPOServerStunServerIP"; "required": false; }; "avayaIPOServerStunServerPort": { "alias": "avayaIPOServerStunServerPort"; "required": false; }; "avayaIPOServerTurnServerIP": { "alias": "avayaIPOServerTurnServerIP"; "required": false; }; "avayaIPOServerTurnServerPort": { "alias": "avayaIPOServerTurnServerPort"; "required": false; }; "token": { "alias": "token"; "required": false; }; "tenantId": { "alias": "tenantId"; "required": false; }; "userId": { "alias": "userId"; "required": false; }; "extension": { "alias": "extension"; "required": false; }; "password": { "alias": "password"; "required": false; }; "showHistory": { "alias": "showHistory"; "required": false; }; "showContacts": { "alias": "showContacts"; "required": false; }; }, { "notificationEvent": "notificationEvent"; "incomingCall": "incomingCall"; }, never, never, false, never>;
283
341
  }
284
342
 
285
343
  declare class CallHistoryComponent implements OnInit {
286
- private http;
287
344
  private cdr;
345
+ private appSync;
346
+ private auth;
288
347
  mode: 'dial' | 'transfer';
289
348
  tenantId?: string;
290
349
  agentId?: string;
@@ -293,17 +352,19 @@ declare class CallHistoryComponent implements OnInit {
293
352
  name?: string;
294
353
  }>;
295
354
  transferEv: EventEmitter<any>;
296
- private readonly CALL_HISTORY_API_URL;
297
355
  showHistoryLoader: boolean;
298
356
  callHistory: any[];
299
357
  searchTerm: string;
300
358
  recentCallactiveTab: 'recentCall' | 'missedCall';
301
359
  selectedCall: any;
302
- constructor(http: HttpClient, cdr: ChangeDetectorRef);
360
+ private readonly LIST_PHONE_INTERACTIONS_QUERY;
361
+ constructor(cdr: ChangeDetectorRef, appSync: AppSyncHelperService, auth: SnugdeskAuthenticationService);
303
362
  ngOnInit(): Promise<void>;
304
363
  recentSelectTab(tab: 'recentCall' | 'missedCall'): void;
305
364
  loadCallHistory(): Promise<void>;
306
- getCallHistory(tenantId: string, agentId: string): Promise<any>;
365
+ private fetchPhoneInteractions;
366
+ private mapInteractionToHistoryItem;
367
+ private safeParse;
307
368
  makeCall(phoneNumber: string, name?: string): void;
308
369
  get callerDropped(): any[];
309
370
  get filteredRecent(): any[];
@@ -342,7 +403,7 @@ declare class CallDetailsComponent {
342
403
  call: any;
343
404
  transcriptLines: TranscriptLine[];
344
405
  summaryText: string;
345
- customerSentiment: string;
406
+ customerBehavior: string;
346
407
  isTranscribing: boolean;
347
408
  transcriptionError: string;
348
409
  isTranscriptFullscreen: boolean;
@@ -355,7 +416,7 @@ declare class CallDetailsComponent {
355
416
  getTranscriptSpeaker(line: TranscriptLine): string;
356
417
  runTranscription(): Promise<void>;
357
418
  private normalizeTranscript;
358
- getSentimentEmoji(): string;
419
+ getBehaviorEmoji(): string;
359
420
  private parseSpeakerLine;
360
421
  toggleTranscriptFullscreen(): void;
361
422
  private getRecordingFilename;
@@ -447,6 +508,7 @@ declare class SettingsComponent implements OnInit, OnDestroy {
447
508
  logout: EventEmitter<void>;
448
509
  audioInputs: MediaDeviceInfo[];
449
510
  audioOutputs: MediaDeviceInfo[];
511
+ readonly widgetVersion: "0.2.3";
450
512
  ngOnInit(): void;
451
513
  onLogout(): void;
452
514
  onToggleDarkMode(): void;
@@ -490,27 +552,26 @@ interface RecordingSession {
490
552
  recorder?: MediaRecorder | null;
491
553
  metadata: CallMetadata;
492
554
  stopping: boolean;
493
- chunkIndex: number;
494
- chunkTimer?: number;
555
+ chunks: Blob[];
556
+ mimeType: string;
557
+ uploaded: boolean;
495
558
  }
496
559
  declare class RecordingManagerService {
497
560
  private http;
498
561
  private sessions;
499
562
  private readonly MIME_TYPE_PREFERRED;
500
563
  private readonly MIME_TYPE_FALLBACK;
501
- private readonly CHUNK_DURATION_MS;
564
+ private readonly TIMESLICE_MS;
502
565
  private readonly AUDIO_CONTEXT_CLOSE_DELAY_MS;
503
- private readonly CALL_HISTORY_API_URL;
566
+ private readonly RECORDING_API_URL;
504
567
  constructor(http: HttpClient);
505
568
  startRecording(localMediaStream: MediaStream, remoteMediaStream: MediaStream, metadata: CallMetadata): RecordingSession | undefined;
506
569
  getSession(callId: string): RecordingSession | undefined;
507
570
  stopRecording(callId: string): void;
508
- private startNextChunk;
571
+ private finalizeRecording;
509
572
  private uploadCallRecording;
510
573
  private convertBlobToBase64;
511
574
  private generateFilename;
512
- private generateChunkFilename;
513
- private normalizePhoneNumberForUpload;
514
575
  static ɵfac: i0.ɵɵFactoryDeclaration<RecordingManagerService, never>;
515
576
  static ɵprov: i0.ɵɵInjectableDeclaration<RecordingManagerService>;
516
577
  }
@@ -530,18 +591,19 @@ declare class TranscriptionStreamService implements OnDestroy {
530
591
  private readonly BUFFER_SIZE;
531
592
  private readonly SILENCE_RMS_THRESHOLD;
532
593
  private readonly VOICE_RMS_THRESHOLD;
594
+ private readonly CUSTOMER_SILENCE_RMS_THRESHOLD;
595
+ private readonly CUSTOMER_VOICE_RMS_THRESHOLD;
533
596
  private readonly NOISE_FLOOR_MULTIPLIER;
534
597
  private readonly NOISE_FLOOR_SMOOTHING;
535
- private readonly CHUNK_INTERVAL_MS;
598
+ private readonly MIN_VOICE_FRAMES;
536
599
  private readonly CUSTOM_WS_URL;
537
- private readonly CUSTOM_WS_MIME_TYPE;
538
- private readonly LANGUAGE_CODE;
539
- private readonly ALT_LANGUAGE_CODES;
600
+ private readonly LANGUAGE;
540
601
  private readonly TRANSCRIPTION_MODEL;
541
602
  constructor();
542
603
  ngOnDestroy(): void;
543
604
  startSession(callId: string, localStream: MediaStream, remoteStream: MediaStream, allowSendBinary?: boolean): Promise<void>;
544
605
  stopSession(callId: string): void;
606
+ destroyAll(): void;
545
607
  enableBinary(callId: string): void;
546
608
  setStreamMuted(callId: string, label: 'agent' | 'customer', muted: boolean): void;
547
609
  private mixToMono;
@@ -549,8 +611,6 @@ declare class TranscriptionStreamService implements OnDestroy {
549
611
  private encodePcm16;
550
612
  private downsampleBuffer;
551
613
  private queueAudio;
552
- private flushPendingAudio;
553
- private mergeChunks;
554
614
  private handleTranscriptPayload;
555
615
  private parseSpeakerLine;
556
616
  private createStreamSession;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snugdesk/avaya-ipo-widget",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Snugdesk - Avaya IPO widget for Angular",
5
5
  "peerDependencies": {
6
6
  "@angular/animations": ">=19.0.0",