@snugdesk/avaya-ipo-widget 0.2.3 → 0.2.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.
@@ -23,29 +23,35 @@ import { PhoneNumberUtil, PhoneNumberFormat } from 'google-libphonenumber';
23
23
  const APP_CONFIG = {
24
24
  // Widget build version — shown in the footer so you can confirm which build is loaded.
25
25
  // Keep this in sync with the "version" field in projects/avaya-ipo-widget/package.json.
26
- WIDGET_VERSION: '0.2.3',
26
+ WIDGET_VERSION: '0.2.4',
27
27
  ASSET_CDN_BASE_URL: 'https://d39qei1249155h.cloudfront.net/avaya-ipo-widget',
28
28
  AWL_SDK_URL: 'https://d39qei1249155h.cloudfront.net/avaya-ipo-widget/assets/js/awl.min.js',
29
29
  AGENT_STATUS_API_URL: 'https://v2xla9n0t6.execute-api.us-west-2.amazonaws.com/dev',
30
- CALL_HISTORY_API_URL: 'https://ktgxyy2x2h.execute-api.us-west-2.amazonaws.com/avayaCallHistory',
31
30
  // Snugdesk backend (SnugdeskApiV1) endpoint that upserts a call as a real Interaction so it shows
32
31
  // up in the same call history as every other channel in snugdesk-app.
33
32
  INTERACTION_CALL_LOG_API_URL: 'https://api.snugdesk.com/avaya-ipo/call-log',
34
33
  // Stores the full call recording in the backend and links it to the Interaction, triggering the
35
34
  // server-side Gemini transcription/summary pipeline.
36
35
  INTERACTION_CALL_RECORDING_API_URL: 'https://api.snugdesk.com/avaya-ipo/call-recording',
37
- CALL_SESSION_WS_URL: 'wss://hymtqh7k82.execute-api.us-west-2.amazonaws.com/callSession',
36
+ // How recordings reach the backend:
37
+ // 'complete' — one upload at call end via INTERACTION_CALL_RECORDING_API_URL (original flow)
38
+ // 'chunked' — stream 5s chunks over RECORDING_SOCKET_WS_URL during the call; the backend
39
+ // (avaya-ipo-recording-socket Lambda) stitches on every socket close, so a dead tab
40
+ // loses at most the last few seconds. Overridable per-embed via the
41
+ // [recordingUploadMode] input on the widget tag.
42
+ RECORDING_UPLOAD_MODE: 'complete',
43
+ // API Gateway WebSocket fronting the avaya-ipo-recording-socket Lambda ($connect/$disconnect/$default).
44
+ // From the snugdesk-backend-api stack output: AvayaIpoRecordingSocketUrl.
45
+ RECORDING_SOCKET_WS_URL: 'wss://lmarx4fzy3.execute-api.ap-south-1.amazonaws.com/production',
46
+ // Live in-call transcription (UI kept; backend integration planned — dev endpoint for now).
38
47
  TRANSCRIPTION_WS_URL: 'ws://localhost:3100/live-stt/stream',
39
48
  TRANSCRIPTION_LANGUAGE: 'auto',
40
49
  TRANSCRIPTION_MODEL: 'nova-2',
41
- POSTCALL_TRANSCRIBE_API_URL: 'https://nqfo27pht1.execute-api.us-east-1.amazonaws.com/Stage/ai-transcription/post-call-analysis',
42
50
  COUNTRY_ENDPOINT: 'https://d39qei1249155h.cloudfront.net/avaya-ipo-widget/assets/metadata/countries.json',
43
51
  PHONE_NUMBER_LOOKUP_BASE: 'https://api.snugdesk.com/phone-numbers',
44
52
  PHONE_NUMBER_HLR_BASE: 'https://api.snugdesk.com/phone-numbers/hlr',
45
53
  PHONE_LOOKUP_COUNTRY_CODE: '91',
46
- ENTITY_SEARCH_BASE: 'https://search.snugdesk.com/entities',
47
54
  OPENSEARCH_ENTITIES_URL: 'https://api.snugdesk.com/opensearch/entities',
48
- PUSH_API_BASE: 'https://<your-api-id>.execute-api.<region>.amazonaws.com',
49
55
  DIAL_OUT_PREFIX: '0',
50
56
  };
51
57
  const assetUrl = (path) => {
@@ -214,14 +220,41 @@ class AvayaIPOService {
214
220
  this.ringAudio.loop = true;
215
221
  this.ringAudio.currentTime = 0;
216
222
  this.ringAudio.play().catch(() => {
217
- // Ignore autoplay failures.
223
+ // Autoplay blocked — the page has had no user gesture yet (common with auto-login).
224
+ // Ring as soon as the user interacts, if the call is still ringing by then.
225
+ console.warn('[avaya-ipo] Ring tone blocked by autoplay policy; will ring on first user gesture');
226
+ this.armRingRetryOnGesture();
218
227
  });
219
228
  }
220
229
  catch {
221
230
  // ignore play errors
222
231
  }
223
232
  }
233
+ ringRetryHandler = null;
234
+ armRingRetryOnGesture() {
235
+ if (this.ringRetryHandler || typeof document === 'undefined') {
236
+ return;
237
+ }
238
+ const handler = () => {
239
+ this.disarmRingRetry();
240
+ // Only ring if the incoming call is still pending.
241
+ if (this.lastIncomingCall && this.ringAudio) {
242
+ this.ringAudio.play().catch(() => { });
243
+ }
244
+ };
245
+ this.ringRetryHandler = handler;
246
+ ['click', 'keydown', 'touchstart'].forEach((type) => document.addEventListener(type, handler, { once: true, capture: true }));
247
+ }
248
+ disarmRingRetry() {
249
+ if (!this.ringRetryHandler || typeof document === 'undefined') {
250
+ return;
251
+ }
252
+ const handler = this.ringRetryHandler;
253
+ this.ringRetryHandler = null;
254
+ ['click', 'keydown', 'touchstart'].forEach((type) => document.removeEventListener(type, handler, { capture: true }));
255
+ }
224
256
  stopRingTone() {
257
+ this.disarmRingRetry();
225
258
  if (!this.ringAudio) {
226
259
  return;
227
260
  }
@@ -1075,6 +1108,7 @@ class EntitiesSearchService {
1075
1108
  http;
1076
1109
  authenticationService;
1077
1110
  nameCache = new Map();
1111
+ entityIdCache = new Map();
1078
1112
  constructor(http, authenticationService) {
1079
1113
  this.http = http;
1080
1114
  this.authenticationService = authenticationService;
@@ -1098,20 +1132,7 @@ class EntitiesSearchService {
1098
1132
  ],
1099
1133
  query: {
1100
1134
  bool: {
1101
- filter: [
1102
- { term: { is_blocked: false } },
1103
- { term: { tenant_id: tenantId } },
1104
- {
1105
- bool: {
1106
- should: [
1107
- { exists: { field: 'phone_numbers' } },
1108
- { exists: { field: 'phone' } },
1109
- { exists: { field: 'normalizedPhoneNumber' } },
1110
- ],
1111
- minimum_should_match: 1,
1112
- },
1113
- },
1114
- ],
1135
+ filter: [{ term: { tenant_id: tenantId } }],
1115
1136
  },
1116
1137
  },
1117
1138
  };
@@ -1229,19 +1250,28 @@ class EntitiesSearchService {
1229
1250
  return this.nameCache.get(key) || null;
1230
1251
  }
1231
1252
  async lookupNameByPhone(tenantId, phoneNumber, size = 25) {
1232
- const cached = this.getCachedName(tenantId, phoneNumber);
1233
- if (cached) {
1234
- return cached;
1253
+ return (await this.lookupEntityByPhone(tenantId, phoneNumber, size)).name;
1254
+ }
1255
+ /** Resolve the entity (id + name) matching a phone number; both are cached per tenant+number. */
1256
+ async lookupEntityByPhone(tenantId, phoneNumber, size = 25) {
1257
+ const key = this.cacheKey(tenantId, phoneNumber);
1258
+ const cachedName = this.nameCache.get(key) || null;
1259
+ const cachedId = this.entityIdCache.get(key) || null;
1260
+ if (cachedName || cachedId) {
1261
+ return { id: cachedId, name: cachedName };
1235
1262
  }
1236
1263
  const res = await this.searchByPhone(tenantId, phoneNumber, size);
1237
1264
  const hit = res?.hits?.hits?.[0];
1238
- const name = hit?._source?.name;
1239
- const trimmed = typeof name === 'string' ? name.trim() : '';
1240
- if (trimmed) {
1241
- this.nameCache.set(this.cacheKey(tenantId, phoneNumber), trimmed);
1242
- return trimmed;
1265
+ const source = hit?._source || {};
1266
+ const name = typeof source.name === 'string' ? source.name.trim() : '';
1267
+ const id = (source.id || hit?._id || '').toString().trim();
1268
+ if (name) {
1269
+ this.nameCache.set(key, name);
1243
1270
  }
1244
- return null;
1271
+ if (id) {
1272
+ this.entityIdCache.set(key, id);
1273
+ }
1274
+ return { id: id || null, name: name || null };
1245
1275
  }
1246
1276
  postEntities(body) {
1247
1277
  const token = this.authenticationService.getAuthSessionToken();
@@ -1266,19 +1296,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
1266
1296
  args: [{ providedIn: 'root' }]
1267
1297
  }], ctorParameters: () => [{ type: i1.HttpClient }, { type: AuthenticationService }] });
1268
1298
 
1299
+ /**
1300
+ * Shows the same AI call analysis as snugdesk-app's conversation view: the data is read
1301
+ * from the Interaction record (metadata.aiAnalysis), which the server-side pipeline fills
1302
+ * after the recording is uploaded — no client-side transcription is run here.
1303
+ */
1269
1304
  class CallDetailsComponent {
1270
- http;
1305
+ appSync;
1271
1306
  call;
1272
1307
  transcriptLines = [];
1308
+ conversationSummary = [];
1309
+ nextActions = [];
1310
+ keyConcerns = [];
1311
+ callType = '';
1312
+ customerIntent = '';
1313
+ customerSentiment = '';
1314
+ aiConfidenceScore = null;
1273
1315
  summaryText = '';
1274
- customerBehavior = '';
1275
- isTranscribing = false;
1276
- transcriptionError = '';
1316
+ aiProcessingStatus = '';
1317
+ hasAnalysis = false;
1318
+ isRefreshing = false;
1319
+ refreshError = '';
1277
1320
  isTranscriptFullscreen = false;
1278
- hasGeneratedTranscript = false;
1279
- ANALYZE_CALL_API = APP_CONFIG.POSTCALL_TRANSCRIBE_API_URL;
1280
- constructor(http) {
1281
- this.http = http;
1321
+ GET_INTERACTION_QUERY = `query GetInteraction($id: ID!) {
1322
+ getInteraction(id: $id) {
1323
+ id
1324
+ metadata
1325
+ summary
1326
+ aiProcessingStatus
1327
+ recording { location }
1328
+ }
1329
+ }`;
1330
+ constructor(appSync) {
1331
+ this.appSync = appSync;
1332
+ }
1333
+ ngOnChanges(changes) {
1334
+ if (changes['call']) {
1335
+ this.parseAnalysisFromCall();
1336
+ }
1337
+ }
1338
+ get isAnalysisPending() {
1339
+ return ['PENDING', 'IN_PROGRESS'].includes((this.aiProcessingStatus || '').toUpperCase());
1282
1340
  }
1283
1341
  getBadge() {
1284
1342
  const base = this.call?.phoneNumber?.country?.code ||
@@ -1304,38 +1362,107 @@ class CallDetailsComponent {
1304
1362
  const normalized = raw.toLowerCase();
1305
1363
  if (normalized === 'customer') {
1306
1364
  const name = this.getDisplayName();
1307
- return name && name !== 'Unknown' ? name : 'Unknown';
1365
+ return name && name !== 'Unknown' ? name : 'Customer';
1308
1366
  }
1309
1367
  if (normalized === 'agent') {
1310
1368
  return 'Agent';
1311
1369
  }
1312
1370
  return raw || 'Unknown';
1313
1371
  }
1314
- async runTranscription() {
1315
- if (!this.call?.fullCallRecordingUrl || this.isTranscribing) {
1372
+ getSentimentEmoji() {
1373
+ const value = (this.customerSentiment || '').toLowerCase();
1374
+ if (value.includes('angry') || value.includes('frustrat'))
1375
+ return '😠';
1376
+ if (value.includes('calm'))
1377
+ return '😌';
1378
+ if (value.includes('happy') || value.includes('positive') || value.includes('satisf'))
1379
+ return '😄';
1380
+ if (value.includes('confus'))
1381
+ return '😕';
1382
+ if (value.includes('neutral'))
1383
+ return '😐';
1384
+ if (value.includes('negative') || value.includes('upset'))
1385
+ return '🙁';
1386
+ return '';
1387
+ }
1388
+ /** Re-read the Interaction record (the AI pipeline fills metadata.aiAnalysis asynchronously). */
1389
+ async refreshAnalysis() {
1390
+ const id = this.call?.id;
1391
+ if (!id || this.isRefreshing) {
1316
1392
  return;
1317
1393
  }
1318
- this.isTranscribing = true;
1319
- this.transcriptionError = '';
1394
+ this.isRefreshing = true;
1395
+ this.refreshError = '';
1320
1396
  try {
1321
- const recordingBlob = await lastValueFrom(this.http.get(this.call.fullCallRecordingUrl, { responseType: 'blob' }));
1322
- const formData = new FormData();
1323
- formData.append('file', recordingBlob, this.getRecordingFilename());
1324
- const res = await lastValueFrom(this.http.post(this.ANALYZE_CALL_API, formData));
1325
- this.transcriptLines = this.normalizeTranscript(res?.transcript);
1326
- this.summaryText = typeof res?.summary === 'string' ? res.summary : '';
1327
- this.customerBehavior =
1328
- typeof res?.customerBehavior === 'string' ? res.customerBehavior : '';
1329
- this.hasGeneratedTranscript = true;
1397
+ const res = await this.appSync.query(this.GET_INTERACTION_QUERY, { id });
1398
+ const interaction = res?.data?.getInteraction;
1399
+ if (interaction) {
1400
+ this.call = {
1401
+ ...this.call,
1402
+ summary: interaction.summary || this.call?.summary || '',
1403
+ metadata: this.safeParse(interaction.metadata) || this.call?.metadata,
1404
+ aiProcessingStatus: interaction.aiProcessingStatus || '',
1405
+ fullCallRecordingUrl: interaction.recording?.location || this.call?.fullCallRecordingUrl || '',
1406
+ };
1407
+ this.parseAnalysisFromCall();
1408
+ }
1330
1409
  }
1331
1410
  catch (err) {
1332
- console.error('[CallDetails] Transcription failed', err);
1333
- this.transcriptionError = 'Failed to analyze call. Please try again.';
1411
+ console.error('[CallDetails] Failed to refresh interaction', err);
1412
+ this.refreshError = 'Failed to refresh analysis. Please try again.';
1334
1413
  }
1335
1414
  finally {
1336
- this.isTranscribing = false;
1415
+ this.isRefreshing = false;
1337
1416
  }
1338
1417
  }
1418
+ toggleTranscriptFullscreen() {
1419
+ this.isTranscriptFullscreen = !this.isTranscriptFullscreen;
1420
+ }
1421
+ /** Pull the structured AI analysis off the interaction's metadata — same shape snugdesk-app reads. */
1422
+ parseAnalysisFromCall() {
1423
+ const metadata = this.safeParse(this.call?.metadata) || {};
1424
+ const ai = metadata.aiAnalysis || {};
1425
+ this.summaryText = this.normalizeText(this.call?.summary);
1426
+ this.aiProcessingStatus = (this.call?.aiProcessingStatus || '').toString();
1427
+ this.conversationSummary = this.normalizeBulletItems(ai.conversationSummary);
1428
+ this.nextActions = this.normalizeBulletItems(ai.nextAction);
1429
+ this.keyConcerns = this.normalizeBulletItems(ai.keyConcerns);
1430
+ this.callType = this.normalizeText(ai.callType);
1431
+ this.customerIntent = this.normalizeText(ai.customerIntent);
1432
+ this.customerSentiment = this.normalizeText(ai.customerSentiment);
1433
+ const score = Number(ai.aiConfidenceScore);
1434
+ this.aiConfidenceScore = Number.isFinite(score) ? Math.round(score) : null;
1435
+ this.transcriptLines = this.normalizeTranscript(ai.transcript);
1436
+ this.hasAnalysis =
1437
+ this.transcriptLines.length > 0 ||
1438
+ this.conversationSummary.length > 0 ||
1439
+ !!this.callType ||
1440
+ !!this.customerIntent ||
1441
+ !!this.customerSentiment ||
1442
+ this.keyConcerns.length > 0 ||
1443
+ this.nextActions.length > 0;
1444
+ }
1445
+ normalizeText(value) {
1446
+ if (value === null || value === undefined)
1447
+ return '';
1448
+ return value.toString().trim();
1449
+ }
1450
+ normalizeBulletItems(input) {
1451
+ if (!input)
1452
+ return [];
1453
+ if (Array.isArray(input)) {
1454
+ return input
1455
+ .map((item) => typeof item === 'string' ? item.trim() : this.normalizeText(item?.text ?? item))
1456
+ .filter(Boolean);
1457
+ }
1458
+ if (typeof input === 'string') {
1459
+ return input
1460
+ .split(/\r?\n|•/)
1461
+ .map((line) => line.replace(/^\s*[-*\d.)]+\s*/, '').trim())
1462
+ .filter(Boolean);
1463
+ }
1464
+ return [];
1465
+ }
1339
1466
  normalizeTranscript(input) {
1340
1467
  if (!input) {
1341
1468
  return [];
@@ -1345,44 +1472,26 @@ class CallDetailsComponent {
1345
1472
  .split(/\r?\n/)
1346
1473
  .map((line) => line.trim())
1347
1474
  .filter(Boolean)
1348
- .map((line) => {
1349
- const parsed = this.parseSpeakerLine(line);
1350
- return { speaker: parsed.speaker, text: parsed.text };
1351
- });
1475
+ .map((line) => this.parseSpeakerLine(line));
1352
1476
  }
1353
1477
  if (Array.isArray(input)) {
1354
1478
  return input
1355
1479
  .map((entry) => {
1356
1480
  if (typeof entry === 'string') {
1357
- const parsed = this.parseSpeakerLine(entry);
1358
- return { speaker: parsed.speaker, text: parsed.text };
1481
+ return this.parseSpeakerLine(entry);
1359
1482
  }
1360
1483
  if (entry && typeof entry === 'object') {
1361
1484
  return {
1362
- speaker: entry.speaker,
1363
- text: entry.text,
1485
+ speaker: entry.speaker || entry.role,
1486
+ text: entry.text ?? entry.message ?? entry.utterance ?? entry.content,
1364
1487
  };
1365
1488
  }
1366
1489
  return null;
1367
1490
  })
1368
- .filter(Boolean);
1491
+ .filter((line) => !!line && !!line.text);
1369
1492
  }
1370
1493
  return [];
1371
1494
  }
1372
- getBehaviorEmoji() {
1373
- const value = (this.customerBehavior || '').toLowerCase();
1374
- if (value.includes('angry'))
1375
- return '😠';
1376
- if (value.includes('calm'))
1377
- return '😌';
1378
- if (value.includes('happy'))
1379
- return '😄';
1380
- if (value.includes('confused'))
1381
- return '😕';
1382
- if (value.includes('neutral'))
1383
- return '😐';
1384
- return '';
1385
- }
1386
1495
  parseSpeakerLine(line) {
1387
1496
  const match = line.match(/^\s*(agent|customer)\s*:\s*(.*)$/i);
1388
1497
  if (match) {
@@ -1390,36 +1499,25 @@ class CallDetailsComponent {
1390
1499
  }
1391
1500
  return { text: line.trim() };
1392
1501
  }
1393
- toggleTranscriptFullscreen() {
1394
- this.isTranscriptFullscreen = !this.isTranscriptFullscreen;
1395
- }
1396
- getRecordingFilename() {
1397
- const url = this.call?.fullCallRecordingUrl;
1398
- if (typeof url === 'string') {
1399
- try {
1400
- const parsed = new URL(url);
1401
- const name = parsed.pathname.split('/').pop();
1402
- if (name) {
1403
- return name;
1404
- }
1405
- }
1406
- catch {
1407
- const parts = url.split('/').filter(Boolean);
1408
- const name = parts[parts.length - 1];
1409
- if (name) {
1410
- return name;
1411
- }
1412
- }
1502
+ safeParse(value) {
1503
+ if (!value)
1504
+ return null;
1505
+ if (typeof value === 'object')
1506
+ return value;
1507
+ try {
1508
+ return JSON.parse(value);
1509
+ }
1510
+ catch {
1511
+ return null;
1413
1512
  }
1414
- return 'call-recording.wav';
1415
1513
  }
1416
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CallDetailsComponent, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
1417
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CallDetailsComponent, isStandalone: false, selector: "app-call-details", inputs: { call: "call" }, ngImport: i0, template: "<div class=\"avaya-ipo-call-profile\">\n <div class=\"avaya-ipo-profile-header\">\n <div class=\"avaya-ipo-avatar\">\n <svg viewBox=\"0 0 448 512\" width=\"28\" height=\"28\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z\" />\n </svg>\n </div>\n <div class=\"avaya-ipo-profile-info\">\n <div class=\"avaya-ipo-primary-number\">\n {{ getDisplayName() }}\n </div>\n <div class=\"avaya-ipo-secondary-info\">\n {{ getPhone() || 'Unknown' }}\n </div>\n <div class=\"avaya-ipo-meta-line\">\n <span>{{ call?.timestamp | date : 'medium' }}</span>\n <span class=\"avaya-ipo-divider\">|</span>\n @if (call?.disconnectSide === 'CALLER' && (call?.duration ?? 0) === 0) {\n <span class=\"avaya-ipo-divider\">|</span>\n <span class=\"avaya-ipo-missed-badge\">\n <svg viewBox=\"0 0 640 512\" width=\"12px\" aria-hidden=\"true\" style=\"fill: currentColor;\">\n <path d=\"M232 0c9.7 0 18.5 5.8 22.2 14.8s1.7 19.3-5.2 26.2l-39 39 58.7 58.7C282.3 152.4 300.8 160 320 160s37.7-7.6 51.3-21.3L503 7c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L405.3 172.7C382.6 195.3 352 208 320 208s-62.6-12.7-85.3-35.3L176 113.9l-39 39c-6.9 6.9-17.2 8.9-26.2 5.2s-14.8-12.5-14.8-22.2L96 24c0-13.3 10.7-24 24-24L232 0zM51.4 489.9l-35.4-62c-9.7-16.9-8.3-38.1 5.5-51.7C72.6 325.9 178.1 256 320 256s247.4 69.9 298.5 120.2c13.9 13.6 15.2 34.8 5.5 51.7l-35.4 62c-7.4 12.9-22.7 19.1-37 14.8L438.8 470.8c-13.5-4.1-22.8-16.5-22.8-30.6l0-56.2c-62.3-20.8-129.7-20.8-192 0l0 56.2c0 14.1-9.3 26.6-22.8 30.6L88.4 504.7c-14.3 4.3-29.6-1.8-37-14.8z\" />\n </svg>\n <span>Missed Call</span>\n </span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-summary-card\">\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Duration</div>\n <div class=\"avaya-ipo-value\">{{ call?.duration ?? 0 }}s</div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Disconnect Side</div>\n <div class=\"avaya-ipo-value\">{{ call?.disconnectSide || 'N/A' }}</div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Country</div>\n <div class=\"avaya-ipo-value\">\n {{\n call?.phoneNumber?.country?.nameEn ||\n call?.phoneNumber?.lookupPhoneNumber?.country ||\n 'N/A'\n }}\n </div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Provider</div>\n <div class=\"avaya-ipo-value\">\n {{\n call?.phoneNumber?.lookupPhoneNumber?.['prefix-network'] ||\n call?.phoneNumber?.lookupPhoneNumber?.provider ||\n 'N/A'\n }}\n </div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-transcription-card\" [class.avaya-ipo-fullscreen]=\"isTranscriptFullscreen\">\n <div class=\"avaya-ipo-detail-title\">Call Recording</div>\n <audio\n *ngIf=\"call?.fullCallRecordingUrl; else noRecording\"\n controls\n [src]=\"call?.fullCallRecordingUrl\"\n ></audio>\n <ng-template #noRecording>\n @if ((call?.duration ?? 0) > 0) {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Processing</button>\n } @else {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Recording not available</button>\n }\n </ng-template>\n </div>\n\n @if (!hasGeneratedTranscript) {\n <div class=\"avaya-ipo-transcription-actions avaya-ipo-outside\">\n <button class=\"avaya-ipo-action-btn\" type=\"button\" [disabled]=\"isTranscribing\" (click)=\"runTranscription()\">\n <span class=\"avaya-ipo-btn-content\">\n @if (isTranscribing) {\n <span class=\"avaya-ipo-btn-spinner\" aria-hidden=\"true\"></span>\n }\n <span>{{ isTranscribing ? 'Generating...' : 'Run AI Call Analysis' }}</span>\n </span>\n </button>\n @if (transcriptionError) {\n <div class=\"avaya-ipo-status-error\">{{ transcriptionError }}</div>\n }\n </div>\n }\n\n <div class=\"avaya-ipo-detail-card\">\n <div class=\"avaya-ipo-detail-title\">Call Summary</div>\n @if (customerBehavior) {\n <div class=\"avaya-ipo-summary-sentiment\">\n Customer Behavior: {{ customerBehavior }}\n @if (getBehaviorEmoji()) {\n <span class=\"avaya-ipo-summary-emoji\">{{ getBehaviorEmoji() }}</span>\n }\n </div>\n }\n @if (summaryText) {\n <div class=\"avaya-ipo-summary-text\">{{ summaryText }}</div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No summary available.</div>\n }\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-transcription-card\" [class.avaya-ipo-fullscreen]=\"isTranscriptFullscreen\">\n <div class=\"avaya-ipo-detail-title-row\">\n <div class=\"avaya-ipo-detail-title\">AI Call Transcription</div>\n @if (transcriptLines?.length) {\n <button\n class=\"avaya-ipo-chat-thread-btn\"\n type=\"button\"\n (click)=\"toggleTranscriptFullscreen()\"\n [attr.aria-label]=\"isTranscriptFullscreen ? 'Exit full screen' : 'Enter full screen'\"\n >\n @if (isTranscriptFullscreen) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"\n />\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"\n />\n </svg>\n }\n </button>\n }\n </div>\n @if (call?.fullCallRecordingUrl) {\n @if (transcriptLines?.length) {\n <div class=\"avaya-ipo-chat-thread\">\n @for (line of transcriptLines; track $index) {\n <div class=\"avaya-ipo-chat-bubble\" [class.avaya-ipo-agent]=\"(line.speaker || '').toLowerCase() === 'agent'\">\n <div class=\"avaya-ipo-chat-speaker\">{{ getTranscriptSpeaker(line) }}</div>\n <div class=\"avaya-ipo-chat-text\">{{ line.text || '' }}</div>\n </div>\n }\n </div>\n } @else if (isTranscribing) {\n <div class=\"avaya-ipo-transcription-skeleton\">\n @for (item of [1,2,3,4,5]; track item) {\n <div class=\"avaya-ipo-transcription-skeleton-line\"></div>\n }\n </div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No transcription available.</div>\n }\n\n } @else {\n <div class=\"avaya-ipo-placeholder\">No recording available for transcription.</div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;box-sizing:border-box}.avaya-ipo-call-profile{display:flex;flex-direction:column;gap:14px;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;color:var(--sd-text, #333)}.avaya-ipo-profile-header{display:flex;gap:12px;align-items:center;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-avatar{width:52px;height:52px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-avatar, #eceff3);display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;color:var(--sd-text, #333)}.avaya-ipo-profile-info{display:flex;flex-direction:column;gap:6px}.avaya-ipo-primary-number{font-size:16px;font-weight:800;color:var(--sd-text, #333)}.avaya-ipo-secondary-info{font-size:12px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-meta-line{display:flex;gap:6px;align-items:center;font-size:12px;color:var(--sd-text-muted, #5f6368);flex-wrap:wrap}.avaya-ipo-meta-line .avaya-ipo-divider{color:var(--sd-text-subtle, #9ca3af)}.avaya-ipo-meta-line .avaya-ipo-dir.avaya-ipo-inbound{color:var(--sd-call-accept, #1aa251)}.avaya-ipo-meta-line .avaya-ipo-dir.avaya-ipo-outbound{color:var(--sd-text-muted, #5f6368)}.avaya-ipo-meta-line .avaya-ipo-missed-badge{color:var(--sd-call-end, #e5484d);font-weight:700}.avaya-ipo-detail-card{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-card, #fff);border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-summary-card{order:1}.avaya-ipo-transcription-card{order:2}.avaya-ipo-detail-card audio{width:100%}.avaya-ipo-disabled-btn{width:100%;border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface-muted, #f7f7f7);color:var(--sd-text-subtle, #9ca3af);padding:10px;border-radius:var(--sd-radius, 10px);font-weight:600;cursor:not-allowed}.avaya-ipo-detail-title{font-weight:800;color:var(--sd-text, #333);font-size:14px}.avaya-ipo-detail-title-row{display:flex;align-items:center;justify-content:space-between}.avaya-ipo-transcription-actions{display:flex;flex-direction:column;gap:8px}.avaya-ipo-transcription-actions.avaya-ipo-outside{padding:0 4px}.avaya-ipo-detail-card.avaya-ipo-is-inactive{opacity:.45;filter:grayscale(.2);pointer-events:none}.avaya-ipo-action-btn{border:none;background:var(--sd-accent, #ff6633);color:var(--sd-accent-contrast, #fff);padding:10px 14px;border-radius:var(--sd-radius, 10px);font-weight:700;cursor:pointer;transition:background .15s ease,box-shadow .15s ease}.avaya-ipo-btn-content{display:inline-flex;align-items:center;gap:8px}.avaya-ipo-btn-spinner{width:14px;height:14px;border-radius:var(--sd-radius-pill, 999px);border:2px solid color-mix(in srgb,var(--sd-accent-contrast, #fff) 35%,transparent);border-top-color:var(--sd-accent-contrast, #fff);animation:spin .8s linear infinite}.avaya-ipo-action-btn:hover:not(:disabled){background:var(--sd-accent-strong, #ff5805)}.avaya-ipo-action-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring, 0 0 0 3px rgba(255, 102, 51, .22))}.avaya-ipo-action-btn:disabled{background:var(--sd-surface-sunken, #e8e8e8);color:var(--sd-text-subtle, #9ca3af);cursor:not-allowed}.avaya-ipo-status-error{color:var(--sd-call-end, #e5484d);font-size:12px;font-weight:600}.avaya-ipo-transcription-skeleton{display:flex;flex-direction:column;gap:10px}.avaya-ipo-transcription-skeleton-line{height:10px;border-radius:var(--sd-radius-pill, 999px);background:linear-gradient(90deg,var(--sd-surface-sunken, #e8e8e8) 0%,var(--sd-surface-muted, #f7f7f7) 45%,var(--sd-surface-sunken, #e8e8e8) 100%);background-size:200% 100%;animation:skeleton-shine 1.2s ease-in-out infinite}.avaya-ipo-transcription-skeleton-line:nth-child(2){width:85%}.avaya-ipo-transcription-skeleton-line:nth-child(3){width:90%}.avaya-ipo-transcription-skeleton-line:nth-child(4){width:70%}.avaya-ipo-transcription-skeleton-line:nth-child(5){width:60%}.avaya-ipo-chat-thread{display:flex;flex-direction:column;gap:8px}.avaya-ipo-chat-thread-btn{border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface, #fff);color:var(--sd-text, #333);padding:6px;border-radius:var(--sd-radius-sm, 8px);font-weight:700;cursor:pointer;font-size:12px;width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;transition:background .15s ease,border-color .15s ease}.avaya-ipo-chat-thread-btn:hover{background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-chat-thread-btn svg{width:16px;height:16px}.avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:absolute;inset:0;background:var(--sd-surface, #fff);padding:16px;z-index:1000;animation:transcript-expand .25s ease;border-radius:0}:host-context(.avaya-ipo-mode-standalone) .avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:fixed}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-detail-title-row{position:sticky;top:0;background:var(--sd-surface, #fff);z-index:2}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-chat-thread{flex:1 1 auto;overflow-y:auto;padding-bottom:8px}.avaya-ipo-detail-card{transition:transform .25s ease,opacity .25s ease}.avaya-ipo-transcription-card:not(.avaya-ipo-fullscreen){animation:transcript-collapse .2s ease}.avaya-ipo-chat-bubble{align-self:flex-start;max-width:86%;background:var(--sd-surface-muted, #f7f7f7);border-radius:var(--sd-radius, 10px);padding:8px 10px;border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-chat-bubble.avaya-ipo-agent{align-self:flex-end;background:var(--sd-accent-soft, #fff1ea);border-color:color-mix(in srgb,var(--sd-accent, #ff6633) 35%,transparent)}.avaya-ipo-chat-speaker{font-size:11px;font-weight:700;color:var(--sd-text-muted, #5f6368);text-transform:capitalize;margin-bottom:4px}.avaya-ipo-chat-text,.avaya-ipo-summary-text{font-size:13px;color:var(--sd-text, #333);line-height:1.4}.avaya-ipo-summary-sentiment{font-size:12px;font-weight:700;color:var(--sd-text, #333);margin-bottom:6px}.avaya-ipo-summary-emoji{margin-left:6px;font-size:14px}.avaya-ipo-summary-grid,.avaya-ipo-qa-grid{display:grid;gap:8px}.avaya-ipo-summary-card,.avaya-ipo-qa-card{border:1px solid var(--sd-border, #e3e3e3);border-radius:var(--sd-radius, 10px);padding:10px;background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-summary-title,.avaya-ipo-qa-title{font-weight:700;color:var(--sd-text, #333);font-size:12px;margin-bottom:6px;text-transform:capitalize}.avaya-ipo-summary-text,.avaya-ipo-qa-answer{font-size:13px;color:var(--sd-text, #333);line-height:1.4}.avaya-ipo-qa-reason{margin-top:6px;font-size:12px;color:var(--sd-text-muted, #5f6368);line-height:1.4}.avaya-ipo-sentiment-score{color:var(--sd-text-muted, #5f6368);font-size:12px}@keyframes transcript-expand{0%{transform:scale(.98);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes transcript-collapse{0%{transform:scale(1.02);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes skeleton-shine{0%{background-position:200% 0}to{background-position:-200% 0}}.avaya-ipo-placeholder{font-size:13px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-detail-row{display:flex;justify-content:space-between;align-items:center}.avaya-ipo-label{font-weight:700;color:var(--sd-text-muted, #5f6368);font-size:13px}.avaya-ipo-value{color:var(--sd-text, #333);text-align:right;font-weight:600;font-size:13px}.avaya-ipo-value.avaya-ipo-mono{font-family:SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;color:var(--sd-text-muted, #5f6368)}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
1514
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CallDetailsComponent, deps: [{ token: i1$1.AppSyncHelperService }], target: i0.ɵɵFactoryTarget.Component });
1515
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CallDetailsComponent, isStandalone: false, selector: "app-call-details", inputs: { call: "call" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"avaya-ipo-call-profile\">\n <div class=\"avaya-ipo-profile-header\">\n <div class=\"avaya-ipo-avatar\">\n <svg viewBox=\"0 0 448 512\" width=\"28\" height=\"28\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z\" />\n </svg>\n </div>\n <div class=\"avaya-ipo-profile-info\">\n <div class=\"avaya-ipo-primary-number\">\n {{ getDisplayName() }}\n </div>\n <div class=\"avaya-ipo-secondary-info\">\n {{ getPhone() || 'Unknown' }}\n </div>\n <div class=\"avaya-ipo-meta-line\">\n <span>{{ call?.timestamp | date : 'medium' }}</span>\n <span class=\"avaya-ipo-divider\">|</span>\n @if (call?.disconnectSide === 'CALLER' && (call?.duration ?? 0) === 0) {\n <span class=\"avaya-ipo-divider\">|</span>\n <span class=\"avaya-ipo-missed-badge\">\n <svg viewBox=\"0 0 640 512\" width=\"12px\" aria-hidden=\"true\" style=\"fill: currentColor;\">\n <path d=\"M232 0c9.7 0 18.5 5.8 22.2 14.8s1.7 19.3-5.2 26.2l-39 39 58.7 58.7C282.3 152.4 300.8 160 320 160s37.7-7.6 51.3-21.3L503 7c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L405.3 172.7C382.6 195.3 352 208 320 208s-62.6-12.7-85.3-35.3L176 113.9l-39 39c-6.9 6.9-17.2 8.9-26.2 5.2s-14.8-12.5-14.8-22.2L96 24c0-13.3 10.7-24 24-24L232 0zM51.4 489.9l-35.4-62c-9.7-16.9-8.3-38.1 5.5-51.7C72.6 325.9 178.1 256 320 256s247.4 69.9 298.5 120.2c13.9 13.6 15.2 34.8 5.5 51.7l-35.4 62c-7.4 12.9-22.7 19.1-37 14.8L438.8 470.8c-13.5-4.1-22.8-16.5-22.8-30.6l0-56.2c-62.3-20.8-129.7-20.8-192 0l0 56.2c0 14.1-9.3 26.6-22.8 30.6L88.4 504.7c-14.3 4.3-29.6-1.8-37-14.8z\" />\n </svg>\n <span>Missed Call</span>\n </span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-summary-card\">\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Duration</div>\n <div class=\"avaya-ipo-value\">{{ call?.duration ?? 0 }}s</div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Disconnect Side</div>\n <div class=\"avaya-ipo-value\">{{ call?.disconnectSide || 'N/A' }}</div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card\">\n <div class=\"avaya-ipo-detail-title\">Call Recording</div>\n <audio\n *ngIf=\"call?.fullCallRecordingUrl; else noRecording\"\n controls\n [src]=\"call?.fullCallRecordingUrl\"\n ></audio>\n <ng-template #noRecording>\n @if ((call?.duration ?? 0) > 0) {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Processing</button>\n } @else {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Recording not available</button>\n }\n </ng-template>\n </div>\n\n <!-- AI Call Analysis \u2014 read from the Interaction record (metadata.aiAnalysis), like snugdesk-app -->\n <div class=\"avaya-ipo-detail-card\">\n <div class=\"avaya-ipo-detail-title-row\">\n <div class=\"avaya-ipo-detail-title\">AI Call Analysis</div>\n <button\n class=\"avaya-ipo-chat-thread-btn\"\n type=\"button\"\n (click)=\"refreshAnalysis()\"\n [disabled]=\"isRefreshing\"\n aria-label=\"Refresh analysis\"\n title=\"Refresh analysis\"\n >\n @if (isRefreshing) {\n <span class=\"avaya-ipo-btn-spinner\" aria-hidden=\"true\"></span>\n } @else {\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M17.65 6.35A7.96 7.96 0 0 0 12 4a8 8 0 1 0 7.73 10h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\" />\n </svg>\n }\n </button>\n </div>\n\n @if (hasAnalysis) {\n @if (aiConfidenceScore !== null) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">AI Confidence</div>\n <div class=\"avaya-ipo-value\">{{ aiConfidenceScore }}%</div>\n </div>\n }\n @if (callType) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Call Type</div>\n <div class=\"avaya-ipo-value\">{{ callType }}</div>\n </div>\n }\n @if (customerSentiment) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Sentiment</div>\n <div class=\"avaya-ipo-value\">\n {{ customerSentiment }}\n @if (getSentimentEmoji()) {\n <span class=\"avaya-ipo-summary-emoji\">{{ getSentimentEmoji() }}</span>\n }\n </div>\n </div>\n }\n @if (customerIntent) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Customer Intent</div>\n <div class=\"avaya-ipo-value\">{{ customerIntent }}</div>\n </div>\n }\n @if (conversationSummary.length) {\n <div class=\"avaya-ipo-analysis-section\">\n <div class=\"avaya-ipo-analysis-heading\">Conversation Summary</div>\n <ul class=\"avaya-ipo-analysis-list\">\n @for (item of conversationSummary; track $index) {\n <li>{{ item }}</li>\n }\n </ul>\n </div>\n }\n @if (keyConcerns.length) {\n <div class=\"avaya-ipo-analysis-section\">\n <div class=\"avaya-ipo-analysis-heading\">Key Concerns</div>\n <ul class=\"avaya-ipo-analysis-list\">\n @for (item of keyConcerns; track $index) {\n <li>{{ item }}</li>\n }\n </ul>\n </div>\n }\n @if (nextActions.length) {\n <div class=\"avaya-ipo-analysis-section\">\n <div class=\"avaya-ipo-analysis-heading\">Next Actions</div>\n <ul class=\"avaya-ipo-analysis-list\">\n @for (item of nextActions; track $index) {\n <li>{{ item }}</li>\n }\n </ul>\n </div>\n }\n } @else if (isAnalysisPending || isRefreshing) {\n <div class=\"avaya-ipo-transcription-skeleton\">\n @for (item of [1,2,3]; track item) {\n <div class=\"avaya-ipo-transcription-skeleton-line\"></div>\n }\n </div>\n <div class=\"avaya-ipo-placeholder\">AI analysis is being generated\u2026 use refresh to check again.</div>\n } @else if (summaryText) {\n <div class=\"avaya-ipo-summary-text\">{{ summaryText }}</div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No AI analysis available for this call yet.</div>\n }\n @if (refreshError) {\n <div class=\"avaya-ipo-status-error\">{{ refreshError }}</div>\n }\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-transcription-card\" [class.avaya-ipo-fullscreen]=\"isTranscriptFullscreen\">\n <div class=\"avaya-ipo-detail-title-row\">\n <div class=\"avaya-ipo-detail-title\">Transcript</div>\n @if (transcriptLines.length) {\n <button\n class=\"avaya-ipo-chat-thread-btn\"\n type=\"button\"\n (click)=\"toggleTranscriptFullscreen()\"\n [attr.aria-label]=\"isTranscriptFullscreen ? 'Exit full screen' : 'Enter full screen'\"\n >\n @if (isTranscriptFullscreen) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"\n />\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"\n />\n </svg>\n }\n </button>\n }\n </div>\n @if (transcriptLines.length) {\n <div class=\"avaya-ipo-chat-thread\">\n @for (line of transcriptLines; track $index) {\n <div class=\"avaya-ipo-chat-bubble\" [class.avaya-ipo-agent]=\"(line.speaker || '').toLowerCase() === 'agent'\">\n <div class=\"avaya-ipo-chat-speaker\">{{ getTranscriptSpeaker(line) }}</div>\n <div class=\"avaya-ipo-chat-text\">{{ line.text || '' }}</div>\n </div>\n }\n </div>\n } @else if (isAnalysisPending || isRefreshing) {\n <div class=\"avaya-ipo-transcription-skeleton\">\n @for (item of [1,2,3,4,5]; track item) {\n <div class=\"avaya-ipo-transcription-skeleton-line\"></div>\n }\n </div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No transcript available.</div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;box-sizing:border-box}.avaya-ipo-call-profile{display:flex;flex-direction:column;gap:14px;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;color:var(--sd-text, #333)}.avaya-ipo-profile-header{display:flex;gap:12px;align-items:center;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-avatar{width:52px;height:52px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-avatar, #eceff3);display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;color:var(--sd-text, #333)}.avaya-ipo-profile-info{display:flex;flex-direction:column;gap:6px}.avaya-ipo-primary-number{font-size:16px;font-weight:800;color:var(--sd-text, #333)}.avaya-ipo-secondary-info{font-size:12px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-meta-line{display:flex;gap:6px;align-items:center;font-size:12px;color:var(--sd-text-muted, #5f6368);flex-wrap:wrap}.avaya-ipo-meta-line .avaya-ipo-divider{color:var(--sd-text-subtle, #9ca3af)}.avaya-ipo-meta-line .avaya-ipo-missed-badge{color:var(--sd-call-end, #e5484d);font-weight:700}.avaya-ipo-detail-card{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-card, #fff);border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-detail-card audio{width:100%}.avaya-ipo-disabled-btn{width:100%;border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface-muted, #f7f7f7);color:var(--sd-text-subtle, #9ca3af);padding:10px;border-radius:var(--sd-radius, 10px);font-weight:600;cursor:not-allowed}.avaya-ipo-detail-title{font-weight:800;color:var(--sd-text, #333);font-size:14px}.avaya-ipo-detail-title-row{display:flex;align-items:center;justify-content:space-between}.avaya-ipo-btn-spinner{width:14px;height:14px;border-radius:var(--sd-radius-pill, 999px);border:2px solid color-mix(in srgb,var(--sd-accent-contrast, #fff) 35%,transparent);border-top-color:var(--sd-accent-contrast, #fff);animation:spin .8s linear infinite}.avaya-ipo-status-error{color:var(--sd-call-end, #e5484d);font-size:12px;font-weight:600}.avaya-ipo-transcription-skeleton{display:flex;flex-direction:column;gap:10px}.avaya-ipo-transcription-skeleton-line{height:10px;border-radius:var(--sd-radius-pill, 999px);background:linear-gradient(90deg,var(--sd-surface-sunken, #e8e8e8) 0%,var(--sd-surface-muted, #f7f7f7) 45%,var(--sd-surface-sunken, #e8e8e8) 100%);background-size:200% 100%;animation:skeleton-shine 1.2s ease-in-out infinite}.avaya-ipo-transcription-skeleton-line:nth-child(2){width:85%}.avaya-ipo-transcription-skeleton-line:nth-child(3){width:90%}.avaya-ipo-transcription-skeleton-line:nth-child(4){width:70%}.avaya-ipo-transcription-skeleton-line:nth-child(5){width:60%}.avaya-ipo-chat-thread{display:flex;flex-direction:column;gap:8px}.avaya-ipo-chat-thread-btn{border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface, #fff);color:var(--sd-text, #333);padding:6px;border-radius:var(--sd-radius-sm, 8px);font-weight:700;cursor:pointer;font-size:12px;width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;transition:background .15s ease,border-color .15s ease}.avaya-ipo-chat-thread-btn:hover{background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-chat-thread-btn svg{width:16px;height:16px}.avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:absolute;inset:0;background:var(--sd-surface, #fff);padding:16px;z-index:1000;animation:transcript-expand .25s ease;border-radius:0}:host-context(.avaya-ipo-mode-standalone) .avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:fixed}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-detail-title-row{position:sticky;top:0;background:var(--sd-surface, #fff);z-index:2}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-chat-thread{flex:1 1 auto;overflow-y:auto;padding-bottom:8px}.avaya-ipo-detail-card{transition:transform .25s ease,opacity .25s ease}.avaya-ipo-transcription-card:not(.avaya-ipo-fullscreen){animation:transcript-collapse .2s ease}.avaya-ipo-chat-bubble{align-self:flex-start;max-width:86%;background:var(--sd-surface-muted, #f7f7f7);border-radius:var(--sd-radius, 10px);padding:8px 10px;border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-chat-bubble.avaya-ipo-agent{align-self:flex-end;background:var(--sd-accent-soft, #fff1ea);border-color:color-mix(in srgb,var(--sd-accent, #ff6633) 35%,transparent)}.avaya-ipo-chat-speaker{font-size:11px;font-weight:700;color:var(--sd-text-muted, #5f6368);text-transform:capitalize;margin-bottom:4px}.avaya-ipo-chat-text,.avaya-ipo-summary-text{font-size:13px;color:var(--sd-text, #333);line-height:1.4}.avaya-ipo-summary-emoji{margin-left:6px;font-size:14px}.avaya-ipo-summary-card{border:1px solid var(--sd-border, #e3e3e3);border-radius:var(--sd-radius, 10px);padding:10px;background:var(--sd-surface-muted, #f7f7f7)}@keyframes transcript-expand{0%{transform:scale(.98);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes transcript-collapse{0%{transform:scale(1.02);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes skeleton-shine{0%{background-position:200% 0}to{background-position:-200% 0}}.avaya-ipo-placeholder{font-size:13px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-analysis-section{margin-top:10px}.avaya-ipo-analysis-heading{font-size:12px;font-weight:700;color:var(--sd-text-muted, #5f6368);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px}.avaya-ipo-analysis-list{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:4px}.avaya-ipo-analysis-list li{font-size:13px;color:var(--sd-text, #333);line-height:1.45}.avaya-ipo-detail-row{display:flex;justify-content:space-between;align-items:center}.avaya-ipo-label{font-weight:700;color:var(--sd-text-muted, #5f6368);font-size:13px}.avaya-ipo-value{color:var(--sd-text, #333);text-align:right;font-weight:600;font-size:13px}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
1418
1516
  }
1419
1517
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CallDetailsComponent, decorators: [{
1420
1518
  type: Component,
1421
- args: [{ selector: 'app-call-details', standalone: false, template: "<div class=\"avaya-ipo-call-profile\">\n <div class=\"avaya-ipo-profile-header\">\n <div class=\"avaya-ipo-avatar\">\n <svg viewBox=\"0 0 448 512\" width=\"28\" height=\"28\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z\" />\n </svg>\n </div>\n <div class=\"avaya-ipo-profile-info\">\n <div class=\"avaya-ipo-primary-number\">\n {{ getDisplayName() }}\n </div>\n <div class=\"avaya-ipo-secondary-info\">\n {{ getPhone() || 'Unknown' }}\n </div>\n <div class=\"avaya-ipo-meta-line\">\n <span>{{ call?.timestamp | date : 'medium' }}</span>\n <span class=\"avaya-ipo-divider\">|</span>\n @if (call?.disconnectSide === 'CALLER' && (call?.duration ?? 0) === 0) {\n <span class=\"avaya-ipo-divider\">|</span>\n <span class=\"avaya-ipo-missed-badge\">\n <svg viewBox=\"0 0 640 512\" width=\"12px\" aria-hidden=\"true\" style=\"fill: currentColor;\">\n <path d=\"M232 0c9.7 0 18.5 5.8 22.2 14.8s1.7 19.3-5.2 26.2l-39 39 58.7 58.7C282.3 152.4 300.8 160 320 160s37.7-7.6 51.3-21.3L503 7c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L405.3 172.7C382.6 195.3 352 208 320 208s-62.6-12.7-85.3-35.3L176 113.9l-39 39c-6.9 6.9-17.2 8.9-26.2 5.2s-14.8-12.5-14.8-22.2L96 24c0-13.3 10.7-24 24-24L232 0zM51.4 489.9l-35.4-62c-9.7-16.9-8.3-38.1 5.5-51.7C72.6 325.9 178.1 256 320 256s247.4 69.9 298.5 120.2c13.9 13.6 15.2 34.8 5.5 51.7l-35.4 62c-7.4 12.9-22.7 19.1-37 14.8L438.8 470.8c-13.5-4.1-22.8-16.5-22.8-30.6l0-56.2c-62.3-20.8-129.7-20.8-192 0l0 56.2c0 14.1-9.3 26.6-22.8 30.6L88.4 504.7c-14.3 4.3-29.6-1.8-37-14.8z\" />\n </svg>\n <span>Missed Call</span>\n </span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-summary-card\">\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Duration</div>\n <div class=\"avaya-ipo-value\">{{ call?.duration ?? 0 }}s</div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Disconnect Side</div>\n <div class=\"avaya-ipo-value\">{{ call?.disconnectSide || 'N/A' }}</div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Country</div>\n <div class=\"avaya-ipo-value\">\n {{\n call?.phoneNumber?.country?.nameEn ||\n call?.phoneNumber?.lookupPhoneNumber?.country ||\n 'N/A'\n }}\n </div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Provider</div>\n <div class=\"avaya-ipo-value\">\n {{\n call?.phoneNumber?.lookupPhoneNumber?.['prefix-network'] ||\n call?.phoneNumber?.lookupPhoneNumber?.provider ||\n 'N/A'\n }}\n </div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-transcription-card\" [class.avaya-ipo-fullscreen]=\"isTranscriptFullscreen\">\n <div class=\"avaya-ipo-detail-title\">Call Recording</div>\n <audio\n *ngIf=\"call?.fullCallRecordingUrl; else noRecording\"\n controls\n [src]=\"call?.fullCallRecordingUrl\"\n ></audio>\n <ng-template #noRecording>\n @if ((call?.duration ?? 0) > 0) {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Processing</button>\n } @else {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Recording not available</button>\n }\n </ng-template>\n </div>\n\n @if (!hasGeneratedTranscript) {\n <div class=\"avaya-ipo-transcription-actions avaya-ipo-outside\">\n <button class=\"avaya-ipo-action-btn\" type=\"button\" [disabled]=\"isTranscribing\" (click)=\"runTranscription()\">\n <span class=\"avaya-ipo-btn-content\">\n @if (isTranscribing) {\n <span class=\"avaya-ipo-btn-spinner\" aria-hidden=\"true\"></span>\n }\n <span>{{ isTranscribing ? 'Generating...' : 'Run AI Call Analysis' }}</span>\n </span>\n </button>\n @if (transcriptionError) {\n <div class=\"avaya-ipo-status-error\">{{ transcriptionError }}</div>\n }\n </div>\n }\n\n <div class=\"avaya-ipo-detail-card\">\n <div class=\"avaya-ipo-detail-title\">Call Summary</div>\n @if (customerBehavior) {\n <div class=\"avaya-ipo-summary-sentiment\">\n Customer Behavior: {{ customerBehavior }}\n @if (getBehaviorEmoji()) {\n <span class=\"avaya-ipo-summary-emoji\">{{ getBehaviorEmoji() }}</span>\n }\n </div>\n }\n @if (summaryText) {\n <div class=\"avaya-ipo-summary-text\">{{ summaryText }}</div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No summary available.</div>\n }\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-transcription-card\" [class.avaya-ipo-fullscreen]=\"isTranscriptFullscreen\">\n <div class=\"avaya-ipo-detail-title-row\">\n <div class=\"avaya-ipo-detail-title\">AI Call Transcription</div>\n @if (transcriptLines?.length) {\n <button\n class=\"avaya-ipo-chat-thread-btn\"\n type=\"button\"\n (click)=\"toggleTranscriptFullscreen()\"\n [attr.aria-label]=\"isTranscriptFullscreen ? 'Exit full screen' : 'Enter full screen'\"\n >\n @if (isTranscriptFullscreen) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"\n />\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"\n />\n </svg>\n }\n </button>\n }\n </div>\n @if (call?.fullCallRecordingUrl) {\n @if (transcriptLines?.length) {\n <div class=\"avaya-ipo-chat-thread\">\n @for (line of transcriptLines; track $index) {\n <div class=\"avaya-ipo-chat-bubble\" [class.avaya-ipo-agent]=\"(line.speaker || '').toLowerCase() === 'agent'\">\n <div class=\"avaya-ipo-chat-speaker\">{{ getTranscriptSpeaker(line) }}</div>\n <div class=\"avaya-ipo-chat-text\">{{ line.text || '' }}</div>\n </div>\n }\n </div>\n } @else if (isTranscribing) {\n <div class=\"avaya-ipo-transcription-skeleton\">\n @for (item of [1,2,3,4,5]; track item) {\n <div class=\"avaya-ipo-transcription-skeleton-line\"></div>\n }\n </div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No transcription available.</div>\n }\n\n } @else {\n <div class=\"avaya-ipo-placeholder\">No recording available for transcription.</div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;box-sizing:border-box}.avaya-ipo-call-profile{display:flex;flex-direction:column;gap:14px;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;color:var(--sd-text, #333)}.avaya-ipo-profile-header{display:flex;gap:12px;align-items:center;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-avatar{width:52px;height:52px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-avatar, #eceff3);display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;color:var(--sd-text, #333)}.avaya-ipo-profile-info{display:flex;flex-direction:column;gap:6px}.avaya-ipo-primary-number{font-size:16px;font-weight:800;color:var(--sd-text, #333)}.avaya-ipo-secondary-info{font-size:12px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-meta-line{display:flex;gap:6px;align-items:center;font-size:12px;color:var(--sd-text-muted, #5f6368);flex-wrap:wrap}.avaya-ipo-meta-line .avaya-ipo-divider{color:var(--sd-text-subtle, #9ca3af)}.avaya-ipo-meta-line .avaya-ipo-dir.avaya-ipo-inbound{color:var(--sd-call-accept, #1aa251)}.avaya-ipo-meta-line .avaya-ipo-dir.avaya-ipo-outbound{color:var(--sd-text-muted, #5f6368)}.avaya-ipo-meta-line .avaya-ipo-missed-badge{color:var(--sd-call-end, #e5484d);font-weight:700}.avaya-ipo-detail-card{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-card, #fff);border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-summary-card{order:1}.avaya-ipo-transcription-card{order:2}.avaya-ipo-detail-card audio{width:100%}.avaya-ipo-disabled-btn{width:100%;border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface-muted, #f7f7f7);color:var(--sd-text-subtle, #9ca3af);padding:10px;border-radius:var(--sd-radius, 10px);font-weight:600;cursor:not-allowed}.avaya-ipo-detail-title{font-weight:800;color:var(--sd-text, #333);font-size:14px}.avaya-ipo-detail-title-row{display:flex;align-items:center;justify-content:space-between}.avaya-ipo-transcription-actions{display:flex;flex-direction:column;gap:8px}.avaya-ipo-transcription-actions.avaya-ipo-outside{padding:0 4px}.avaya-ipo-detail-card.avaya-ipo-is-inactive{opacity:.45;filter:grayscale(.2);pointer-events:none}.avaya-ipo-action-btn{border:none;background:var(--sd-accent, #ff6633);color:var(--sd-accent-contrast, #fff);padding:10px 14px;border-radius:var(--sd-radius, 10px);font-weight:700;cursor:pointer;transition:background .15s ease,box-shadow .15s ease}.avaya-ipo-btn-content{display:inline-flex;align-items:center;gap:8px}.avaya-ipo-btn-spinner{width:14px;height:14px;border-radius:var(--sd-radius-pill, 999px);border:2px solid color-mix(in srgb,var(--sd-accent-contrast, #fff) 35%,transparent);border-top-color:var(--sd-accent-contrast, #fff);animation:spin .8s linear infinite}.avaya-ipo-action-btn:hover:not(:disabled){background:var(--sd-accent-strong, #ff5805)}.avaya-ipo-action-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring, 0 0 0 3px rgba(255, 102, 51, .22))}.avaya-ipo-action-btn:disabled{background:var(--sd-surface-sunken, #e8e8e8);color:var(--sd-text-subtle, #9ca3af);cursor:not-allowed}.avaya-ipo-status-error{color:var(--sd-call-end, #e5484d);font-size:12px;font-weight:600}.avaya-ipo-transcription-skeleton{display:flex;flex-direction:column;gap:10px}.avaya-ipo-transcription-skeleton-line{height:10px;border-radius:var(--sd-radius-pill, 999px);background:linear-gradient(90deg,var(--sd-surface-sunken, #e8e8e8) 0%,var(--sd-surface-muted, #f7f7f7) 45%,var(--sd-surface-sunken, #e8e8e8) 100%);background-size:200% 100%;animation:skeleton-shine 1.2s ease-in-out infinite}.avaya-ipo-transcription-skeleton-line:nth-child(2){width:85%}.avaya-ipo-transcription-skeleton-line:nth-child(3){width:90%}.avaya-ipo-transcription-skeleton-line:nth-child(4){width:70%}.avaya-ipo-transcription-skeleton-line:nth-child(5){width:60%}.avaya-ipo-chat-thread{display:flex;flex-direction:column;gap:8px}.avaya-ipo-chat-thread-btn{border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface, #fff);color:var(--sd-text, #333);padding:6px;border-radius:var(--sd-radius-sm, 8px);font-weight:700;cursor:pointer;font-size:12px;width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;transition:background .15s ease,border-color .15s ease}.avaya-ipo-chat-thread-btn:hover{background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-chat-thread-btn svg{width:16px;height:16px}.avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:absolute;inset:0;background:var(--sd-surface, #fff);padding:16px;z-index:1000;animation:transcript-expand .25s ease;border-radius:0}:host-context(.avaya-ipo-mode-standalone) .avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:fixed}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-detail-title-row{position:sticky;top:0;background:var(--sd-surface, #fff);z-index:2}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-chat-thread{flex:1 1 auto;overflow-y:auto;padding-bottom:8px}.avaya-ipo-detail-card{transition:transform .25s ease,opacity .25s ease}.avaya-ipo-transcription-card:not(.avaya-ipo-fullscreen){animation:transcript-collapse .2s ease}.avaya-ipo-chat-bubble{align-self:flex-start;max-width:86%;background:var(--sd-surface-muted, #f7f7f7);border-radius:var(--sd-radius, 10px);padding:8px 10px;border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-chat-bubble.avaya-ipo-agent{align-self:flex-end;background:var(--sd-accent-soft, #fff1ea);border-color:color-mix(in srgb,var(--sd-accent, #ff6633) 35%,transparent)}.avaya-ipo-chat-speaker{font-size:11px;font-weight:700;color:var(--sd-text-muted, #5f6368);text-transform:capitalize;margin-bottom:4px}.avaya-ipo-chat-text,.avaya-ipo-summary-text{font-size:13px;color:var(--sd-text, #333);line-height:1.4}.avaya-ipo-summary-sentiment{font-size:12px;font-weight:700;color:var(--sd-text, #333);margin-bottom:6px}.avaya-ipo-summary-emoji{margin-left:6px;font-size:14px}.avaya-ipo-summary-grid,.avaya-ipo-qa-grid{display:grid;gap:8px}.avaya-ipo-summary-card,.avaya-ipo-qa-card{border:1px solid var(--sd-border, #e3e3e3);border-radius:var(--sd-radius, 10px);padding:10px;background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-summary-title,.avaya-ipo-qa-title{font-weight:700;color:var(--sd-text, #333);font-size:12px;margin-bottom:6px;text-transform:capitalize}.avaya-ipo-summary-text,.avaya-ipo-qa-answer{font-size:13px;color:var(--sd-text, #333);line-height:1.4}.avaya-ipo-qa-reason{margin-top:6px;font-size:12px;color:var(--sd-text-muted, #5f6368);line-height:1.4}.avaya-ipo-sentiment-score{color:var(--sd-text-muted, #5f6368);font-size:12px}@keyframes transcript-expand{0%{transform:scale(.98);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes transcript-collapse{0%{transform:scale(1.02);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes skeleton-shine{0%{background-position:200% 0}to{background-position:-200% 0}}.avaya-ipo-placeholder{font-size:13px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-detail-row{display:flex;justify-content:space-between;align-items:center}.avaya-ipo-label{font-weight:700;color:var(--sd-text-muted, #5f6368);font-size:13px}.avaya-ipo-value{color:var(--sd-text, #333);text-align:right;font-weight:600;font-size:13px}.avaya-ipo-value.avaya-ipo-mono{font-family:SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;color:var(--sd-text-muted, #5f6368)}\n"] }]
1422
- }], ctorParameters: () => [{ type: i1.HttpClient }], propDecorators: { call: [{
1519
+ args: [{ selector: 'app-call-details', standalone: false, template: "<div class=\"avaya-ipo-call-profile\">\n <div class=\"avaya-ipo-profile-header\">\n <div class=\"avaya-ipo-avatar\">\n <svg viewBox=\"0 0 448 512\" width=\"28\" height=\"28\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z\" />\n </svg>\n </div>\n <div class=\"avaya-ipo-profile-info\">\n <div class=\"avaya-ipo-primary-number\">\n {{ getDisplayName() }}\n </div>\n <div class=\"avaya-ipo-secondary-info\">\n {{ getPhone() || 'Unknown' }}\n </div>\n <div class=\"avaya-ipo-meta-line\">\n <span>{{ call?.timestamp | date : 'medium' }}</span>\n <span class=\"avaya-ipo-divider\">|</span>\n @if (call?.disconnectSide === 'CALLER' && (call?.duration ?? 0) === 0) {\n <span class=\"avaya-ipo-divider\">|</span>\n <span class=\"avaya-ipo-missed-badge\">\n <svg viewBox=\"0 0 640 512\" width=\"12px\" aria-hidden=\"true\" style=\"fill: currentColor;\">\n <path d=\"M232 0c9.7 0 18.5 5.8 22.2 14.8s1.7 19.3-5.2 26.2l-39 39 58.7 58.7C282.3 152.4 300.8 160 320 160s37.7-7.6 51.3-21.3L503 7c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L405.3 172.7C382.6 195.3 352 208 320 208s-62.6-12.7-85.3-35.3L176 113.9l-39 39c-6.9 6.9-17.2 8.9-26.2 5.2s-14.8-12.5-14.8-22.2L96 24c0-13.3 10.7-24 24-24L232 0zM51.4 489.9l-35.4-62c-9.7-16.9-8.3-38.1 5.5-51.7C72.6 325.9 178.1 256 320 256s247.4 69.9 298.5 120.2c13.9 13.6 15.2 34.8 5.5 51.7l-35.4 62c-7.4 12.9-22.7 19.1-37 14.8L438.8 470.8c-13.5-4.1-22.8-16.5-22.8-30.6l0-56.2c-62.3-20.8-129.7-20.8-192 0l0 56.2c0 14.1-9.3 26.6-22.8 30.6L88.4 504.7c-14.3 4.3-29.6-1.8-37-14.8z\" />\n </svg>\n <span>Missed Call</span>\n </span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-summary-card\">\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Duration</div>\n <div class=\"avaya-ipo-value\">{{ call?.duration ?? 0 }}s</div>\n </div>\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Disconnect Side</div>\n <div class=\"avaya-ipo-value\">{{ call?.disconnectSide || 'N/A' }}</div>\n </div>\n </div>\n\n <div class=\"avaya-ipo-detail-card\">\n <div class=\"avaya-ipo-detail-title\">Call Recording</div>\n <audio\n *ngIf=\"call?.fullCallRecordingUrl; else noRecording\"\n controls\n [src]=\"call?.fullCallRecordingUrl\"\n ></audio>\n <ng-template #noRecording>\n @if ((call?.duration ?? 0) > 0) {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Processing</button>\n } @else {\n <button class=\"avaya-ipo-disabled-btn\" disabled>Recording not available</button>\n }\n </ng-template>\n </div>\n\n <!-- AI Call Analysis \u2014 read from the Interaction record (metadata.aiAnalysis), like snugdesk-app -->\n <div class=\"avaya-ipo-detail-card\">\n <div class=\"avaya-ipo-detail-title-row\">\n <div class=\"avaya-ipo-detail-title\">AI Call Analysis</div>\n <button\n class=\"avaya-ipo-chat-thread-btn\"\n type=\"button\"\n (click)=\"refreshAnalysis()\"\n [disabled]=\"isRefreshing\"\n aria-label=\"Refresh analysis\"\n title=\"Refresh analysis\"\n >\n @if (isRefreshing) {\n <span class=\"avaya-ipo-btn-spinner\" aria-hidden=\"true\"></span>\n } @else {\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M17.65 6.35A7.96 7.96 0 0 0 12 4a8 8 0 1 0 7.73 10h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\" />\n </svg>\n }\n </button>\n </div>\n\n @if (hasAnalysis) {\n @if (aiConfidenceScore !== null) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">AI Confidence</div>\n <div class=\"avaya-ipo-value\">{{ aiConfidenceScore }}%</div>\n </div>\n }\n @if (callType) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Call Type</div>\n <div class=\"avaya-ipo-value\">{{ callType }}</div>\n </div>\n }\n @if (customerSentiment) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Sentiment</div>\n <div class=\"avaya-ipo-value\">\n {{ customerSentiment }}\n @if (getSentimentEmoji()) {\n <span class=\"avaya-ipo-summary-emoji\">{{ getSentimentEmoji() }}</span>\n }\n </div>\n </div>\n }\n @if (customerIntent) {\n <div class=\"avaya-ipo-detail-row\">\n <div class=\"avaya-ipo-label\">Customer Intent</div>\n <div class=\"avaya-ipo-value\">{{ customerIntent }}</div>\n </div>\n }\n @if (conversationSummary.length) {\n <div class=\"avaya-ipo-analysis-section\">\n <div class=\"avaya-ipo-analysis-heading\">Conversation Summary</div>\n <ul class=\"avaya-ipo-analysis-list\">\n @for (item of conversationSummary; track $index) {\n <li>{{ item }}</li>\n }\n </ul>\n </div>\n }\n @if (keyConcerns.length) {\n <div class=\"avaya-ipo-analysis-section\">\n <div class=\"avaya-ipo-analysis-heading\">Key Concerns</div>\n <ul class=\"avaya-ipo-analysis-list\">\n @for (item of keyConcerns; track $index) {\n <li>{{ item }}</li>\n }\n </ul>\n </div>\n }\n @if (nextActions.length) {\n <div class=\"avaya-ipo-analysis-section\">\n <div class=\"avaya-ipo-analysis-heading\">Next Actions</div>\n <ul class=\"avaya-ipo-analysis-list\">\n @for (item of nextActions; track $index) {\n <li>{{ item }}</li>\n }\n </ul>\n </div>\n }\n } @else if (isAnalysisPending || isRefreshing) {\n <div class=\"avaya-ipo-transcription-skeleton\">\n @for (item of [1,2,3]; track item) {\n <div class=\"avaya-ipo-transcription-skeleton-line\"></div>\n }\n </div>\n <div class=\"avaya-ipo-placeholder\">AI analysis is being generated\u2026 use refresh to check again.</div>\n } @else if (summaryText) {\n <div class=\"avaya-ipo-summary-text\">{{ summaryText }}</div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No AI analysis available for this call yet.</div>\n }\n @if (refreshError) {\n <div class=\"avaya-ipo-status-error\">{{ refreshError }}</div>\n }\n </div>\n\n <div class=\"avaya-ipo-detail-card avaya-ipo-transcription-card\" [class.avaya-ipo-fullscreen]=\"isTranscriptFullscreen\">\n <div class=\"avaya-ipo-detail-title-row\">\n <div class=\"avaya-ipo-detail-title\">Transcript</div>\n @if (transcriptLines.length) {\n <button\n class=\"avaya-ipo-chat-thread-btn\"\n type=\"button\"\n (click)=\"toggleTranscriptFullscreen()\"\n [attr.aria-label]=\"isTranscriptFullscreen ? 'Exit full screen' : 'Enter full screen'\"\n >\n @if (isTranscriptFullscreen) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"\n />\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"\n />\n </svg>\n }\n </button>\n }\n </div>\n @if (transcriptLines.length) {\n <div class=\"avaya-ipo-chat-thread\">\n @for (line of transcriptLines; track $index) {\n <div class=\"avaya-ipo-chat-bubble\" [class.avaya-ipo-agent]=\"(line.speaker || '').toLowerCase() === 'agent'\">\n <div class=\"avaya-ipo-chat-speaker\">{{ getTranscriptSpeaker(line) }}</div>\n <div class=\"avaya-ipo-chat-text\">{{ line.text || '' }}</div>\n </div>\n }\n </div>\n } @else if (isAnalysisPending || isRefreshing) {\n <div class=\"avaya-ipo-transcription-skeleton\">\n @for (item of [1,2,3,4,5]; track item) {\n <div class=\"avaya-ipo-transcription-skeleton-line\"></div>\n }\n </div>\n } @else {\n <div class=\"avaya-ipo-placeholder\">No transcript available.</div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;box-sizing:border-box}.avaya-ipo-call-profile{display:flex;flex-direction:column;gap:14px;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;color:var(--sd-text, #333)}.avaya-ipo-profile-header{display:flex;gap:12px;align-items:center;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-avatar{width:52px;height:52px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-avatar, #eceff3);display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;color:var(--sd-text, #333)}.avaya-ipo-profile-info{display:flex;flex-direction:column;gap:6px}.avaya-ipo-primary-number{font-size:16px;font-weight:800;color:var(--sd-text, #333)}.avaya-ipo-secondary-info{font-size:12px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-meta-line{display:flex;gap:6px;align-items:center;font-size:12px;color:var(--sd-text-muted, #5f6368);flex-wrap:wrap}.avaya-ipo-meta-line .avaya-ipo-divider{color:var(--sd-text-subtle, #9ca3af)}.avaya-ipo-meta-line .avaya-ipo-missed-badge{color:var(--sd-call-end, #e5484d);font-weight:700}.avaya-ipo-detail-card{display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:var(--sd-radius-lg, 14px);background:var(--sd-card, #fff);border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-detail-card audio{width:100%}.avaya-ipo-disabled-btn{width:100%;border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface-muted, #f7f7f7);color:var(--sd-text-subtle, #9ca3af);padding:10px;border-radius:var(--sd-radius, 10px);font-weight:600;cursor:not-allowed}.avaya-ipo-detail-title{font-weight:800;color:var(--sd-text, #333);font-size:14px}.avaya-ipo-detail-title-row{display:flex;align-items:center;justify-content:space-between}.avaya-ipo-btn-spinner{width:14px;height:14px;border-radius:var(--sd-radius-pill, 999px);border:2px solid color-mix(in srgb,var(--sd-accent-contrast, #fff) 35%,transparent);border-top-color:var(--sd-accent-contrast, #fff);animation:spin .8s linear infinite}.avaya-ipo-status-error{color:var(--sd-call-end, #e5484d);font-size:12px;font-weight:600}.avaya-ipo-transcription-skeleton{display:flex;flex-direction:column;gap:10px}.avaya-ipo-transcription-skeleton-line{height:10px;border-radius:var(--sd-radius-pill, 999px);background:linear-gradient(90deg,var(--sd-surface-sunken, #e8e8e8) 0%,var(--sd-surface-muted, #f7f7f7) 45%,var(--sd-surface-sunken, #e8e8e8) 100%);background-size:200% 100%;animation:skeleton-shine 1.2s ease-in-out infinite}.avaya-ipo-transcription-skeleton-line:nth-child(2){width:85%}.avaya-ipo-transcription-skeleton-line:nth-child(3){width:90%}.avaya-ipo-transcription-skeleton-line:nth-child(4){width:70%}.avaya-ipo-transcription-skeleton-line:nth-child(5){width:60%}.avaya-ipo-chat-thread{display:flex;flex-direction:column;gap:8px}.avaya-ipo-chat-thread-btn{border:1px solid var(--sd-border, #e3e3e3);background:var(--sd-surface, #fff);color:var(--sd-text, #333);padding:6px;border-radius:var(--sd-radius-sm, 8px);font-weight:700;cursor:pointer;font-size:12px;width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;transition:background .15s ease,border-color .15s ease}.avaya-ipo-chat-thread-btn:hover{background:var(--sd-surface-muted, #f7f7f7)}.avaya-ipo-chat-thread-btn svg{width:16px;height:16px}.avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:absolute;inset:0;background:var(--sd-surface, #fff);padding:16px;z-index:1000;animation:transcript-expand .25s ease;border-radius:0}:host-context(.avaya-ipo-mode-standalone) .avaya-ipo-transcription-card.avaya-ipo-fullscreen{position:fixed}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-detail-title-row{position:sticky;top:0;background:var(--sd-surface, #fff);z-index:2}.avaya-ipo-transcription-card.avaya-ipo-fullscreen .avaya-ipo-chat-thread{flex:1 1 auto;overflow-y:auto;padding-bottom:8px}.avaya-ipo-detail-card{transition:transform .25s ease,opacity .25s ease}.avaya-ipo-transcription-card:not(.avaya-ipo-fullscreen){animation:transcript-collapse .2s ease}.avaya-ipo-chat-bubble{align-self:flex-start;max-width:86%;background:var(--sd-surface-muted, #f7f7f7);border-radius:var(--sd-radius, 10px);padding:8px 10px;border:1px solid var(--sd-border, #e3e3e3)}.avaya-ipo-chat-bubble.avaya-ipo-agent{align-self:flex-end;background:var(--sd-accent-soft, #fff1ea);border-color:color-mix(in srgb,var(--sd-accent, #ff6633) 35%,transparent)}.avaya-ipo-chat-speaker{font-size:11px;font-weight:700;color:var(--sd-text-muted, #5f6368);text-transform:capitalize;margin-bottom:4px}.avaya-ipo-chat-text,.avaya-ipo-summary-text{font-size:13px;color:var(--sd-text, #333);line-height:1.4}.avaya-ipo-summary-emoji{margin-left:6px;font-size:14px}.avaya-ipo-summary-card{border:1px solid var(--sd-border, #e3e3e3);border-radius:var(--sd-radius, 10px);padding:10px;background:var(--sd-surface-muted, #f7f7f7)}@keyframes transcript-expand{0%{transform:scale(.98);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes transcript-collapse{0%{transform:scale(1.02);opacity:.6}to{transform:scale(1);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes skeleton-shine{0%{background-position:200% 0}to{background-position:-200% 0}}.avaya-ipo-placeholder{font-size:13px;color:var(--sd-text-muted, #5f6368)}.avaya-ipo-analysis-section{margin-top:10px}.avaya-ipo-analysis-heading{font-size:12px;font-weight:700;color:var(--sd-text-muted, #5f6368);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px}.avaya-ipo-analysis-list{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:4px}.avaya-ipo-analysis-list li{font-size:13px;color:var(--sd-text, #333);line-height:1.45}.avaya-ipo-detail-row{display:flex;justify-content:space-between;align-items:center}.avaya-ipo-label{font-weight:700;color:var(--sd-text-muted, #5f6368);font-size:13px}.avaya-ipo-value{color:var(--sd-text, #333);text-align:right;font-weight:600;font-size:13px}\n"] }]
1520
+ }], ctorParameters: () => [{ type: i1$1.AppSyncHelperService }], propDecorators: { call: [{
1423
1521
  type: Input
1424
1522
  }] } });
1425
1523
 
@@ -1452,6 +1550,7 @@ class CallHistoryComponent {
1452
1550
  last_status
1453
1551
  metadata
1454
1552
  summary
1553
+ aiProcessingStatus
1455
1554
  startedAt
1456
1555
  completedAt
1457
1556
  duration
@@ -1559,7 +1658,9 @@ class CallHistoryComponent {
1559
1658
  disconnectSide,
1560
1659
  timestamp: tsSec ? new Date(tsSec * 1000).toISOString() : new Date().toISOString(),
1561
1660
  summary: interaction.summary || '',
1562
- fullCallRecordingUrl: interaction.recording?.location || '',
1661
+ metadata,
1662
+ aiProcessingStatus: interaction.aiProcessingStatus || '',
1663
+ fullCallRecordingUrl: interaction.recording?.location || metadata.phoneData?.AudioFile || '',
1563
1664
  phoneNumber: {
1564
1665
  normalizedPhoneNumber: customerNumber,
1565
1666
  name: name || undefined,
@@ -1682,33 +1783,6 @@ class CallHistoryComponent {
1682
1783
  }
1683
1784
  return undefined;
1684
1785
  }
1685
- formatDialOutFromInput(value) {
1686
- return formatDialOutNumber(value);
1687
- }
1688
- getTenantIdFromSession() {
1689
- const raw = sessionStorage.getItem('sd-tenant');
1690
- if (!raw)
1691
- return undefined;
1692
- try {
1693
- const parsed = JSON.parse(raw);
1694
- return parsed?.id || parsed?.tenantId || undefined;
1695
- }
1696
- catch {
1697
- return undefined;
1698
- }
1699
- }
1700
- getUserIdFromSession() {
1701
- const raw = sessionStorage.getItem('sd-user');
1702
- if (!raw)
1703
- return undefined;
1704
- try {
1705
- const parsed = JSON.parse(raw);
1706
- return parsed?.id || parsed?.userId || undefined;
1707
- }
1708
- catch {
1709
- return undefined;
1710
- }
1711
- }
1712
1786
  getPhoneDisplay(item) {
1713
1787
  return (item?.phoneNumber?.name ||
1714
1788
  item?.lookupPhoneNumber?.name ||
@@ -2272,15 +2346,46 @@ class RecordingManagerService {
2272
2346
  MIME_TYPE_PREFERRED = 'audio/webm;codecs=opus';
2273
2347
  MIME_TYPE_FALLBACK = 'audio/webm';
2274
2348
  // Record one continuous file for the whole call; a timeslice just flushes data periodically so the
2275
- // final Blob is complete. The full recording is uploaded once at call end and handed to the backend
2276
- // AI pipeline (transcription + summary).
2349
+ // final Blob is complete. In 'complete' mode the full recording is uploaded once at call end; in
2350
+ // 'chunked' mode each timeslice is also streamed live over the recording WebSocket so the backend
2351
+ // can stitch a file even if this tab dies mid-call.
2277
2352
  TIMESLICE_MS = 1000;
2353
+ // API Gateway WebSockets enforce a 32 KB FRAME limit — oversized frames kill the connection (1009).
2354
+ // Three-second slices at a capped bitrate stay comfortably under it; anything bigger is split into
2355
+ // frame-safe segments before sending (see MAX_WS_DATA_CHARS).
2356
+ CHUNKED_TIMESLICE_MS = 3000;
2357
+ // Opus voice at 32 kbps is transparent for calls and keeps a 3s slice ≈ 12 KB raw / 16 KB base64.
2358
+ CHUNKED_AUDIO_BPS = 32000;
2359
+ // Base64 payload cap per websocket message (multiple of 4 so each slice decodes independently);
2360
+ // leaves ample headroom inside the 32 KB frame limit including the JSON envelope.
2361
+ MAX_WS_DATA_CHARS = 24000;
2278
2362
  AUDIO_CONTEXT_CLOSE_DELAY_MS = 500;
2363
+ SOCKET_RECONNECT_DELAY_MS = 3000;
2364
+ // Pause between the last flushed chunk and the call-completed message: chunk messages invoke the
2365
+ // backend Lambda concurrently, so the final parts may still be mid-write to S3 when the stitch
2366
+ // would otherwise run. This settle window lets them land first.
2367
+ CALL_COMPLETED_DELAY_MS = 2000;
2368
+ // Stop redialing a broken socket after this many consecutive failures — the in-memory chunks and
2369
+ // the REST fallback still save the recording at call end, so endless connection spam buys nothing.
2370
+ SOCKET_MAX_RECONNECT_ATTEMPTS = 10;
2371
+ // Give the final flush + call-completed message a moment before force-closing the socket.
2372
+ SOCKET_FINALIZE_GRACE_MS = 1500;
2279
2373
  RECORDING_API_URL = APP_CONFIG.INTERACTION_CALL_RECORDING_API_URL;
2374
+ RECORDING_WS_URL = APP_CONFIG.RECORDING_SOCKET_WS_URL;
2280
2375
  constructor(http) {
2281
2376
  this.http = http;
2282
2377
  }
2283
- startRecording(localMediaStream, remoteMediaStream, metadata) {
2378
+ startRecording(localMediaStream, remoteMediaStream, metadata, mode = APP_CONFIG.RECORDING_UPLOAD_MODE) {
2379
+ // Restart for the SAME call in chunked mode (e.g. remote stream arrived late, or the call
2380
+ // re-fired CONNECTED): keep the session — one socket and one seq counter per call — and only
2381
+ // swap the audio plumbing. Tearing down would open a second socket and prematurely finalize.
2382
+ const existing = this.sessions.get(metadata.callId);
2383
+ if (existing && existing.mode === 'chunked' && mode === 'chunked' && !existing.stopping) {
2384
+ if (localMediaStream && remoteMediaStream) {
2385
+ return this.rebindMedia(existing, localMediaStream, remoteMediaStream);
2386
+ }
2387
+ return existing;
2388
+ }
2284
2389
  this.stopRecording(metadata.callId);
2285
2390
  if (!localMediaStream || !remoteMediaStream) {
2286
2391
  console.warn(`[${metadata.callId}] Skipped start recording: missing remote or local stream`);
@@ -2295,12 +2400,10 @@ class RecordingManagerService {
2295
2400
  }
2296
2401
  const audioContext = new AudioContext();
2297
2402
  const recordingStream = audioContext.createMediaStreamDestination();
2298
- audioContext
2299
- .createMediaStreamSource(localMediaStream)
2300
- .connect(recordingStream);
2301
- audioContext
2302
- .createMediaStreamSource(remoteMediaStream)
2303
- .connect(recordingStream);
2403
+ const localSource = audioContext.createMediaStreamSource(localMediaStream);
2404
+ localSource.connect(recordingStream);
2405
+ const remoteSource = audioContext.createMediaStreamSource(remoteMediaStream);
2406
+ remoteSource.connect(recordingStream);
2304
2407
  const mimeType = MediaRecorder.isTypeSupported(this.MIME_TYPE_PREFERRED)
2305
2408
  ? this.MIME_TYPE_PREFERRED
2306
2409
  : this.MIME_TYPE_FALLBACK;
@@ -2313,13 +2416,36 @@ class RecordingManagerService {
2313
2416
  recorder: null,
2314
2417
  mimeType,
2315
2418
  uploaded: false,
2419
+ mode,
2420
+ socket: null,
2421
+ seq: 0,
2422
+ pendingChunks: [],
2423
+ sentAny: false,
2424
+ reconnectAttempts: 0,
2425
+ sourceNodes: [localSource, remoteSource],
2426
+ streamCursor: 0,
2427
+ pumping: false,
2428
+ everConnected: false,
2429
+ completedSent: false,
2316
2430
  };
2317
2431
  this.sessions.set(metadata.callId, session);
2318
- const recorder = new MediaRecorder(recordingStream.stream, { mimeType });
2432
+ if (mode === 'chunked') {
2433
+ this.openRecordingSocket(session);
2434
+ }
2435
+ const recorder = new MediaRecorder(recordingStream.stream, mode === 'chunked'
2436
+ ? { mimeType, audioBitsPerSecond: this.CHUNKED_AUDIO_BPS }
2437
+ : { mimeType });
2319
2438
  session.recorder = recorder;
2320
2439
  recorder.ondataavailable = (evt) => {
2321
2440
  if (evt.data && evt.data.size > 0) {
2441
+ // Keep the local copy in BOTH modes: it's the upload source in 'complete' mode and the
2442
+ // fallback in 'chunked' mode if the socket never works.
2322
2443
  session.chunks.push(evt.data);
2444
+ if (session.mode === 'chunked') {
2445
+ // The pump streams chunks strictly in order from session.chunks — it also lets a
2446
+ // reconnect rewind and re-send the whole call (the backend deletes parts on every close).
2447
+ void this.pumpChunks(session);
2448
+ }
2323
2449
  }
2324
2450
  };
2325
2451
  recorder.onerror = (err) => {
@@ -2328,8 +2454,8 @@ class RecordingManagerService {
2328
2454
  recorder.onstop = () => {
2329
2455
  void this.finalizeRecording(session);
2330
2456
  };
2331
- recorder.start(this.TIMESLICE_MS);
2332
- console.debug(`[${metadata.callId}] MediaRecorder started (single-file mode)`);
2457
+ recorder.start(mode === 'chunked' ? this.CHUNKED_TIMESLICE_MS : this.TIMESLICE_MS);
2458
+ console.debug(`[${metadata.callId}] MediaRecorder started (${mode} mode)`);
2333
2459
  return session;
2334
2460
  }
2335
2461
  getSession(callId) {
@@ -2365,6 +2491,10 @@ class RecordingManagerService {
2365
2491
  if (session.uploaded)
2366
2492
  return;
2367
2493
  session.uploaded = true;
2494
+ if (session.mode === 'chunked') {
2495
+ await this.finalizeChunked(session);
2496
+ return;
2497
+ }
2368
2498
  if (!session.chunks.length) {
2369
2499
  console.warn(`[${session.metadata.callId}] No recording data captured`);
2370
2500
  return;
@@ -2380,6 +2510,220 @@ class RecordingManagerService {
2380
2510
  console.error(`[${session.metadata.callId}] ❌ recording upload failed`, err);
2381
2511
  }
2382
2512
  }
2513
+ // ── Chunked mode: stream slices over the recording WebSocket ─────────────────────────────────
2514
+ /**
2515
+ * Rewire fresh local/remote streams into the SAME recording destination. The MediaRecorder (and
2516
+ * therefore the single WebM byte stream, the socket and the seq counter) continue uninterrupted —
2517
+ * restarting the recorder would inject a second WebM header mid-file and break playback of the
2518
+ * stitched recording.
2519
+ */
2520
+ rebindMedia(session, localMediaStream, remoteMediaStream) {
2521
+ const { callId } = session.metadata;
2522
+ console.debug(`[${callId}] Rewiring recording sources (recorder, socket and seq preserved)`);
2523
+ for (const node of session.sourceNodes) {
2524
+ try {
2525
+ node.disconnect();
2526
+ }
2527
+ catch { /* already disconnected */ }
2528
+ }
2529
+ const ctx = session.audioContext;
2530
+ if (ctx.state === 'suspended') {
2531
+ void ctx.resume();
2532
+ }
2533
+ const localSource = ctx.createMediaStreamSource(localMediaStream);
2534
+ localSource.connect(session.recordingStream);
2535
+ const remoteSource = ctx.createMediaStreamSource(remoteMediaStream);
2536
+ remoteSource.connect(session.recordingStream);
2537
+ session.sourceNodes = [localSource, remoteSource];
2538
+ return session;
2539
+ }
2540
+ openRecordingSocket(session) {
2541
+ const { metadata } = session;
2542
+ // One socket per call: never open a second connection while one is open or still connecting.
2543
+ if (session.socket &&
2544
+ (session.socket.readyState === WebSocket.OPEN ||
2545
+ session.socket.readyState === WebSocket.CONNECTING)) {
2546
+ return;
2547
+ }
2548
+ if (session.reconnectTimer) {
2549
+ clearTimeout(session.reconnectTimer);
2550
+ session.reconnectTimer = undefined;
2551
+ }
2552
+ const token = (typeof sessionStorage !== 'undefined' && sessionStorage.getItem('auth_sessionToken')) || '';
2553
+ const url = `${this.RECORDING_WS_URL}?` +
2554
+ `token=${encodeURIComponent(token)}` +
2555
+ `&callId=${encodeURIComponent(metadata.callId)}` +
2556
+ `&tenantId=${encodeURIComponent(metadata.tenantId)}` +
2557
+ (metadata.entityId ? `&entityId=${encodeURIComponent(metadata.entityId)}` : '') +
2558
+ `&contentType=${encodeURIComponent(session.mimeType)}`;
2559
+ console.debug(`[${metadata.callId}] Opening recording socket (entityId=${metadata.entityId || 'NONE — chunks will land under the NIL entity folder'})`);
2560
+ try {
2561
+ const socket = new WebSocket(url);
2562
+ session.socket = socket;
2563
+ socket.onopen = () => {
2564
+ session.reconnectAttempts = 0;
2565
+ if (session.everConnected) {
2566
+ // Reconnect after a drop: the backend stitched AND deleted the parts on $disconnect, so
2567
+ // rewind and re-stream the entire call from memory — the next stitch then has everything.
2568
+ console.debug(`[${metadata.callId}] Recording socket reconnected — re-streaming ${session.chunks.length} slices`);
2569
+ session.streamCursor = 0;
2570
+ session.seq = 0;
2571
+ session.pendingChunks = [];
2572
+ void this.pumpChunks(session);
2573
+ }
2574
+ else {
2575
+ console.debug(`[${metadata.callId}] Recording socket connected`);
2576
+ session.everConnected = true;
2577
+ this.flushPendingChunks(session);
2578
+ void this.pumpChunks(session);
2579
+ }
2580
+ };
2581
+ socket.onerror = (err) => {
2582
+ console.warn(`[${metadata.callId}] Recording socket error`, err);
2583
+ };
2584
+ socket.onclose = () => {
2585
+ // Ignore close events from sockets we've already replaced — only the current one counts.
2586
+ if (session.socket !== socket) {
2587
+ return;
2588
+ }
2589
+ session.socket = null;
2590
+ // Reconnect while the call is still recording — the backend stitches on every close, so a
2591
+ // blip costs nothing; the next close re-stitches the fuller file.
2592
+ if (!session.stopping && this.sessions.get(metadata.callId) === session) {
2593
+ session.reconnectAttempts += 1;
2594
+ if (session.reconnectAttempts > this.SOCKET_MAX_RECONNECT_ATTEMPTS) {
2595
+ console.warn(`[${metadata.callId}] Recording socket gave up after ${this.SOCKET_MAX_RECONNECT_ATTEMPTS} attempts; ` +
2596
+ `recording continues in memory and uploads at call end`);
2597
+ return;
2598
+ }
2599
+ if (session.reconnectTimer) {
2600
+ clearTimeout(session.reconnectTimer);
2601
+ }
2602
+ session.reconnectTimer = setTimeout(() => this.openRecordingSocket(session), this.SOCKET_RECONNECT_DELAY_MS);
2603
+ }
2604
+ };
2605
+ }
2606
+ catch (err) {
2607
+ console.warn(`[${metadata.callId}] Failed to open recording socket`, err);
2608
+ session.socket = null;
2609
+ }
2610
+ }
2611
+ /** Stream session.chunks in strict order; safe to call repeatedly (single active pump). */
2612
+ async pumpChunks(session) {
2613
+ if (session.pumping || session.completedSent) {
2614
+ return;
2615
+ }
2616
+ session.pumping = true;
2617
+ try {
2618
+ while (session.streamCursor < session.chunks.length && !session.completedSent) {
2619
+ const blob = session.chunks[session.streamCursor];
2620
+ session.streamCursor += 1;
2621
+ await this.streamChunk(session, blob);
2622
+ }
2623
+ }
2624
+ finally {
2625
+ session.pumping = false;
2626
+ }
2627
+ }
2628
+ async streamChunk(session, chunk) {
2629
+ if (session.completedSent) {
2630
+ // Never send chunks after call-completed: the backend has already stitched and retired the
2631
+ // connection; a straggler would just become an orphaned part.
2632
+ return;
2633
+ }
2634
+ try {
2635
+ const dataUrl = await this.convertBlobToBase64(chunk);
2636
+ const data = dataUrl.split(',')[1] || '';
2637
+ if (!data)
2638
+ return;
2639
+ // Split into frame-safe segments: API Gateway kills connections on frames > 32 KB. Slicing
2640
+ // base64 at 4-char boundaries keeps every segment independently decodable, and each segment
2641
+ // carries its own seq — server-side concatenation in seq order reproduces the exact bytes.
2642
+ for (let i = 0; i < data.length; i += this.MAX_WS_DATA_CHARS) {
2643
+ const segment = data.slice(i, i + this.MAX_WS_DATA_CHARS);
2644
+ session.seq += 1;
2645
+ const message = JSON.stringify({ action: 'chunk', seq: session.seq, data: segment });
2646
+ if (session.socket && session.socket.readyState === WebSocket.OPEN) {
2647
+ session.socket.send(message);
2648
+ session.sentAny = true;
2649
+ }
2650
+ else {
2651
+ // Socket down — keep the message (seq already assigned, so order survives a reconnect).
2652
+ session.pendingChunks.push(message);
2653
+ }
2654
+ }
2655
+ }
2656
+ catch (err) {
2657
+ console.warn(`[${session.metadata.callId}] Failed to stream recording chunk`, err);
2658
+ }
2659
+ }
2660
+ flushPendingChunks(session) {
2661
+ if (!session.socket || session.socket.readyState !== WebSocket.OPEN)
2662
+ return;
2663
+ while (session.pendingChunks.length) {
2664
+ session.socket.send(session.pendingChunks.shift());
2665
+ session.sentAny = true;
2666
+ }
2667
+ }
2668
+ async finalizeChunked(session) {
2669
+ const { metadata } = session;
2670
+ if (session.reconnectTimer) {
2671
+ clearTimeout(session.reconnectTimer);
2672
+ session.reconnectTimer = undefined;
2673
+ }
2674
+ // Wait (briefly) for the pump to drain so the call's tail audio is part of the stitch.
2675
+ const drainDeadline = Date.now() + 2000;
2676
+ while ((session.pumping || session.streamCursor < session.chunks.length) &&
2677
+ Date.now() < drainDeadline) {
2678
+ await new Promise((resolve) => setTimeout(resolve, 100));
2679
+ }
2680
+ const socket = session.socket;
2681
+ if (socket && socket.readyState === WebSocket.OPEN) {
2682
+ try {
2683
+ this.flushPendingChunks(session);
2684
+ session.completedSent = true; // no further chunks may be queued from here on
2685
+ // Let the already-sent chunk writes settle server-side before asking for the stitch.
2686
+ await new Promise((resolve) => setTimeout(resolve, this.CALL_COMPLETED_DELAY_MS));
2687
+ socket.send(JSON.stringify({ action: 'call-completed' }));
2688
+ console.debug(`[${metadata.callId}] ✅ recording finalized over socket (${session.seq} chunks)`);
2689
+ }
2690
+ catch (err) {
2691
+ console.warn(`[${metadata.callId}] Failed to send call-completed`, err);
2692
+ }
2693
+ setTimeout(() => {
2694
+ try {
2695
+ socket.close();
2696
+ }
2697
+ catch { /* already closed */ }
2698
+ }, this.SOCKET_FINALIZE_GRACE_MS);
2699
+ session.chunks = [];
2700
+ return;
2701
+ }
2702
+ if (session.sentAny) {
2703
+ // Some chunks made it — the backend's $disconnect stitch already saved (or will save) those.
2704
+ // Don't double-upload; the lost tail is at most a few seconds.
2705
+ console.warn(`[${metadata.callId}] Socket down at finalize; backend stitches what was streamed`);
2706
+ session.chunks = [];
2707
+ return;
2708
+ }
2709
+ // Streaming never worked at all — fall back to the original complete upload so the recording
2710
+ // is not lost just because the socket couldn't connect.
2711
+ console.warn(`[${metadata.callId}] Recording socket never connected; falling back to complete upload`);
2712
+ if (!session.chunks.length) {
2713
+ console.warn(`[${metadata.callId}] No recording data captured`);
2714
+ return;
2715
+ }
2716
+ const blob = new Blob(session.chunks, { type: session.mimeType });
2717
+ session.chunks = [];
2718
+ const filename = this.generateFilename(metadata.callId, metadata.agentId, session.mimeType);
2719
+ try {
2720
+ await this.uploadCallRecording(metadata, blob, filename, session.mimeType);
2721
+ console.debug(`[${metadata.callId}] ✅ uploaded recording (fallback) -> ${filename}`);
2722
+ }
2723
+ catch (err) {
2724
+ console.error(`[${metadata.callId}] ❌ fallback recording upload failed`, err);
2725
+ }
2726
+ }
2383
2727
  async uploadCallRecording(metadata, file, filename, mimeType) {
2384
2728
  try {
2385
2729
  const base64 = await this.convertBlobToBase64(file);
@@ -2899,11 +3243,11 @@ class PhoneIdleComponent {
2899
3243
  this.keyboardInput.emit(ev);
2900
3244
  }
2901
3245
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: PhoneIdleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2902
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: PhoneIdleComponent, isStandalone: false, selector: "app-phone-idle", inputs: { dialForm: "dialForm", contacts: "contacts", showDirectoryPhonebook: "showDirectoryPhonebook", isRinging: "isRinging", CountryISO: "CountryISO", SearchCountryField: "SearchCountryField" }, outputs: { toggleDirectory: "toggleDirectory", clear: "clear", makeCall: "makeCall", keypadInput: "keypadInput", keyboardInput: "keyboardInput" }, ngImport: i0, template: "<form class=\"avaya-ipo-phone-shell avaya-ipo-classic\" [formGroup]=\"dialForm\" (ngSubmit)=\"onMakeCall()\">\n <div class=\"avaya-ipo-input-row avaya-ipo-classic-input\">\n <ngx-intl-tel-input\n formControlName=\"phoneNumber\"\n name=\"phoneNumber\"\n [cssClass]=\"'avaya-ipo-phone_number_sd'\"\n [preferredCountries]=\"['in']\"\n [customPlaceholder]=\"'Phone Number'\"\n [enableAutoCountrySelect]=\"false\"\n [enablePlaceholder]=\"false\"\n [searchCountryFlag]=\"true\"\n [searchCountryField]=\"[SearchCountryField.Iso2, SearchCountryField.Name]\"\n [selectFirstCountry]=\"false\"\n [selectedCountryISO]=\"CountryISO.India\"\n [maxLength]=\"15\"\n [phoneValidation]=\"true\"\n [separateDialCode]=\"true\"\n (keydown)=\"onKeyboardInput($event)\"\n >\n </ngx-intl-tel-input>\n <button type=\"button\" class=\"avaya-ipo-clear-btn\" (click)=\"onClear()\" aria-label=\"Backspace\" title=\"Backspace\">\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.12c.36.53.9.88 1.59.88h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z\" />\n </svg>\n </button>\n </div>\n\n <div class=\"avaya-ipo-dial-cluster\">\n <div class=\"avaya-ipo-keypad avaya-ipo-classic-grid\">\n <button type=\"button\" (click)=\"onKeypadInput('1')\">\n <span class=\"avaya-ipo-digit\">1</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('2')\">\n <span class=\"avaya-ipo-digit\">2</span>\n <span class=\"avaya-ipo-letters\">ABC</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('3')\">\n <span class=\"avaya-ipo-digit\">3</span>\n <span class=\"avaya-ipo-letters\">DEF</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('4')\">\n <span class=\"avaya-ipo-digit\">4</span>\n <span class=\"avaya-ipo-letters\">GHI</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('5')\">\n <span class=\"avaya-ipo-digit\">5</span>\n <span class=\"avaya-ipo-letters\">JKL</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('6')\">\n <span class=\"avaya-ipo-digit\">6</span>\n <span class=\"avaya-ipo-letters\">MNO</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('7')\">\n <span class=\"avaya-ipo-digit\">7</span>\n <span class=\"avaya-ipo-letters\">PQRS</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('8')\">\n <span class=\"avaya-ipo-digit\">8</span>\n <span class=\"avaya-ipo-letters\">TUV</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('9')\">\n <span class=\"avaya-ipo-digit\">9</span>\n <span class=\"avaya-ipo-letters\">WXYZ</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('*')\">\n <span class=\"avaya-ipo-digit\">*</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('0')\">\n <span class=\"avaya-ipo-digit\">0</span>\n <span class=\"avaya-ipo-letters\">+</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('#')\">\n <span class=\"avaya-ipo-digit\">#</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n </div>\n\n <div class=\"avaya-ipo-actions\">\n <button type=\"submit\" class=\"avaya-ipo-call-btn-main\" [disabled]=\"!this.dialForm.valid\">\n <svg viewBox=\"0 0 512 512\" width=\"22px\" height=\"22px\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M164.9 24.6c-7.7-18.6-28-28.5-47.4-23.2l-88 24C12.1 30.2 0 46 0 64C0 311.4 200.6 512 448 512c18 0 33.8-12.1 38.6-29.5l24-88c5.3-19.4-4.6-39.7-23.2-47.4l-96-40c-16.3-6.8-35.2-2.1-46.3 11.6L304.7 368C234.3 334.7 177.3 277.7 144 207.3L193.3 167c13.7-11.2 18.4-30 11.6-46.3l-40-96z\" />\n </svg>\n </button>\n </div>\n </div>\n</form>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.avaya-ipo-phone-shell.avaya-ipo-classic{--key-size: clamp(40px, min(24cqw, 18cqh - 30px), 88px);--key-gap: calc(var(--key-size) * .16);display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(35px,4.5cqw,30px);background:transparent;width:100%;height:100%;flex:1 1 auto;min-height:0;padding:46px 15px clamp(12px,3cqw,20px);box-sizing:border-box}.avaya-ipo-dial-cluster{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(10px,2.6cqw,18px)}.avaya-ipo-classic-input{width:100%;display:flex;align-items:center;padding:0;box-sizing:border-box;position:relative;border:1.5px solid var(--sd-input-border);border-radius:var(--sd-radius);background:var(--sd-input);box-shadow:var(--sd-shadow-sm);margin-bottom:0;transition:border-color .18s ease,box-shadow .18s ease}.avaya-ipo-classic-input:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-phonebook-btn{border:none;background:transparent;color:var(--sd-text-muted);width:32px;height:32px;border-radius:var(--sd-radius-sm);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;cursor:pointer}.avaya-ipo-phonebook-btn:hover{background:var(--sd-surface-muted)}.avaya-ipo-phonebook-btn:focus{outline:none;box-shadow:none}.avaya-ipo-phonebook-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn{position:absolute;right:clamp(5px,1.6cqw,9px);top:50%;transform:translateY(-50%);width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--sd-text-subtle);border-radius:50%;padding:0;cursor:pointer;transition:background .15s ease,color .15s ease,transform .1s ease}.avaya-ipo-clear-btn:hover{background:var(--sd-surface-muted);color:var(--sd-accent)}.avaya-ipo-clear-btn:active{transform:translateY(-50%) scale(.9)}.avaya-ipo-clear-btn:focus{outline:none;box-shadow:none}.avaya-ipo-clear-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn svg{display:block}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd{width:100%}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input{width:100%;border:none!important;box-shadow:none!important;background:transparent!important;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0!important;font-size:clamp(12px,calc(var(--key-size) * .27),20px)!important;font-weight:600;letter-spacing:.4px;color:var(--sd-text)!important}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input::placeholder{font-weight:400;letter-spacing:normal;color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti{width:100%}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag{padding:0 10px 0 14px;border-right:1px solid var(--sd-border);border-radius:calc(var(--sd-radius) - 2px) 0 0 calc(var(--sd-radius) - 2px);background:transparent;outline:none;transition:background .15s ease}:host ::ng-deep .avaya-ipo-classic-input .iti--allow-dropdown .iti__flag-container:hover .iti__selected-flag{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .selected-dial-code{margin-left:6px;font-size:clamp(12px,calc(var(--key-size) * .18),16px);font-weight:600;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag:focus,:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input:focus,.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input:focus{outline:none;box-shadow:none}:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input{background:transparent!important;border:none!important;box-shadow:none!important;height:auto;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0;font-size:clamp(12px,calc(var(--key-size) * .27),20px);font-weight:600;letter-spacing:.4px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti.separate-dial-code .iti__tel-input{padding-left:102px!important}:host ::ng-deep .avaya-ipo-classic-input .iti__dropdown-content,:host ::ng-deep .avaya-ipo-classic-input .dropdown-menu{z-index:30;min-width:248px;padding:6px;background:var(--sd-surface);border:1px solid var(--sd-border);border-radius:var(--sd-radius);box-shadow:var(--sd-shadow-lg)}:host ::ng-deep .avaya-ipo-classic-input .iti__country-list{max-height:220px;overflow-y:auto;margin:0;padding:0;border:none;box-shadow:none;background:transparent}:host ::ng-deep .avaya-ipo-classic-input .search-container{position:sticky;top:0;z-index:1;padding:0 0 6px;background:var(--sd-surface)}:host ::ng-deep .avaya-ipo-classic-input #country-search-box{width:100%;box-sizing:border-box;margin:0!important;padding:8px 12px!important;font-size:14px!important;font-weight:400!important;letter-spacing:normal!important;color:var(--sd-text)!important;background:var(--sd-input)!important;border:1px solid var(--sd-input-border)!important;border-radius:var(--sd-radius-sm)!important;box-shadow:none!important;height:auto!important;transition:border-color .15s ease,box-shadow .15s ease}:host ::ng-deep .avaya-ipo-classic-input #country-search-box:focus{outline:none!important;border-color:var(--sd-accent)!important;box-shadow:var(--sd-focus-ring)!important}:host ::ng-deep .avaya-ipo-classic-input #country-search-box::placeholder{color:var(--sd-text-subtle)!important}:host ::ng-deep .avaya-ipo-classic-input .iti__country{padding:7px 8px;border-radius:var(--sd-radius-sm);font-size:14px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__country.iti__highlight,:host ::ng-deep .avaya-ipo-classic-input .iti__country:hover{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .iti__country .iti__dial-code{color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti__divider{border-top:1px solid var(--sd-border);margin:4px 0}.avaya-ipo-classic-grid{width:auto;margin:0 auto;display:grid;grid-template-columns:repeat(3,var(--key-size));gap:var(--key-gap);justify-content:center;flex:0 1 auto}.avaya-ipo-classic-grid button{width:var(--key-size);height:var(--key-size);border-radius:50%;border:1.6px solid var(--sd-border-strong);background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-classic-grid button:focus{outline:none;box-shadow:none}.avaya-ipo-classic-grid button:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-classic-grid button:active{background:var(--sd-surface-muted)}.avaya-ipo-classic-grid .avaya-ipo-digit{font-size:clamp(15px,calc(var(--key-size) * .34),26px);font-weight:400;color:var(--sd-text);line-height:1.1}.avaya-ipo-classic-grid .avaya-ipo-letters{font-size:clamp(7px,calc(var(--key-size) * .12),10px);letter-spacing:.8px;color:var(--sd-text-subtle);margin-top:2px}.avaya-ipo-actions{display:flex;justify-content:center;width:100%;margin-top:0}.avaya-ipo-call-btn-main{width:var(--key-size);height:var(--key-size);border-radius:50%;border:none;background:var(--sd-call-accept);color:var(--sd-accent-contrast);display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--sd-shadow-md);cursor:pointer}.avaya-ipo-call-btn-main:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.NgxIntlTelInputComponent, selector: "ngx-intl-tel-input", inputs: ["value", "preferredCountries", "enablePlaceholder", "customPlaceholder", "numberFormat", "cssClass", "onlyCountries", "enableAutoCountrySelect", "searchCountryFlag", "searchCountryField", "searchCountryPlaceholder", "maxLength", "selectFirstCountry", "selectedCountryISO", "phoneValidation", "inputId", "separateDialCode"], outputs: ["countryChange"] }, { kind: "directive", type: i2$1.NativeElementInjectorDirective, selector: "[ngModel], [formControl], [formControlName]" }] });
3246
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: PhoneIdleComponent, isStandalone: false, selector: "app-phone-idle", inputs: { dialForm: "dialForm", contacts: "contacts", showDirectoryPhonebook: "showDirectoryPhonebook", isRinging: "isRinging", CountryISO: "CountryISO", SearchCountryField: "SearchCountryField" }, outputs: { toggleDirectory: "toggleDirectory", clear: "clear", makeCall: "makeCall", keypadInput: "keypadInput", keyboardInput: "keyboardInput" }, ngImport: i0, template: "<form class=\"avaya-ipo-phone-shell avaya-ipo-classic\" [formGroup]=\"dialForm\" (ngSubmit)=\"onMakeCall()\">\n <div class=\"avaya-ipo-input-row avaya-ipo-classic-input\">\n <ngx-intl-tel-input\n formControlName=\"phoneNumber\"\n name=\"phoneNumber\"\n [cssClass]=\"'avaya-ipo-phone_number_sd'\"\n [preferredCountries]=\"['in']\"\n [customPlaceholder]=\"'Phone Number'\"\n [enableAutoCountrySelect]=\"false\"\n [enablePlaceholder]=\"false\"\n [searchCountryFlag]=\"true\"\n [searchCountryField]=\"[SearchCountryField.Iso2, SearchCountryField.Name]\"\n [selectFirstCountry]=\"false\"\n [selectedCountryISO]=\"CountryISO.India\"\n [maxLength]=\"15\"\n [phoneValidation]=\"true\"\n [separateDialCode]=\"true\"\n (keydown)=\"onKeyboardInput($event)\"\n >\n </ngx-intl-tel-input>\n <button type=\"button\" class=\"avaya-ipo-clear-btn\" (click)=\"onClear()\" aria-label=\"Backspace\" title=\"Backspace\">\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.12c.36.53.9.88 1.59.88h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z\" />\n </svg>\n </button>\n </div>\n\n <div class=\"avaya-ipo-dial-cluster\">\n <div class=\"avaya-ipo-keypad avaya-ipo-classic-grid\">\n <button type=\"button\" (click)=\"onKeypadInput('1')\">\n <span class=\"avaya-ipo-digit\">1</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('2')\">\n <span class=\"avaya-ipo-digit\">2</span>\n <span class=\"avaya-ipo-letters\">ABC</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('3')\">\n <span class=\"avaya-ipo-digit\">3</span>\n <span class=\"avaya-ipo-letters\">DEF</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('4')\">\n <span class=\"avaya-ipo-digit\">4</span>\n <span class=\"avaya-ipo-letters\">GHI</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('5')\">\n <span class=\"avaya-ipo-digit\">5</span>\n <span class=\"avaya-ipo-letters\">JKL</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('6')\">\n <span class=\"avaya-ipo-digit\">6</span>\n <span class=\"avaya-ipo-letters\">MNO</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('7')\">\n <span class=\"avaya-ipo-digit\">7</span>\n <span class=\"avaya-ipo-letters\">PQRS</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('8')\">\n <span class=\"avaya-ipo-digit\">8</span>\n <span class=\"avaya-ipo-letters\">TUV</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('9')\">\n <span class=\"avaya-ipo-digit\">9</span>\n <span class=\"avaya-ipo-letters\">WXYZ</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('*')\">\n <span class=\"avaya-ipo-digit\">*</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('0')\">\n <span class=\"avaya-ipo-digit\">0</span>\n <span class=\"avaya-ipo-letters\">+</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('#')\">\n <span class=\"avaya-ipo-digit\">#</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n </div>\n\n <div class=\"avaya-ipo-actions\">\n <button type=\"submit\" class=\"avaya-ipo-call-btn-main\" [disabled]=\"!this.dialForm.valid\">\n <svg viewBox=\"0 0 512 512\" width=\"22px\" height=\"22px\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M164.9 24.6c-7.7-18.6-28-28.5-47.4-23.2l-88 24C12.1 30.2 0 46 0 64C0 311.4 200.6 512 448 512c18 0 33.8-12.1 38.6-29.5l24-88c5.3-19.4-4.6-39.7-23.2-47.4l-96-40c-16.3-6.8-35.2-2.1-46.3 11.6L304.7 368C234.3 334.7 177.3 277.7 144 207.3L193.3 167c13.7-11.2 18.4-30 11.6-46.3l-40-96z\" />\n </svg>\n </button>\n </div>\n </div>\n</form>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.avaya-ipo-phone-shell.avaya-ipo-classic{--key-size: clamp(40px, min(24cqw, 18cqh - 30px), 88px);--key-gap: calc(var(--key-size) * .16);display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(35px,4.5cqw,30px);background:transparent;width:100%;height:100%;flex:1 1 auto;min-height:0;padding:46px 15px clamp(12px,3cqw,20px);box-sizing:border-box}.avaya-ipo-dial-cluster{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(10px,2.6cqw,18px)}.avaya-ipo-classic-input{width:100%;display:flex;align-items:center;padding:0;box-sizing:border-box;position:relative;border:1.5px solid var(--sd-input-border);border-radius:var(--sd-radius);background:var(--sd-input);box-shadow:var(--sd-shadow-sm);margin-bottom:0;transition:border-color .18s ease,box-shadow .18s ease}.avaya-ipo-classic-input:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn{position:absolute;right:clamp(5px,1.6cqw,9px);top:50%;transform:translateY(-50%);width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--sd-text-subtle);border-radius:50%;padding:0;cursor:pointer;transition:background .15s ease,color .15s ease,transform .1s ease}.avaya-ipo-clear-btn:hover{background:var(--sd-surface-muted);color:var(--sd-accent)}.avaya-ipo-clear-btn:active{transform:translateY(-50%) scale(.9)}.avaya-ipo-clear-btn:focus{outline:none;box-shadow:none}.avaya-ipo-clear-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn svg{display:block}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd{width:100%}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input{width:100%;border:none!important;box-shadow:none!important;background:transparent!important;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0!important;font-size:clamp(12px,calc(var(--key-size) * .27),20px)!important;font-weight:600;letter-spacing:.4px;color:var(--sd-text)!important}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input::placeholder{font-weight:400;letter-spacing:normal;color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti{width:100%}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag{padding:0 10px 0 14px;border-right:1px solid var(--sd-border);border-radius:calc(var(--sd-radius) - 2px) 0 0 calc(var(--sd-radius) - 2px);background:transparent;outline:none;transition:background .15s ease}:host ::ng-deep .avaya-ipo-classic-input .iti--allow-dropdown .iti__flag-container:hover .iti__selected-flag{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .selected-dial-code{margin-left:6px;font-size:clamp(12px,calc(var(--key-size) * .18),16px);font-weight:600;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag:focus,:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input:focus,.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input:focus{outline:none;box-shadow:none}:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input{background:transparent!important;border:none!important;box-shadow:none!important;height:auto;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0;font-size:clamp(12px,calc(var(--key-size) * .27),20px);font-weight:600;letter-spacing:.4px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti.separate-dial-code .iti__tel-input{padding-left:102px!important}:host ::ng-deep .avaya-ipo-classic-input .iti__dropdown-content,:host ::ng-deep .avaya-ipo-classic-input .dropdown-menu{z-index:30;min-width:248px;padding:6px;background:var(--sd-surface);border:1px solid var(--sd-border);border-radius:var(--sd-radius);box-shadow:var(--sd-shadow-lg)}:host ::ng-deep .avaya-ipo-classic-input .iti__country-list{max-height:220px;overflow-y:auto;margin:0;padding:0;border:none;box-shadow:none;background:transparent}:host ::ng-deep .avaya-ipo-classic-input .search-container{position:sticky;top:0;z-index:1;padding:0 0 6px;background:var(--sd-surface)}:host ::ng-deep .avaya-ipo-classic-input #country-search-box{width:100%;box-sizing:border-box;margin:0!important;padding:8px 12px!important;font-size:14px!important;font-weight:400!important;letter-spacing:normal!important;color:var(--sd-text)!important;background:var(--sd-input)!important;border:1px solid var(--sd-input-border)!important;border-radius:var(--sd-radius-sm)!important;box-shadow:none!important;height:auto!important;transition:border-color .15s ease,box-shadow .15s ease}:host ::ng-deep .avaya-ipo-classic-input #country-search-box:focus{outline:none!important;border-color:var(--sd-accent)!important;box-shadow:var(--sd-focus-ring)!important}:host ::ng-deep .avaya-ipo-classic-input #country-search-box::placeholder{color:var(--sd-text-subtle)!important}:host ::ng-deep .avaya-ipo-classic-input .iti__country{padding:7px 8px;border-radius:var(--sd-radius-sm);font-size:14px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__country.iti__highlight,:host ::ng-deep .avaya-ipo-classic-input .iti__country:hover{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .iti__country .iti__dial-code{color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti__divider{border-top:1px solid var(--sd-border);margin:4px 0}.avaya-ipo-classic-grid{width:auto;margin:0 auto;display:grid;grid-template-columns:repeat(3,var(--key-size));gap:var(--key-gap);justify-content:center;flex:0 1 auto}.avaya-ipo-classic-grid button{width:var(--key-size);height:var(--key-size);border-radius:50%;border:1.6px solid var(--sd-border-strong);background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-classic-grid button:focus{outline:none;box-shadow:none}.avaya-ipo-classic-grid button:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-classic-grid button:active{background:var(--sd-surface-muted)}.avaya-ipo-classic-grid .avaya-ipo-digit{font-size:clamp(15px,calc(var(--key-size) * .34),26px);font-weight:400;color:var(--sd-text);line-height:1.1}.avaya-ipo-classic-grid .avaya-ipo-letters{font-size:clamp(7px,calc(var(--key-size) * .12),10px);letter-spacing:.8px;color:var(--sd-text-subtle);margin-top:2px}.avaya-ipo-actions{display:flex;justify-content:center;width:100%;margin-top:0}.avaya-ipo-call-btn-main{width:var(--key-size);height:var(--key-size);border-radius:50%;border:none;background:var(--sd-call-accept);color:var(--sd-accent-contrast);display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--sd-shadow-md);cursor:pointer}.avaya-ipo-call-btn-main:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.NgxIntlTelInputComponent, selector: "ngx-intl-tel-input", inputs: ["value", "preferredCountries", "enablePlaceholder", "customPlaceholder", "numberFormat", "cssClass", "onlyCountries", "enableAutoCountrySelect", "searchCountryFlag", "searchCountryField", "searchCountryPlaceholder", "maxLength", "selectFirstCountry", "selectedCountryISO", "phoneValidation", "inputId", "separateDialCode"], outputs: ["countryChange"] }, { kind: "directive", type: i2$1.NativeElementInjectorDirective, selector: "[ngModel], [formControl], [formControlName]" }] });
2903
3247
  }
2904
3248
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: PhoneIdleComponent, decorators: [{
2905
3249
  type: Component,
2906
- args: [{ selector: 'app-phone-idle', standalone: false, template: "<form class=\"avaya-ipo-phone-shell avaya-ipo-classic\" [formGroup]=\"dialForm\" (ngSubmit)=\"onMakeCall()\">\n <div class=\"avaya-ipo-input-row avaya-ipo-classic-input\">\n <ngx-intl-tel-input\n formControlName=\"phoneNumber\"\n name=\"phoneNumber\"\n [cssClass]=\"'avaya-ipo-phone_number_sd'\"\n [preferredCountries]=\"['in']\"\n [customPlaceholder]=\"'Phone Number'\"\n [enableAutoCountrySelect]=\"false\"\n [enablePlaceholder]=\"false\"\n [searchCountryFlag]=\"true\"\n [searchCountryField]=\"[SearchCountryField.Iso2, SearchCountryField.Name]\"\n [selectFirstCountry]=\"false\"\n [selectedCountryISO]=\"CountryISO.India\"\n [maxLength]=\"15\"\n [phoneValidation]=\"true\"\n [separateDialCode]=\"true\"\n (keydown)=\"onKeyboardInput($event)\"\n >\n </ngx-intl-tel-input>\n <button type=\"button\" class=\"avaya-ipo-clear-btn\" (click)=\"onClear()\" aria-label=\"Backspace\" title=\"Backspace\">\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.12c.36.53.9.88 1.59.88h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z\" />\n </svg>\n </button>\n </div>\n\n <div class=\"avaya-ipo-dial-cluster\">\n <div class=\"avaya-ipo-keypad avaya-ipo-classic-grid\">\n <button type=\"button\" (click)=\"onKeypadInput('1')\">\n <span class=\"avaya-ipo-digit\">1</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('2')\">\n <span class=\"avaya-ipo-digit\">2</span>\n <span class=\"avaya-ipo-letters\">ABC</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('3')\">\n <span class=\"avaya-ipo-digit\">3</span>\n <span class=\"avaya-ipo-letters\">DEF</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('4')\">\n <span class=\"avaya-ipo-digit\">4</span>\n <span class=\"avaya-ipo-letters\">GHI</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('5')\">\n <span class=\"avaya-ipo-digit\">5</span>\n <span class=\"avaya-ipo-letters\">JKL</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('6')\">\n <span class=\"avaya-ipo-digit\">6</span>\n <span class=\"avaya-ipo-letters\">MNO</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('7')\">\n <span class=\"avaya-ipo-digit\">7</span>\n <span class=\"avaya-ipo-letters\">PQRS</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('8')\">\n <span class=\"avaya-ipo-digit\">8</span>\n <span class=\"avaya-ipo-letters\">TUV</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('9')\">\n <span class=\"avaya-ipo-digit\">9</span>\n <span class=\"avaya-ipo-letters\">WXYZ</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('*')\">\n <span class=\"avaya-ipo-digit\">*</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('0')\">\n <span class=\"avaya-ipo-digit\">0</span>\n <span class=\"avaya-ipo-letters\">+</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('#')\">\n <span class=\"avaya-ipo-digit\">#</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n </div>\n\n <div class=\"avaya-ipo-actions\">\n <button type=\"submit\" class=\"avaya-ipo-call-btn-main\" [disabled]=\"!this.dialForm.valid\">\n <svg viewBox=\"0 0 512 512\" width=\"22px\" height=\"22px\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M164.9 24.6c-7.7-18.6-28-28.5-47.4-23.2l-88 24C12.1 30.2 0 46 0 64C0 311.4 200.6 512 448 512c18 0 33.8-12.1 38.6-29.5l24-88c5.3-19.4-4.6-39.7-23.2-47.4l-96-40c-16.3-6.8-35.2-2.1-46.3 11.6L304.7 368C234.3 334.7 177.3 277.7 144 207.3L193.3 167c13.7-11.2 18.4-30 11.6-46.3l-40-96z\" />\n </svg>\n </button>\n </div>\n </div>\n</form>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.avaya-ipo-phone-shell.avaya-ipo-classic{--key-size: clamp(40px, min(24cqw, 18cqh - 30px), 88px);--key-gap: calc(var(--key-size) * .16);display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(35px,4.5cqw,30px);background:transparent;width:100%;height:100%;flex:1 1 auto;min-height:0;padding:46px 15px clamp(12px,3cqw,20px);box-sizing:border-box}.avaya-ipo-dial-cluster{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(10px,2.6cqw,18px)}.avaya-ipo-classic-input{width:100%;display:flex;align-items:center;padding:0;box-sizing:border-box;position:relative;border:1.5px solid var(--sd-input-border);border-radius:var(--sd-radius);background:var(--sd-input);box-shadow:var(--sd-shadow-sm);margin-bottom:0;transition:border-color .18s ease,box-shadow .18s ease}.avaya-ipo-classic-input:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-phonebook-btn{border:none;background:transparent;color:var(--sd-text-muted);width:32px;height:32px;border-radius:var(--sd-radius-sm);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;cursor:pointer}.avaya-ipo-phonebook-btn:hover{background:var(--sd-surface-muted)}.avaya-ipo-phonebook-btn:focus{outline:none;box-shadow:none}.avaya-ipo-phonebook-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn{position:absolute;right:clamp(5px,1.6cqw,9px);top:50%;transform:translateY(-50%);width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--sd-text-subtle);border-radius:50%;padding:0;cursor:pointer;transition:background .15s ease,color .15s ease,transform .1s ease}.avaya-ipo-clear-btn:hover{background:var(--sd-surface-muted);color:var(--sd-accent)}.avaya-ipo-clear-btn:active{transform:translateY(-50%) scale(.9)}.avaya-ipo-clear-btn:focus{outline:none;box-shadow:none}.avaya-ipo-clear-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn svg{display:block}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd{width:100%}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input{width:100%;border:none!important;box-shadow:none!important;background:transparent!important;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0!important;font-size:clamp(12px,calc(var(--key-size) * .27),20px)!important;font-weight:600;letter-spacing:.4px;color:var(--sd-text)!important}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input::placeholder{font-weight:400;letter-spacing:normal;color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti{width:100%}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag{padding:0 10px 0 14px;border-right:1px solid var(--sd-border);border-radius:calc(var(--sd-radius) - 2px) 0 0 calc(var(--sd-radius) - 2px);background:transparent;outline:none;transition:background .15s ease}:host ::ng-deep .avaya-ipo-classic-input .iti--allow-dropdown .iti__flag-container:hover .iti__selected-flag{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .selected-dial-code{margin-left:6px;font-size:clamp(12px,calc(var(--key-size) * .18),16px);font-weight:600;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag:focus,:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input:focus,.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input:focus{outline:none;box-shadow:none}:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input{background:transparent!important;border:none!important;box-shadow:none!important;height:auto;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0;font-size:clamp(12px,calc(var(--key-size) * .27),20px);font-weight:600;letter-spacing:.4px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti.separate-dial-code .iti__tel-input{padding-left:102px!important}:host ::ng-deep .avaya-ipo-classic-input .iti__dropdown-content,:host ::ng-deep .avaya-ipo-classic-input .dropdown-menu{z-index:30;min-width:248px;padding:6px;background:var(--sd-surface);border:1px solid var(--sd-border);border-radius:var(--sd-radius);box-shadow:var(--sd-shadow-lg)}:host ::ng-deep .avaya-ipo-classic-input .iti__country-list{max-height:220px;overflow-y:auto;margin:0;padding:0;border:none;box-shadow:none;background:transparent}:host ::ng-deep .avaya-ipo-classic-input .search-container{position:sticky;top:0;z-index:1;padding:0 0 6px;background:var(--sd-surface)}:host ::ng-deep .avaya-ipo-classic-input #country-search-box{width:100%;box-sizing:border-box;margin:0!important;padding:8px 12px!important;font-size:14px!important;font-weight:400!important;letter-spacing:normal!important;color:var(--sd-text)!important;background:var(--sd-input)!important;border:1px solid var(--sd-input-border)!important;border-radius:var(--sd-radius-sm)!important;box-shadow:none!important;height:auto!important;transition:border-color .15s ease,box-shadow .15s ease}:host ::ng-deep .avaya-ipo-classic-input #country-search-box:focus{outline:none!important;border-color:var(--sd-accent)!important;box-shadow:var(--sd-focus-ring)!important}:host ::ng-deep .avaya-ipo-classic-input #country-search-box::placeholder{color:var(--sd-text-subtle)!important}:host ::ng-deep .avaya-ipo-classic-input .iti__country{padding:7px 8px;border-radius:var(--sd-radius-sm);font-size:14px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__country.iti__highlight,:host ::ng-deep .avaya-ipo-classic-input .iti__country:hover{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .iti__country .iti__dial-code{color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti__divider{border-top:1px solid var(--sd-border);margin:4px 0}.avaya-ipo-classic-grid{width:auto;margin:0 auto;display:grid;grid-template-columns:repeat(3,var(--key-size));gap:var(--key-gap);justify-content:center;flex:0 1 auto}.avaya-ipo-classic-grid button{width:var(--key-size);height:var(--key-size);border-radius:50%;border:1.6px solid var(--sd-border-strong);background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-classic-grid button:focus{outline:none;box-shadow:none}.avaya-ipo-classic-grid button:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-classic-grid button:active{background:var(--sd-surface-muted)}.avaya-ipo-classic-grid .avaya-ipo-digit{font-size:clamp(15px,calc(var(--key-size) * .34),26px);font-weight:400;color:var(--sd-text);line-height:1.1}.avaya-ipo-classic-grid .avaya-ipo-letters{font-size:clamp(7px,calc(var(--key-size) * .12),10px);letter-spacing:.8px;color:var(--sd-text-subtle);margin-top:2px}.avaya-ipo-actions{display:flex;justify-content:center;width:100%;margin-top:0}.avaya-ipo-call-btn-main{width:var(--key-size);height:var(--key-size);border-radius:50%;border:none;background:var(--sd-call-accept);color:var(--sd-accent-contrast);display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--sd-shadow-md);cursor:pointer}.avaya-ipo-call-btn-main:disabled{opacity:.4;cursor:not-allowed}\n"] }]
3250
+ args: [{ selector: 'app-phone-idle', standalone: false, template: "<form class=\"avaya-ipo-phone-shell avaya-ipo-classic\" [formGroup]=\"dialForm\" (ngSubmit)=\"onMakeCall()\">\n <div class=\"avaya-ipo-input-row avaya-ipo-classic-input\">\n <ngx-intl-tel-input\n formControlName=\"phoneNumber\"\n name=\"phoneNumber\"\n [cssClass]=\"'avaya-ipo-phone_number_sd'\"\n [preferredCountries]=\"['in']\"\n [customPlaceholder]=\"'Phone Number'\"\n [enableAutoCountrySelect]=\"false\"\n [enablePlaceholder]=\"false\"\n [searchCountryFlag]=\"true\"\n [searchCountryField]=\"[SearchCountryField.Iso2, SearchCountryField.Name]\"\n [selectFirstCountry]=\"false\"\n [selectedCountryISO]=\"CountryISO.India\"\n [maxLength]=\"15\"\n [phoneValidation]=\"true\"\n [separateDialCode]=\"true\"\n (keydown)=\"onKeyboardInput($event)\"\n >\n </ngx-intl-tel-input>\n <button type=\"button\" class=\"avaya-ipo-clear-btn\" (click)=\"onClear()\" aria-label=\"Backspace\" title=\"Backspace\">\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.12c.36.53.9.88 1.59.88h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z\" />\n </svg>\n </button>\n </div>\n\n <div class=\"avaya-ipo-dial-cluster\">\n <div class=\"avaya-ipo-keypad avaya-ipo-classic-grid\">\n <button type=\"button\" (click)=\"onKeypadInput('1')\">\n <span class=\"avaya-ipo-digit\">1</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('2')\">\n <span class=\"avaya-ipo-digit\">2</span>\n <span class=\"avaya-ipo-letters\">ABC</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('3')\">\n <span class=\"avaya-ipo-digit\">3</span>\n <span class=\"avaya-ipo-letters\">DEF</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('4')\">\n <span class=\"avaya-ipo-digit\">4</span>\n <span class=\"avaya-ipo-letters\">GHI</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('5')\">\n <span class=\"avaya-ipo-digit\">5</span>\n <span class=\"avaya-ipo-letters\">JKL</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('6')\">\n <span class=\"avaya-ipo-digit\">6</span>\n <span class=\"avaya-ipo-letters\">MNO</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('7')\">\n <span class=\"avaya-ipo-digit\">7</span>\n <span class=\"avaya-ipo-letters\">PQRS</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('8')\">\n <span class=\"avaya-ipo-digit\">8</span>\n <span class=\"avaya-ipo-letters\">TUV</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('9')\">\n <span class=\"avaya-ipo-digit\">9</span>\n <span class=\"avaya-ipo-letters\">WXYZ</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('*')\">\n <span class=\"avaya-ipo-digit\">*</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('0')\">\n <span class=\"avaya-ipo-digit\">0</span>\n <span class=\"avaya-ipo-letters\">+</span>\n </button>\n <button type=\"button\" (click)=\"onKeypadInput('#')\">\n <span class=\"avaya-ipo-digit\">#</span>\n <span class=\"avaya-ipo-letters\">&nbsp;</span>\n </button>\n </div>\n\n <div class=\"avaya-ipo-actions\">\n <button type=\"submit\" class=\"avaya-ipo-call-btn-main\" [disabled]=\"!this.dialForm.valid\">\n <svg viewBox=\"0 0 512 512\" width=\"22px\" height=\"22px\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M164.9 24.6c-7.7-18.6-28-28.5-47.4-23.2l-88 24C12.1 30.2 0 46 0 64C0 311.4 200.6 512 448 512c18 0 33.8-12.1 38.6-29.5l24-88c5.3-19.4-4.6-39.7-23.2-47.4l-96-40c-16.3-6.8-35.2-2.1-46.3 11.6L304.7 368C234.3 334.7 177.3 277.7 144 207.3L193.3 167c13.7-11.2 18.4-30 11.6-46.3l-40-96z\" />\n </svg>\n </button>\n </div>\n </div>\n</form>\n", styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0}.avaya-ipo-phone-shell.avaya-ipo-classic{--key-size: clamp(40px, min(24cqw, 18cqh - 30px), 88px);--key-gap: calc(var(--key-size) * .16);display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(35px,4.5cqw,30px);background:transparent;width:100%;height:100%;flex:1 1 auto;min-height:0;padding:46px 15px clamp(12px,3cqw,20px);box-sizing:border-box}.avaya-ipo-dial-cluster{flex:1 1 auto;min-height:0;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(10px,2.6cqw,18px)}.avaya-ipo-classic-input{width:100%;display:flex;align-items:center;padding:0;box-sizing:border-box;position:relative;border:1.5px solid var(--sd-input-border);border-radius:var(--sd-radius);background:var(--sd-input);box-shadow:var(--sd-shadow-sm);margin-bottom:0;transition:border-color .18s ease,box-shadow .18s ease}.avaya-ipo-classic-input:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn{position:absolute;right:clamp(5px,1.6cqw,9px);top:50%;transform:translateY(-50%);width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--sd-text-subtle);border-radius:50%;padding:0;cursor:pointer;transition:background .15s ease,color .15s ease,transform .1s ease}.avaya-ipo-clear-btn:hover{background:var(--sd-surface-muted);color:var(--sd-accent)}.avaya-ipo-clear-btn:active{transform:translateY(-50%) scale(.9)}.avaya-ipo-clear-btn:focus{outline:none;box-shadow:none}.avaya-ipo-clear-btn:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-clear-btn svg{display:block}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd{width:100%}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input{width:100%;border:none!important;box-shadow:none!important;background:transparent!important;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0!important;font-size:clamp(12px,calc(var(--key-size) * .27),20px)!important;font-weight:600;letter-spacing:.4px;color:var(--sd-text)!important}.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input::placeholder{font-weight:400;letter-spacing:normal;color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti{width:100%}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag{padding:0 10px 0 14px;border-right:1px solid var(--sd-border);border-radius:calc(var(--sd-radius) - 2px) 0 0 calc(var(--sd-radius) - 2px);background:transparent;outline:none;transition:background .15s ease}:host ::ng-deep .avaya-ipo-classic-input .iti--allow-dropdown .iti__flag-container:hover .iti__selected-flag{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .selected-dial-code{margin-left:6px;font-size:clamp(12px,calc(var(--key-size) * .18),16px);font-weight:600;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__selected-flag:focus,:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input:focus,.avaya-ipo-classic-input .avaya-ipo-phone_number_sd input:focus{outline:none;box-shadow:none}:host ::ng-deep .avaya-ipo-classic-input .iti__tel-input{background:transparent!important;border:none!important;box-shadow:none!important;height:auto;padding:clamp(8px,calc(var(--key-size) * .16),15px) 46px clamp(8px,calc(var(--key-size) * .16),15px) 0;font-size:clamp(12px,calc(var(--key-size) * .27),20px);font-weight:600;letter-spacing:.4px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti.separate-dial-code .iti__tel-input{padding-left:102px!important}:host ::ng-deep .avaya-ipo-classic-input .iti__dropdown-content,:host ::ng-deep .avaya-ipo-classic-input .dropdown-menu{z-index:30;min-width:248px;padding:6px;background:var(--sd-surface);border:1px solid var(--sd-border);border-radius:var(--sd-radius);box-shadow:var(--sd-shadow-lg)}:host ::ng-deep .avaya-ipo-classic-input .iti__country-list{max-height:220px;overflow-y:auto;margin:0;padding:0;border:none;box-shadow:none;background:transparent}:host ::ng-deep .avaya-ipo-classic-input .search-container{position:sticky;top:0;z-index:1;padding:0 0 6px;background:var(--sd-surface)}:host ::ng-deep .avaya-ipo-classic-input #country-search-box{width:100%;box-sizing:border-box;margin:0!important;padding:8px 12px!important;font-size:14px!important;font-weight:400!important;letter-spacing:normal!important;color:var(--sd-text)!important;background:var(--sd-input)!important;border:1px solid var(--sd-input-border)!important;border-radius:var(--sd-radius-sm)!important;box-shadow:none!important;height:auto!important;transition:border-color .15s ease,box-shadow .15s ease}:host ::ng-deep .avaya-ipo-classic-input #country-search-box:focus{outline:none!important;border-color:var(--sd-accent)!important;box-shadow:var(--sd-focus-ring)!important}:host ::ng-deep .avaya-ipo-classic-input #country-search-box::placeholder{color:var(--sd-text-subtle)!important}:host ::ng-deep .avaya-ipo-classic-input .iti__country{padding:7px 8px;border-radius:var(--sd-radius-sm);font-size:14px;color:var(--sd-text)}:host ::ng-deep .avaya-ipo-classic-input .iti__country.iti__highlight,:host ::ng-deep .avaya-ipo-classic-input .iti__country:hover{background:var(--sd-surface-muted)}:host ::ng-deep .avaya-ipo-classic-input .iti__country .iti__dial-code{color:var(--sd-text-subtle)}:host ::ng-deep .avaya-ipo-classic-input .iti__divider{border-top:1px solid var(--sd-border);margin:4px 0}.avaya-ipo-classic-grid{width:auto;margin:0 auto;display:grid;grid-template-columns:repeat(3,var(--key-size));gap:var(--key-gap);justify-content:center;flex:0 1 auto}.avaya-ipo-classic-grid button{width:var(--key-size);height:var(--key-size);border-radius:50%;border:1.6px solid var(--sd-border-strong);background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-classic-grid button:focus{outline:none;box-shadow:none}.avaya-ipo-classic-grid button:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-classic-grid button:active{background:var(--sd-surface-muted)}.avaya-ipo-classic-grid .avaya-ipo-digit{font-size:clamp(15px,calc(var(--key-size) * .34),26px);font-weight:400;color:var(--sd-text);line-height:1.1}.avaya-ipo-classic-grid .avaya-ipo-letters{font-size:clamp(7px,calc(var(--key-size) * .12),10px);letter-spacing:.8px;color:var(--sd-text-subtle);margin-top:2px}.avaya-ipo-actions{display:flex;justify-content:center;width:100%;margin-top:0}.avaya-ipo-call-btn-main{width:var(--key-size);height:var(--key-size);border-radius:50%;border:none;background:var(--sd-call-accept);color:var(--sd-accent-contrast);display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--sd-shadow-md);cursor:pointer}.avaya-ipo-call-btn-main:disabled{opacity:.4;cursor:not-allowed}\n"] }]
2907
3251
  }], propDecorators: { dialForm: [{
2908
3252
  type: Input
2909
3253
  }], contacts: [{
@@ -3108,6 +3452,9 @@ class PhoneComponent {
3108
3452
  turnIp;
3109
3453
  turnPort;
3110
3454
  configurationMode;
3455
+ recordingUploadMode;
3456
+ /** Entity id of the call counterpart (resolved by the shell) — included in recording metadata. */
3457
+ entityId;
3111
3458
  makeCallEv = new EventEmitter();
3112
3459
  endCallEv = new EventEmitter();
3113
3460
  audioElement;
@@ -3127,7 +3474,6 @@ class PhoneComponent {
3127
3474
  pendingTranscriptionCallId = null;
3128
3475
  pendingTranscriptionAllowBinary = false;
3129
3476
  lastPartialIndex = {};
3130
- pendingIncomingCall = false;
3131
3477
  dialForm;
3132
3478
  directoryForm;
3133
3479
  showDirectoryPhonebook = false;
@@ -3245,7 +3591,6 @@ class PhoneComponent {
3245
3591
  }
3246
3592
  if (evt.state === CallState.CONNECTED) {
3247
3593
  this.isRinging = false;
3248
- this.pendingIncomingCall = false;
3249
3594
  this._isActiveCall = true;
3250
3595
  if (evt.callId) {
3251
3596
  this.currentCallId = evt.callId;
@@ -3278,7 +3623,6 @@ class PhoneComponent {
3278
3623
  this.pendingTranscriptionAllowBinary = false;
3279
3624
  }
3280
3625
  this.isRinging = false;
3281
- this.pendingIncomingCall = false;
3282
3626
  this._isActiveCall = false;
3283
3627
  this.isMuted = false;
3284
3628
  this.isHeld = false;
@@ -3365,7 +3709,6 @@ class PhoneComponent {
3365
3709
  this.pendingTranscriptionAllowBinary = false;
3366
3710
  }
3367
3711
  this.isRinging = false;
3368
- this.pendingIncomingCall = false;
3369
3712
  this._isActiveCall = false;
3370
3713
  this.incomingCallNumber = undefined;
3371
3714
  this.currentCallId = null;
@@ -3378,16 +3721,6 @@ class PhoneComponent {
3378
3721
  this.cdr.detectChanges();
3379
3722
  });
3380
3723
  }
3381
- ngOnChanges(changes) {
3382
- if (changes['incomingNameResolved'] && this.pendingIncomingCall) {
3383
- if (this.incomingNameResolved) {
3384
- this.isRinging = true;
3385
- this.pendingIncomingCall = false;
3386
- this.emitCallScreenState();
3387
- this.cdr.detectChanges();
3388
- }
3389
- }
3390
- }
3391
3724
  ngAfterViewInit() {
3392
3725
  this.audio = this.audioElement?.nativeElement;
3393
3726
  }
@@ -3493,7 +3826,6 @@ class PhoneComponent {
3493
3826
  declineAvayaCall() {
3494
3827
  this.suppressHangupToneOnce = true;
3495
3828
  this.isRinging = false;
3496
- this.pendingIncomingCall = false;
3497
3829
  this._isActiveCall = false;
3498
3830
  this.pendingOutgoing = false;
3499
3831
  this.avayaIpoService.clearOutgoingDial();
@@ -3510,7 +3842,6 @@ class PhoneComponent {
3510
3842
  this.avayaIpoService.answerCall();
3511
3843
  // this.headerComponent.showAvayaIpo = true;
3512
3844
  this.isRinging = false;
3513
- this.pendingIncomingCall = false;
3514
3845
  this._isActiveCall = true;
3515
3846
  this.callStatusText = '';
3516
3847
  this.startCallTimer();
@@ -3606,8 +3937,10 @@ class PhoneComponent {
3606
3937
  this.contactSearch = '';
3607
3938
  this.directoryForm.reset();
3608
3939
  this.callStatusText = '';
3609
- this.isRinging = this.incomingNameResolved;
3610
- this.pendingIncomingCall = !this.incomingNameResolved;
3940
+ // Show the ringing screen IMMEDIATELY — the caller-name lookups resolve in place (the template
3941
+ // shows the number first and fills the name when ready). Holding the screen until
3942
+ // incomingNameResolved meant two network round trips of blank UI while the phone was ringing.
3943
+ this.isRinging = true;
3611
3944
  if (this.endToneTimeout) {
3612
3945
  clearTimeout(this.endToneTimeout);
3613
3946
  this.endToneTimeout = undefined;
@@ -4100,6 +4433,7 @@ class PhoneComponent {
4100
4433
  agentId: this.agentId || '',
4101
4434
  phoneNumber: this.activeCallNumber || '',
4102
4435
  callId,
4436
+ entityId: this.entityId || undefined,
4103
4437
  };
4104
4438
  if (!hasAudio(local)) {
4105
4439
  console.warn('[Phone] Missing local audio, requesting mic', callId);
@@ -4117,7 +4451,7 @@ class PhoneComponent {
4117
4451
  }
4118
4452
  const remote = this.lastRemoteStream;
4119
4453
  if (hasAudio(remote)) {
4120
- this.recordingManagerService.startRecording(local, remote, metadata);
4454
+ this.recordingManagerService.startRecording(local, remote, metadata, this.resolvedRecordingMode());
4121
4455
  return;
4122
4456
  }
4123
4457
  const remoteSub = this.avayaIpoService.remoteStream$.subscribe((r) => {
@@ -4132,12 +4466,18 @@ class PhoneComponent {
4132
4466
  return;
4133
4467
  }
4134
4468
  console.debug('[Phone] Remote audio ready, restarting recording', callId);
4135
- this.recordingManagerService.startRecording(freshLocal, r.stream, metadata);
4469
+ this.recordingManagerService.startRecording(freshLocal, r.stream, metadata, this.resolvedRecordingMode());
4136
4470
  remoteSub.unsubscribe();
4137
4471
  });
4138
4472
  }
4473
+ /** Per-embed [recordingUploadMode] wins; otherwise the APP_CONFIG default applies. */
4474
+ resolvedRecordingMode() {
4475
+ return this.recordingUploadMode === 'chunked' || this.recordingUploadMode === 'complete'
4476
+ ? this.recordingUploadMode
4477
+ : APP_CONFIG.RECORDING_UPLOAD_MODE;
4478
+ }
4139
4479
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: PhoneComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$2.FormBuilder }, { token: AvayaIPOService }, { token: AuthenticationService }, { token: RecordingManagerService }, { token: TranscriptionStreamService }], target: i0.ɵɵFactoryTarget.Component });
4140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: PhoneComponent, isStandalone: false, selector: "app-phone", inputs: { contacts: "contacts", tenantId: "tenantId", agentId: "agentId", isActiveCall: "isActiveCall", activeCallNumber: "activeCallNumber", incomingCallName: "incomingCallName", incomingNameResolved: "incomingNameResolved", activeCallName: "activeCallName", serverIp: "serverIp", serverPort: "serverPort", stunIp: "stunIp", stunPort: "stunPort", turnIp: "turnIp", turnPort: "turnPort", configurationMode: "configurationMode" }, outputs: { callScreenChange: "callScreenChange", makeCallEv: "makeCallEv", endCallEv: "endCallEv" }, viewQueries: [{ propertyName: "audioElement", first: true, predicate: ["audioElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"avaya-ipo-phone-container\">\n <audio id=\"sd_call_ring\" #audioElement></audio>\n\n @if (isRinging) {\n <app-phone-incoming [incomingCallNumber]=\"incomingCallNumber\" [incomingCallName]=\"incomingCallName\" [incomingNameResolved]=\"incomingNameResolved\" (accept)=\"acceptAvayaCAll()\"\n (decline)=\"declineAvayaCall()\"></app-phone-incoming>\n } @else if (isActiveCall) {\n <app-phone-active [tenantId]=\"tenantId\" [activeCallNumber]=\"activeCallNumber\" [activeCallName]=\"activeCallName\"\n [activeCallDuration]=\"activeCallDuration\" [callStatusText]=\"callStatusText\" [isConnecting]=\"isConnecting\"\n [isMuted]=\"isMuted\" [isHeld]=\"isHeld\"\n (toggleMute)=\"toggleMute()\" (toggleHold)=\"toggleHold()\" (transfer)=\"onTransferCall()\"\n (openContacts)=\"onActiveOpenContacts()\" (openKeypad)=\"onActiveOpenKeypad()\"\n (startTranscription)=\"openTranscription()\" (contactsLoaded)=\"onContactsLoaded($event)\"\n (endCall)=\"onEndActiveCall()\"></app-phone-active>\n } @else {\n <app-phone-idle [dialForm]=\"dialForm\" [contacts]=\"contacts\" [showDirectoryPhonebook]=\"showDirectoryPhonebook\"\n [isRinging]=\"isRinging\" [CountryISO]=\"CountryISO\" [SearchCountryField]=\"SearchCountryField\"\n (toggleDirectory)=\"onIdleToggleDirectory()\" (clear)=\"onIdleClear()\" (makeCall)=\"onIdleMakeCall()\"\n (keypadInput)=\"onIdleKeypadInput($event)\" (keyboardInput)=\"onIdleKeyboardInput($event)\"></app-phone-idle>\n }\n</div>\n\n@if (showDirectoryPhonebook) {\n<div class=\"avaya-ipo-phonebook-overlay\">\n <div class=\"avaya-ipo-phonebook-sheet\">\n <div class=\"avaya-ipo-phonebook-header\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-back\" (click)=\"onClosePhonebook()\">\u2039</button>\n <div class=\"avaya-ipo-phonebook-titles\">\n <div class=\"avaya-ipo-phonebook-kicker\">{{ isTransferMode ? 'Transfer Call' : 'Add Call' }}</div>\n <div class=\"avaya-ipo-phonebook-title\">Directory</div>\n </div>\n <button type=\"button\" class=\"avaya-ipo-phonebook-add\" disabled>\uFF0B</button>\n </div>\n @if (transferError) {\n <div class=\"avaya-ipo-phonebook-error\">{{ transferError }}</div>\n }\n @if (transferSuccess) {\n <div class=\"avaya-ipo-phonebook-success\">{{ transferSuccess }}</div>\n }\n\n <div class=\"avaya-ipo-phonebook-tabs\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-tab\" [class.avaya-ipo-active]=\"directoryTab === 'contacts'\"\n (click)=\"setDirectoryTab('contacts')\">\n Contacts\n </button>\n <button type=\"button\" class=\"avaya-ipo-phonebook-tab\" [class.avaya-ipo-active]=\"directoryTab === 'dialpad'\"\n (click)=\"setDirectoryTab('dialpad')\">\n Dialpad\n </button>\n </div>\n\n <div class=\"avaya-ipo-phonebook-list\">\n @if (directoryTab === 'contacts') {\n <div class=\"avaya-ipo-phonebook-search\">\n <span class=\"avaya-ipo-search-icon\">\uD83D\uDD0D</span>\n <input type=\"text\" placeholder=\"Search\" [value]=\"contactSearch\"\n (input)=\"contactSearch = ($any($event.target).value)\" />\n </div>\n\n @if (filteredContacts?.length) {\n @for (contact of filteredContacts; track contact.id ?? contact.phone ?? $index) {\n <button type=\"button\" class=\"avaya-ipo-phonebook-item\" (click)=\"onSelectContact(contact)\">\n <span class=\"avaya-ipo-phonebook-avatar\">{{ (contact.name || contact.phone || 'U') | slice:0:2 }}</span>\n <span class=\"avaya-ipo-phonebook-name\">{{ contact.name || 'Unknown' }}</span>\n <span class=\"avaya-ipo-phonebook-number\">{{ contact.phone || '' }}</span>\n </button>\n }\n } @else {\n <div class=\"avaya-ipo-phonebook-empty\">No contacts found</div>\n }\n } @else {\n <div class=\"avaya-ipo-phonebook-dialpad\">\n <div class=\"avaya-ipo-dialpad-input\" [formGroup]=\"directoryForm\">\n <ngx-intl-tel-input formControlName=\"phoneNumber\" name=\"phoneNumber\" [cssClass]=\"'avaya-ipo-phone_number_sd'\"\n [preferredCountries]=\"['in']\" [customPlaceholder]=\"'Phone Number'\" [enableAutoCountrySelect]=\"false\"\n [enablePlaceholder]=\"false\" [searchCountryFlag]=\"true\"\n [searchCountryField]=\"[SearchCountryField.Iso2, SearchCountryField.Name]\" [selectFirstCountry]=\"false\"\n [selectedCountryISO]=\"CountryISO.India\" [maxLength]=\"15\" [phoneValidation]=\"true\" [separateDialCode]=\"true\">\n </ngx-intl-tel-input>\n <button type=\"button\" class=\"avaya-ipo-dialpad-backspace\" (click)=\"onDirectoryBackspace()\">\u232B</button>\n </div>\n\n <div class=\"avaya-ipo-dialpad-grid\">\n @for (item of directoryDigits; track item.digit) {\n <button type=\"button\" class=\"avaya-ipo-dialpad-key\" (click)=\"onDirectoryKeypad(item.digit)\">\n <span class=\"avaya-ipo-dialpad-digit\">{{ item.digit }}</span>\n <span class=\"avaya-ipo-dialpad-letters\">{{ item.letters || '\\u00a0' }}</span>\n </button>\n }\n </div>\n\n <button type=\"button\" class=\"avaya-ipo-dialpad-action\" [disabled]=\"!(directoryForm.valid || directoryNumber)\"\n (click)=\"onDirectoryUseNumber()\">\n {{ isTransferMode ? 'Transfer' : 'Add Call' }}\n </button>\n </div>\n }\n </div>\n </div>\n</div>\n}\n\n@if (isKeypadOpen) {\n<div class=\"avaya-ipo-phonebook-overlay\">\n <div class=\"avaya-ipo-phonebook-sheet avaya-ipo-keypad-sheet\">\n <div class=\"avaya-ipo-phonebook-header\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-back\" (click)=\"closeKeypad()\">\u2039</button>\n <div class=\"avaya-ipo-phonebook-titles\">\n <div class=\"avaya-ipo-phonebook-kicker\">DTMF</div>\n <div class=\"avaya-ipo-phonebook-title\">Keypad</div>\n </div>\n <button type=\"button\" class=\"avaya-ipo-phonebook-add\" disabled>\uFF0B</button>\n </div>\n\n <div class=\"avaya-ipo-dialpad-input avaya-ipo-dtmf-input\">\n <div class=\"avaya-ipo-dtmf-text\">{{ dtmfBuffer || ' ' }}</div>\n </div>\n\n <div class=\"avaya-ipo-phonebook-dialpad\">\n <div class=\"avaya-ipo-dialpad-grid\">\n @for (item of directoryDigits; track item.digit) {\n <button type=\"button\" class=\"avaya-ipo-dialpad-key\" (click)=\"onDtmfDigit(item.digit)\">\n <div class=\"avaya-ipo-dialpad-digit\">{{ item.digit }}</div>\n @if (item.letters) {\n <div class=\"avaya-ipo-dialpad-letters\">{{ item.letters }}</div>\n }\n </button>\n }\n </div>\n\n <button type=\"button\" class=\"avaya-ipo-dialpad-action\" (click)=\"closeKeypad()\">Done</button>\n </div>\n </div>\n</div>\n}\n\n@if (isTranscriptionOpen) {\n<div class=\"avaya-ipo-phonebook-overlay\">\n <div class=\"avaya-ipo-phonebook-sheet avaya-ipo-transcription-sheet\">\n <div class=\"avaya-ipo-phonebook-header\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-back\" (click)=\"closeTranscription()\">\u2039</button>\n <div class=\"avaya-ipo-phonebook-titles\">\n <div class=\"avaya-ipo-phonebook-title\">Live Transcription</div>\n </div>\n </div>\n <div class=\"avaya-ipo-transcription-body\">\n @if (transcriptSegments?.length) {\n <div class=\"avaya-ipo-transcription-split\">\n <div class=\"avaya-ipo-transcription-panel\">\n <div class=\"avaya-ipo-transcription-panel-title\">\n Customer\n </div>\n <div class=\"avaya-ipo-transcription-panel-body\">\n @if (customerTranscriptSegments.length) {\n @for (segment of customerTranscriptSegments; track segment.ts ?? $index) {\n <div class=\"avaya-ipo-transcription-line\">{{ segment.text }}</div>\n }\n } @else {\n <div class=\"avaya-ipo-transcription-placeholder\">No customer speech yet.</div>\n }\n </div>\n </div>\n <div class=\"avaya-ipo-transcription-panel\">\n <div class=\"avaya-ipo-transcription-panel-title\">\n Agent\n </div>\n <div class=\"avaya-ipo-transcription-panel-body\">\n @if (agentTranscriptSegments.length) {\n @for (segment of agentTranscriptSegments; track segment.ts ?? $index) {\n <div class=\"avaya-ipo-transcription-line\">{{ segment.text }}</div>\n }\n } @else {\n <div class=\"avaya-ipo-transcription-placeholder\">No agent speech yet.</div>\n }\n </div>\n </div>\n </div>\n } @else {\n <div class=\"avaya-ipo-transcription-placeholder\">Live transcription will appear here.</div>\n }\n </div>\n </div>\n</div>\n}\n", styles: [":host{display:block;height:100%}.avaya-ipo-phone-container{width:100%;box-sizing:border-box;padding:0;background:transparent;border-radius:0;min-height:100%;height:100%;position:relative;container-type:size}.avaya-ipo-phonebook-overlay{position:absolute;inset:0;background:#00000059;display:flex;align-items:flex-end;justify-content:center;z-index:100}.avaya-ipo-phonebook-sheet{width:100%;max-width:100%;height:90%;max-height:100%;background:var(--sd-surface-muted);color:var(--sd-text);border-radius:var(--sd-radius-lg) var(--sd-radius-lg) 0 0;overflow:hidden;border:1px solid var(--sd-border);display:flex;flex-direction:column;animation:sheet-slide-up .22s ease}.avaya-ipo-keypad-sheet{height:82%}.avaya-ipo-transcription-sheet{height:90%}.avaya-ipo-transcription-body{flex:1 1 auto;padding:12px 18px 20px;overflow-y:auto}.avaya-ipo-transcription-split{display:flex;flex-direction:column;gap:12px;height:100%}.avaya-ipo-transcription-panel{flex:1 1 0;border:1px solid var(--sd-border);border-radius:var(--sd-radius);background:var(--sd-card);display:flex;flex-direction:column;min-height:0}.avaya-ipo-transcription-panel-title{font-size:12px;font-weight:700;color:var(--sd-text-muted);padding:8px 12px;border-bottom:1px solid var(--sd-border);background:var(--sd-surface-muted)}.avaya-ipo-transcription-panel-body{flex:1 1 auto;padding:10px 12px;overflow-y:auto;display:flex;flex-direction:column;gap:6px}.avaya-ipo-transcription-line{font-size:14px;color:var(--sd-text);line-height:1.5;white-space:pre-wrap}.avaya-ipo-transcription-panel .avaya-ipo-transcription-placeholder{font-size:12px;color:var(--sd-text-subtle)}.avaya-ipo-transcription-placeholder{font-size:13px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-header{display:flex;align-items:center;justify-content:space-between;padding:18px 18px 8px}.avaya-ipo-phonebook-titles{text-align:center;display:flex;flex-direction:column;gap:4px;flex:1 1 auto}.avaya-ipo-phonebook-kicker{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-title{font-size:18px;font-weight:700;color:var(--sd-text)}.avaya-ipo-phonebook-back,.avaya-ipo-phonebook-add{width:36px;height:36px;border-radius:50%;border:1px solid var(--sd-border);background:var(--sd-card);color:var(--sd-text-muted);font-size:18px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-phonebook-back:hover,.avaya-ipo-phonebook-add:hover{background:var(--sd-surface-muted)}.avaya-ipo-phonebook-add:disabled{opacity:.4;cursor:default}.avaya-ipo-phonebook-error{margin:0 16px 8px;padding:8px 10px;border-radius:var(--sd-radius);background:var(--sd-accent-soft);color:var(--sd-call-end);font-size:12px;font-weight:600;text-align:center}.avaya-ipo-phonebook-success{margin:0 16px 8px;padding:8px 10px;border-radius:var(--sd-radius);background:#1aa2511f;color:var(--sd-call-accept);font-size:12px;font-weight:600;text-align:center}.avaya-ipo-phonebook-tabs{margin:4px 16px 8px;display:flex;gap:8px;background:var(--sd-card);border:1px solid var(--sd-border);padding:4px;border-radius:var(--sd-radius-lg)}.avaya-ipo-phonebook-tab{flex:1 1 0;border:none;background:transparent;color:var(--sd-text-muted);font-size:13px;padding:8px 0;border-radius:var(--sd-radius);cursor:pointer}.avaya-ipo-phonebook-tab.avaya-ipo-active{background:var(--sd-accent);color:var(--sd-accent-contrast)}.avaya-ipo-phonebook-search{margin:8px 16px 14px;display:flex;align-items:center;gap:8px;padding:10px 14px;border-radius:var(--sd-radius-sm);background:var(--sd-input);border:1px solid var(--sd-input-border);color:var(--sd-text)}.avaya-ipo-phonebook-search:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-phonebook-search input{flex:1 1 auto;background:transparent;border:none;outline:none;color:var(--sd-text);font-size:14px}.avaya-ipo-phonebook-search input::placeholder{color:var(--sd-text-subtle)}.avaya-ipo-phonebook-list{flex:1 1 auto;overflow-y:auto}.avaya-ipo-phonebook-item{width:100%;text-align:left;padding:12px 18px;border:none;background:transparent;display:grid;grid-template-columns:40px 1fr;grid-template-rows:auto auto;column-gap:12px;row-gap:2px;cursor:pointer;border-bottom:1px solid var(--sd-border)}.avaya-ipo-phonebook-item:hover{background:var(--sd-surface-muted)}.avaya-ipo-phonebook-item:last-child{border-bottom:none}.avaya-ipo-phonebook-avatar{width:40px;height:40px;border-radius:50%;background:var(--sd-avatar);color:var(--sd-text-muted);display:inline-flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;grid-row:span 2}.avaya-ipo-phonebook-name{font-size:13px;font-weight:600;color:var(--sd-text)}.avaya-ipo-phonebook-number{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-empty{padding:18px;font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-dialpad{padding:10px 16px 18px;display:flex;flex-direction:column;gap:14px}.avaya-ipo-dialpad-input{display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:var(--sd-radius-sm);border:1px solid var(--sd-input-border);background:var(--sd-input)}.avaya-ipo-dialpad-input:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-dialpad-input .avaya-ipo-phone_number_sd{width:100%}.avaya-ipo-dialpad-input input{flex:1 1 auto;border:none;outline:none;font-size:16px;background:transparent;color:var(--sd-text)}.avaya-ipo-dialpad-backspace{border:none;background:transparent;font-size:16px;cursor:pointer;color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-dialpad-input .iti{width:100%}:host ::ng-deep .avaya-ipo-dialpad-input .iti__flag-container{padding-left:6px}:host ::ng-deep .avaya-ipo-dialpad-input .iti__selected-flag{border-right:1px solid var(--sd-border);padding-right:8px}:host ::ng-deep .avaya-ipo-dialpad-input .iti.separate-dial-code input{padding-left:130px!important}:host ::ng-deep .avaya-ipo-dialpad-input .iti__tel-input{background:transparent;border:none;box-shadow:none;height:32px;padding:0 0 0 6px;font-size:15px;color:var(--sd-text)}.avaya-ipo-dialpad-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(8px,3%,12px);justify-items:center}.avaya-ipo-dialpad-key{width:clamp(52px,18%,68px);aspect-ratio:1;height:auto;border-radius:50%;border:1.6px solid var(--sd-border-strong);background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-dialpad-key:focus{outline:none;box-shadow:none}.avaya-ipo-dialpad-key:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-dialpad-key:active{background:var(--sd-surface-muted)}.avaya-ipo-dialpad-digit{font-size:24px;font-weight:400;color:var(--sd-text);line-height:24px}.avaya-ipo-dialpad-letters{font-size:9px;letter-spacing:.8px;color:var(--sd-text-subtle);margin-top:2px}.avaya-ipo-dialpad-action{border:none;border-radius:var(--sd-radius);padding:12px 0;background:var(--sd-accent);color:var(--sd-accent-contrast);font-size:14px;font-weight:600;cursor:pointer}.avaya-ipo-dialpad-action:hover{background:var(--sd-accent-strong)}.avaya-ipo-dialpad-action:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-dialpad-action:disabled{opacity:.5;cursor:default}.avaya-ipo-dtmf-input{margin:0 16px 6px}.avaya-ipo-dtmf-text{flex:1 1 auto;text-align:center;font-size:18px;letter-spacing:1px;color:var(--sd-text);min-height:24px}@keyframes sheet-slide-up{0%{transform:translateY(24px);opacity:.6}to{transform:translateY(0);opacity:1}}\n"], dependencies: [{ kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.NgxIntlTelInputComponent, selector: "ngx-intl-tel-input", inputs: ["value", "preferredCountries", "enablePlaceholder", "customPlaceholder", "numberFormat", "cssClass", "onlyCountries", "enableAutoCountrySelect", "searchCountryFlag", "searchCountryField", "searchCountryPlaceholder", "maxLength", "selectFirstCountry", "selectedCountryISO", "phoneValidation", "inputId", "separateDialCode"], outputs: ["countryChange"] }, { kind: "directive", type: i2$1.NativeElementInjectorDirective, selector: "[ngModel], [formControl], [formControlName]" }, { kind: "component", type: PhoneIdleComponent, selector: "app-phone-idle", inputs: ["dialForm", "contacts", "showDirectoryPhonebook", "isRinging", "CountryISO", "SearchCountryField"], outputs: ["toggleDirectory", "clear", "makeCall", "keypadInput", "keyboardInput"] }, { kind: "component", type: PhoneIncomingComponent, selector: "app-phone-incoming", inputs: ["incomingCallName", "incomingNameResolved", "incomingCallNumber"], outputs: ["accept", "decline"] }, { kind: "component", type: PhoneActiveComponent, selector: "app-phone-active", inputs: ["tenantId", "activeCallName", "activeCallNumber", "activeCallDuration", "callStatusText", "isConnecting", "isMuted", "isHeld"], outputs: ["endCall", "toggleMute", "toggleHold", "transfer", "openContacts", "openKeypad", "startTranscription", "contactsLoaded"] }, { kind: "pipe", type: i2.SlicePipe, name: "slice" }] });
4480
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: PhoneComponent, isStandalone: false, selector: "app-phone", inputs: { contacts: "contacts", tenantId: "tenantId", agentId: "agentId", isActiveCall: "isActiveCall", activeCallNumber: "activeCallNumber", incomingCallName: "incomingCallName", incomingNameResolved: "incomingNameResolved", activeCallName: "activeCallName", serverIp: "serverIp", serverPort: "serverPort", stunIp: "stunIp", stunPort: "stunPort", turnIp: "turnIp", turnPort: "turnPort", configurationMode: "configurationMode", recordingUploadMode: "recordingUploadMode", entityId: "entityId" }, outputs: { callScreenChange: "callScreenChange", makeCallEv: "makeCallEv", endCallEv: "endCallEv" }, viewQueries: [{ propertyName: "audioElement", first: true, predicate: ["audioElement"], descendants: true }], ngImport: i0, template: "<div class=\"avaya-ipo-phone-container\">\n <audio id=\"sd_call_ring\" #audioElement></audio>\n\n @if (isRinging) {\n <app-phone-incoming [incomingCallNumber]=\"incomingCallNumber\" [incomingCallName]=\"incomingCallName\" [incomingNameResolved]=\"incomingNameResolved\" (accept)=\"acceptAvayaCAll()\"\n (decline)=\"declineAvayaCall()\"></app-phone-incoming>\n } @else if (isActiveCall) {\n <app-phone-active [tenantId]=\"tenantId\" [activeCallNumber]=\"activeCallNumber\" [activeCallName]=\"activeCallName\"\n [activeCallDuration]=\"activeCallDuration\" [callStatusText]=\"callStatusText\" [isConnecting]=\"isConnecting\"\n [isMuted]=\"isMuted\" [isHeld]=\"isHeld\"\n (toggleMute)=\"toggleMute()\" (toggleHold)=\"toggleHold()\" (transfer)=\"onTransferCall()\"\n (openContacts)=\"onActiveOpenContacts()\" (openKeypad)=\"onActiveOpenKeypad()\"\n (startTranscription)=\"openTranscription()\" (contactsLoaded)=\"onContactsLoaded($event)\"\n (endCall)=\"onEndActiveCall()\"></app-phone-active>\n } @else {\n <app-phone-idle [dialForm]=\"dialForm\" [contacts]=\"contacts\" [showDirectoryPhonebook]=\"showDirectoryPhonebook\"\n [isRinging]=\"isRinging\" [CountryISO]=\"CountryISO\" [SearchCountryField]=\"SearchCountryField\"\n (toggleDirectory)=\"onIdleToggleDirectory()\" (clear)=\"onIdleClear()\" (makeCall)=\"onIdleMakeCall()\"\n (keypadInput)=\"onIdleKeypadInput($event)\" (keyboardInput)=\"onIdleKeyboardInput($event)\"></app-phone-idle>\n }\n</div>\n\n@if (showDirectoryPhonebook) {\n<div class=\"avaya-ipo-phonebook-overlay\">\n <div class=\"avaya-ipo-phonebook-sheet\">\n <div class=\"avaya-ipo-phonebook-header\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-back\" (click)=\"onClosePhonebook()\">\u2039</button>\n <div class=\"avaya-ipo-phonebook-titles\">\n <div class=\"avaya-ipo-phonebook-kicker\">{{ isTransferMode ? 'Transfer Call' : 'Add Call' }}</div>\n <div class=\"avaya-ipo-phonebook-title\">Directory</div>\n </div>\n <button type=\"button\" class=\"avaya-ipo-phonebook-add\" disabled>\uFF0B</button>\n </div>\n @if (transferError) {\n <div class=\"avaya-ipo-phonebook-error\">{{ transferError }}</div>\n }\n @if (transferSuccess) {\n <div class=\"avaya-ipo-phonebook-success\">{{ transferSuccess }}</div>\n }\n\n <div class=\"avaya-ipo-phonebook-tabs\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-tab\" [class.avaya-ipo-active]=\"directoryTab === 'contacts'\"\n (click)=\"setDirectoryTab('contacts')\">\n Contacts\n </button>\n <button type=\"button\" class=\"avaya-ipo-phonebook-tab\" [class.avaya-ipo-active]=\"directoryTab === 'dialpad'\"\n (click)=\"setDirectoryTab('dialpad')\">\n Dialpad\n </button>\n </div>\n\n <div class=\"avaya-ipo-phonebook-list\">\n @if (directoryTab === 'contacts') {\n <div class=\"avaya-ipo-phonebook-search\">\n <span class=\"avaya-ipo-search-icon\">\uD83D\uDD0D</span>\n <input type=\"text\" placeholder=\"Search\" [value]=\"contactSearch\"\n (input)=\"contactSearch = ($any($event.target).value)\" />\n </div>\n\n @if (filteredContacts?.length) {\n @for (contact of filteredContacts; track contact.id ?? contact.phone ?? $index) {\n <button type=\"button\" class=\"avaya-ipo-phonebook-item\" (click)=\"onSelectContact(contact)\">\n <span class=\"avaya-ipo-phonebook-avatar\">{{ (contact.name || contact.phone || 'U') | slice:0:2 }}</span>\n <span class=\"avaya-ipo-phonebook-name\">{{ contact.name || 'Unknown' }}</span>\n <span class=\"avaya-ipo-phonebook-number\">{{ contact.phone || '' }}</span>\n </button>\n }\n } @else {\n <div class=\"avaya-ipo-phonebook-empty\">No contacts found</div>\n }\n } @else {\n <div class=\"avaya-ipo-phonebook-dialpad\">\n <div class=\"avaya-ipo-dialpad-input\" [formGroup]=\"directoryForm\">\n <ngx-intl-tel-input formControlName=\"phoneNumber\" name=\"phoneNumber\" [cssClass]=\"'avaya-ipo-phone_number_sd'\"\n [preferredCountries]=\"['in']\" [customPlaceholder]=\"'Phone Number'\" [enableAutoCountrySelect]=\"false\"\n [enablePlaceholder]=\"false\" [searchCountryFlag]=\"true\"\n [searchCountryField]=\"[SearchCountryField.Iso2, SearchCountryField.Name]\" [selectFirstCountry]=\"false\"\n [selectedCountryISO]=\"CountryISO.India\" [maxLength]=\"15\" [phoneValidation]=\"true\" [separateDialCode]=\"true\">\n </ngx-intl-tel-input>\n <button type=\"button\" class=\"avaya-ipo-dialpad-backspace\" (click)=\"onDirectoryBackspace()\">\u232B</button>\n </div>\n\n <div class=\"avaya-ipo-dialpad-grid\">\n @for (item of directoryDigits; track item.digit) {\n <button type=\"button\" class=\"avaya-ipo-dialpad-key\" (click)=\"onDirectoryKeypad(item.digit)\">\n <span class=\"avaya-ipo-dialpad-digit\">{{ item.digit }}</span>\n <span class=\"avaya-ipo-dialpad-letters\">{{ item.letters || '\\u00a0' }}</span>\n </button>\n }\n </div>\n\n <button type=\"button\" class=\"avaya-ipo-dialpad-action\" [disabled]=\"!(directoryForm.valid || directoryNumber)\"\n (click)=\"onDirectoryUseNumber()\">\n {{ isTransferMode ? 'Transfer' : 'Add Call' }}\n </button>\n </div>\n }\n </div>\n </div>\n</div>\n}\n\n@if (isKeypadOpen) {\n<div class=\"avaya-ipo-phonebook-overlay\">\n <div class=\"avaya-ipo-phonebook-sheet avaya-ipo-keypad-sheet\">\n <div class=\"avaya-ipo-phonebook-header\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-back\" (click)=\"closeKeypad()\">\u2039</button>\n <div class=\"avaya-ipo-phonebook-titles\">\n <div class=\"avaya-ipo-phonebook-kicker\">DTMF</div>\n <div class=\"avaya-ipo-phonebook-title\">Keypad</div>\n </div>\n <button type=\"button\" class=\"avaya-ipo-phonebook-add\" disabled>\uFF0B</button>\n </div>\n\n <div class=\"avaya-ipo-dialpad-input avaya-ipo-dtmf-input\">\n <div class=\"avaya-ipo-dtmf-text\">{{ dtmfBuffer || ' ' }}</div>\n </div>\n\n <div class=\"avaya-ipo-phonebook-dialpad\">\n <div class=\"avaya-ipo-dialpad-grid\">\n @for (item of directoryDigits; track item.digit) {\n <button type=\"button\" class=\"avaya-ipo-dialpad-key\" (click)=\"onDtmfDigit(item.digit)\">\n <div class=\"avaya-ipo-dialpad-digit\">{{ item.digit }}</div>\n @if (item.letters) {\n <div class=\"avaya-ipo-dialpad-letters\">{{ item.letters }}</div>\n }\n </button>\n }\n </div>\n\n <button type=\"button\" class=\"avaya-ipo-dialpad-action\" (click)=\"closeKeypad()\">Done</button>\n </div>\n </div>\n</div>\n}\n\n@if (isTranscriptionOpen) {\n<div class=\"avaya-ipo-phonebook-overlay\">\n <div class=\"avaya-ipo-phonebook-sheet avaya-ipo-transcription-sheet\">\n <div class=\"avaya-ipo-phonebook-header\">\n <button type=\"button\" class=\"avaya-ipo-phonebook-back\" (click)=\"closeTranscription()\">\u2039</button>\n <div class=\"avaya-ipo-phonebook-titles\">\n <div class=\"avaya-ipo-phonebook-title\">Live Transcription</div>\n </div>\n </div>\n <div class=\"avaya-ipo-transcription-body\">\n @if (transcriptSegments?.length) {\n <div class=\"avaya-ipo-transcription-split\">\n <div class=\"avaya-ipo-transcription-panel\">\n <div class=\"avaya-ipo-transcription-panel-title\">\n Customer\n </div>\n <div class=\"avaya-ipo-transcription-panel-body\">\n @if (customerTranscriptSegments.length) {\n @for (segment of customerTranscriptSegments; track segment.ts ?? $index) {\n <div class=\"avaya-ipo-transcription-line\">{{ segment.text }}</div>\n }\n } @else {\n <div class=\"avaya-ipo-transcription-placeholder\">No customer speech yet.</div>\n }\n </div>\n </div>\n <div class=\"avaya-ipo-transcription-panel\">\n <div class=\"avaya-ipo-transcription-panel-title\">\n Agent\n </div>\n <div class=\"avaya-ipo-transcription-panel-body\">\n @if (agentTranscriptSegments.length) {\n @for (segment of agentTranscriptSegments; track segment.ts ?? $index) {\n <div class=\"avaya-ipo-transcription-line\">{{ segment.text }}</div>\n }\n } @else {\n <div class=\"avaya-ipo-transcription-placeholder\">No agent speech yet.</div>\n }\n </div>\n </div>\n </div>\n } @else {\n <div class=\"avaya-ipo-transcription-placeholder\">Live transcription will appear here.</div>\n }\n </div>\n </div>\n</div>\n}\n", styles: [":host{display:block;height:100%}.avaya-ipo-phone-container{width:100%;box-sizing:border-box;padding:0;background:transparent;border-radius:0;min-height:100%;height:100%;position:relative;container-type:size}.avaya-ipo-phonebook-overlay{position:absolute;inset:0;background:#00000059;display:flex;align-items:flex-end;justify-content:center;z-index:100}.avaya-ipo-phonebook-sheet{width:100%;max-width:100%;height:90%;max-height:100%;background:var(--sd-surface-muted);color:var(--sd-text);border-radius:var(--sd-radius-lg) var(--sd-radius-lg) 0 0;overflow:hidden;border:1px solid var(--sd-border);display:flex;flex-direction:column;animation:sheet-slide-up .22s ease}.avaya-ipo-keypad-sheet{height:82%}.avaya-ipo-transcription-sheet{height:90%}.avaya-ipo-transcription-body{flex:1 1 auto;padding:12px 18px 20px;overflow-y:auto}.avaya-ipo-transcription-split{display:flex;flex-direction:column;gap:12px;height:100%}.avaya-ipo-transcription-panel{flex:1 1 0;border:1px solid var(--sd-border);border-radius:var(--sd-radius);background:var(--sd-card);display:flex;flex-direction:column;min-height:0}.avaya-ipo-transcription-panel-title{font-size:12px;font-weight:700;color:var(--sd-text-muted);padding:8px 12px;border-bottom:1px solid var(--sd-border);background:var(--sd-surface-muted)}.avaya-ipo-transcription-panel-body{flex:1 1 auto;padding:10px 12px;overflow-y:auto;display:flex;flex-direction:column;gap:6px}.avaya-ipo-transcription-line{font-size:14px;color:var(--sd-text);line-height:1.5;white-space:pre-wrap}.avaya-ipo-transcription-panel .avaya-ipo-transcription-placeholder{font-size:12px;color:var(--sd-text-subtle)}.avaya-ipo-transcription-placeholder{font-size:13px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-header{display:flex;align-items:center;justify-content:space-between;padding:18px 18px 8px}.avaya-ipo-phonebook-titles{text-align:center;display:flex;flex-direction:column;gap:4px;flex:1 1 auto}.avaya-ipo-phonebook-kicker{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-title{font-size:18px;font-weight:700;color:var(--sd-text)}.avaya-ipo-phonebook-back,.avaya-ipo-phonebook-add{width:36px;height:36px;border-radius:50%;border:1px solid var(--sd-border);background:var(--sd-card);color:var(--sd-text-muted);font-size:18px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-phonebook-back:hover,.avaya-ipo-phonebook-add:hover{background:var(--sd-surface-muted)}.avaya-ipo-phonebook-add:disabled{opacity:.4;cursor:default}.avaya-ipo-phonebook-error{margin:0 16px 8px;padding:8px 10px;border-radius:var(--sd-radius);background:var(--sd-accent-soft);color:var(--sd-call-end);font-size:12px;font-weight:600;text-align:center}.avaya-ipo-phonebook-success{margin:0 16px 8px;padding:8px 10px;border-radius:var(--sd-radius);background:#1aa2511f;color:var(--sd-call-accept);font-size:12px;font-weight:600;text-align:center}.avaya-ipo-phonebook-tabs{margin:4px 16px 8px;display:flex;gap:8px;background:var(--sd-card);border:1px solid var(--sd-border);padding:4px;border-radius:var(--sd-radius-lg)}.avaya-ipo-phonebook-tab{flex:1 1 0;border:none;background:transparent;color:var(--sd-text-muted);font-size:13px;padding:8px 0;border-radius:var(--sd-radius);cursor:pointer}.avaya-ipo-phonebook-tab.avaya-ipo-active{background:var(--sd-accent);color:var(--sd-accent-contrast)}.avaya-ipo-phonebook-search{margin:8px 16px 14px;display:flex;align-items:center;gap:8px;padding:10px 14px;border-radius:var(--sd-radius-sm);background:var(--sd-input);border:1px solid var(--sd-input-border);color:var(--sd-text)}.avaya-ipo-phonebook-search:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-phonebook-search input{flex:1 1 auto;background:transparent;border:none;outline:none;color:var(--sd-text);font-size:14px}.avaya-ipo-phonebook-search input::placeholder{color:var(--sd-text-subtle)}.avaya-ipo-phonebook-list{flex:1 1 auto;overflow-y:auto}.avaya-ipo-phonebook-item{width:100%;text-align:left;padding:12px 18px;border:none;background:transparent;display:grid;grid-template-columns:40px 1fr;grid-template-rows:auto auto;column-gap:12px;row-gap:2px;cursor:pointer;border-bottom:1px solid var(--sd-border)}.avaya-ipo-phonebook-item:hover{background:var(--sd-surface-muted)}.avaya-ipo-phonebook-item:last-child{border-bottom:none}.avaya-ipo-phonebook-avatar{width:40px;height:40px;border-radius:50%;background:var(--sd-avatar);color:var(--sd-text-muted);display:inline-flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;grid-row:span 2}.avaya-ipo-phonebook-name{font-size:13px;font-weight:600;color:var(--sd-text)}.avaya-ipo-phonebook-number{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-empty{padding:18px;font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-phonebook-dialpad{padding:10px 16px 18px;display:flex;flex-direction:column;gap:14px}.avaya-ipo-dialpad-input{display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:var(--sd-radius-sm);border:1px solid var(--sd-input-border);background:var(--sd-input)}.avaya-ipo-dialpad-input:focus-within{border-color:var(--sd-accent);box-shadow:var(--sd-focus-ring)}.avaya-ipo-dialpad-input .avaya-ipo-phone_number_sd{width:100%}.avaya-ipo-dialpad-input input{flex:1 1 auto;border:none;outline:none;font-size:16px;background:transparent;color:var(--sd-text)}.avaya-ipo-dialpad-backspace{border:none;background:transparent;font-size:16px;cursor:pointer;color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-dialpad-input .iti{width:100%}:host ::ng-deep .avaya-ipo-dialpad-input .iti__flag-container{padding-left:6px}:host ::ng-deep .avaya-ipo-dialpad-input .iti__selected-flag{border-right:1px solid var(--sd-border);padding-right:8px}:host ::ng-deep .avaya-ipo-dialpad-input .iti.separate-dial-code input{padding-left:130px!important}:host ::ng-deep .avaya-ipo-dialpad-input .iti__tel-input{background:transparent;border:none;box-shadow:none;height:32px;padding:0 0 0 6px;font-size:15px;color:var(--sd-text)}.avaya-ipo-dialpad-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(8px,3%,12px);justify-items:center}.avaya-ipo-dialpad-key{width:clamp(52px,18%,68px);aspect-ratio:1;height:auto;border-radius:50%;border:1.6px solid var(--sd-border-strong);background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer}.avaya-ipo-dialpad-key:focus{outline:none;box-shadow:none}.avaya-ipo-dialpad-key:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-dialpad-key:active{background:var(--sd-surface-muted)}.avaya-ipo-dialpad-digit{font-size:24px;font-weight:400;color:var(--sd-text);line-height:24px}.avaya-ipo-dialpad-letters{font-size:9px;letter-spacing:.8px;color:var(--sd-text-subtle);margin-top:2px}.avaya-ipo-dialpad-action{border:none;border-radius:var(--sd-radius);padding:12px 0;background:var(--sd-accent);color:var(--sd-accent-contrast);font-size:14px;font-weight:600;cursor:pointer}.avaya-ipo-dialpad-action:hover{background:var(--sd-accent-strong)}.avaya-ipo-dialpad-action:focus-visible{outline:none;box-shadow:var(--sd-focus-ring)}.avaya-ipo-dialpad-action:disabled{opacity:.5;cursor:default}.avaya-ipo-dtmf-input{margin:0 16px 6px}.avaya-ipo-dtmf-text{flex:1 1 auto;text-align:center;font-size:18px;letter-spacing:1px;color:var(--sd-text);min-height:24px}@keyframes sheet-slide-up{0%{transform:translateY(24px);opacity:.6}to{transform:translateY(0);opacity:1}}\n"], dependencies: [{ kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.NgxIntlTelInputComponent, selector: "ngx-intl-tel-input", inputs: ["value", "preferredCountries", "enablePlaceholder", "customPlaceholder", "numberFormat", "cssClass", "onlyCountries", "enableAutoCountrySelect", "searchCountryFlag", "searchCountryField", "searchCountryPlaceholder", "maxLength", "selectFirstCountry", "selectedCountryISO", "phoneValidation", "inputId", "separateDialCode"], outputs: ["countryChange"] }, { kind: "directive", type: i2$1.NativeElementInjectorDirective, selector: "[ngModel], [formControl], [formControlName]" }, { kind: "component", type: PhoneIdleComponent, selector: "app-phone-idle", inputs: ["dialForm", "contacts", "showDirectoryPhonebook", "isRinging", "CountryISO", "SearchCountryField"], outputs: ["toggleDirectory", "clear", "makeCall", "keypadInput", "keyboardInput"] }, { kind: "component", type: PhoneIncomingComponent, selector: "app-phone-incoming", inputs: ["incomingCallName", "incomingNameResolved", "incomingCallNumber"], outputs: ["accept", "decline"] }, { kind: "component", type: PhoneActiveComponent, selector: "app-phone-active", inputs: ["tenantId", "activeCallName", "activeCallNumber", "activeCallDuration", "callStatusText", "isConnecting", "isMuted", "isHeld"], outputs: ["endCall", "toggleMute", "toggleHold", "transfer", "openContacts", "openKeypad", "startTranscription", "contactsLoaded"] }, { kind: "pipe", type: i2.SlicePipe, name: "slice" }] });
4141
4481
  }
4142
4482
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: PhoneComponent, decorators: [{
4143
4483
  type: Component,
@@ -4174,6 +4514,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
4174
4514
  type: Input
4175
4515
  }], configurationMode: [{
4176
4516
  type: Input
4517
+ }], recordingUploadMode: [{
4518
+ type: Input
4519
+ }], entityId: [{
4520
+ type: Input
4177
4521
  }], makeCallEv: [{
4178
4522
  type: Output
4179
4523
  }], endCallEv: [{
@@ -4209,6 +4553,9 @@ class AvayaIPOWidgetComponent {
4209
4553
  */
4210
4554
  displayMode = 'popup';
4211
4555
  configurationMode;
4556
+ /** Recording upload strategy: 'complete' (one upload at call end) or 'chunked' (live-streamed
4557
+ * over the recording WebSocket, survives a dead tab). Defaults to APP_CONFIG.RECORDING_UPLOAD_MODE. */
4558
+ recordingUploadMode;
4212
4559
  avayaIPOServerIP;
4213
4560
  avayaIPOServerPort;
4214
4561
  avayaIPOServerStunServerIP;
@@ -4243,7 +4590,6 @@ class AvayaIPOWidgetComponent {
4243
4590
  * Payload: the call id, the caller's number, and the resolved caller name (null if not yet known).
4244
4591
  */
4245
4592
  incomingCall = new EventEmitter();
4246
- avayaLogoUrl = assetUrl('assets/images/logo-avaya_small_color.svg');
4247
4593
  widgetVersion = APP_CONFIG.WIDGET_VERSION;
4248
4594
  isReconnectingInProgress = false;
4249
4595
  isFailoverInProgress = false;
@@ -4265,6 +4611,9 @@ class AvayaIPOWidgetComponent {
4265
4611
  hideTabs = false;
4266
4612
  darkModeEnabled = false;
4267
4613
  activeCallNumber = null;
4614
+ /** Entity id of the current call's counterpart (resolved via OpenSearch); sent with the
4615
+ * chunked-recording socket so chunks land under <tenantId>/<entityId>/avaya-ipo-chunks/. */
4616
+ activeCallEntityId = null;
4268
4617
  incomingCallName = null;
4269
4618
  incomingNameResolved = false;
4270
4619
  activeCallName = null;
@@ -4327,6 +4676,7 @@ class AvayaIPOWidgetComponent {
4327
4676
  this.activeTab = 'keypad';
4328
4677
  const phoneNumber = (farEndNumber ?? '').toString();
4329
4678
  this.activeCallNumber = phoneNumber;
4679
+ this.activeCallEntityId = null;
4330
4680
  this.incomingCallName = null;
4331
4681
  this.incomingNameResolved = false;
4332
4682
  this.activeCallName = null;
@@ -4446,6 +4796,7 @@ class AvayaIPOWidgetComponent {
4446
4796
  if (this.avayaIPOService.activeCallId === callId) {
4447
4797
  this.activeCallNumber = null;
4448
4798
  this.activeCallName = null;
4799
+ this.activeCallEntityId = null;
4449
4800
  this.incomingCallName = null;
4450
4801
  }
4451
4802
  }
@@ -4734,6 +5085,7 @@ class AvayaIPOWidgetComponent {
4734
5085
  }
4735
5086
  this.activeTab = 'keypad';
4736
5087
  this.activeCallNumber = destination;
5088
+ this.activeCallEntityId = null;
4737
5089
  this.activeCallName = providedName || null;
4738
5090
  const normalizedSearch = this.normalizePhoneForSearch(destination);
4739
5091
  if (!providedName) {
@@ -4744,9 +5096,12 @@ class AvayaIPOWidgetComponent {
4744
5096
  }
4745
5097
  this.avayaIPOService.notifyOutgoingDial(destination);
4746
5098
  try {
5099
+ // Always run the entity lookup — even when the caller name is already known (contacts/history)
5100
+ // we still need the entity ID for the recording socket payload. The provided name keeps display
5101
+ // priority below.
4747
5102
  const [lookupResult, callerName] = await Promise.all([
4748
5103
  this.getLookupPhoneNumber(destination),
4749
- providedName ? Promise.resolve(null) : this.getOpenSearchCallerName(normalizedSearch),
5104
+ this.getOpenSearchCallerName(normalizedSearch),
4750
5105
  ]);
4751
5106
  const mapNumber = lookupResult?.lookupPhoneNumber?.['local-number']?.replace(/\s+/g, '') ||
4752
5107
  lookupResult?.normalizedPhoneNumber ||
@@ -4855,7 +5210,11 @@ class AvayaIPOWidgetComponent {
4855
5210
  return null;
4856
5211
  }
4857
5212
  try {
4858
- return await this.entitiesSearchService.lookupNameByPhone(tenantId, phoneNumber);
5213
+ const entity = await this.entitiesSearchService.lookupEntityByPhone(tenantId, phoneNumber);
5214
+ // Remember the entity for the recording socket payload (chunks live under its folder).
5215
+ this.activeCallEntityId = entity.id;
5216
+ console.debug(`[avaya-ipo] entity lookup for ${phoneNumber}: id=${entity.id || 'NONE'} name=${entity.name || 'NONE'}`);
5217
+ return entity.name;
4859
5218
  }
4860
5219
  catch (err) {
4861
5220
  console.warn('OpenSearch lookup failed:', err);
@@ -4993,11 +5352,11 @@ class AvayaIPOWidgetComponent {
4993
5352
  return this.awlScriptPromise;
4994
5353
  }
4995
5354
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AvayaIPOWidgetComponent, deps: [{ token: i1$2.FormBuilder }, { token: AvayaIPOService }, { token: i0.ChangeDetectorRef }, { token: CountryService }, { token: PhoneNumberLookupService }, { token: EntitiesSearchService }, { token: i1$1.SnugdeskAuthenticationService }], target: i0.ɵɵFactoryTarget.Component });
4996
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AvayaIPOWidgetComponent, isStandalone: false, selector: "snugdesk-avaya-ipo-widget", inputs: { isVisible: "isVisible", displayMode: "displayMode", configurationMode: "configurationMode", avayaIPOServerIP: "avayaIPOServerIP", avayaIPOServerPort: "avayaIPOServerPort", avayaIPOServerStunServerIP: "avayaIPOServerStunServerIP", avayaIPOServerStunServerPort: "avayaIPOServerStunServerPort", avayaIPOServerTurnServerIP: "avayaIPOServerTurnServerIP", avayaIPOServerTurnServerPort: "avayaIPOServerTurnServerPort", token: "token", tenantId: "tenantId", userId: "userId", extension: "extension", password: "password", showHistory: "showHistory", showContacts: "showContacts" }, outputs: { notificationEvent: "notificationEvent", incomingCall: "incomingCall" }, host: { properties: { "class.avaya-ipo-dark-mode": "this.hostDarkMode", "class.avaya-ipo-mode-standalone": "this.hostModeStandalone", "class.avaya-ipo-mode-popup": "this.hostModePopup" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"avaya-ipo-media-elements\">\n <audio id=\"rmtAudio\" autoplay></audio>\n <audio id=\"lclAudio\" autoplay></audio>\n <video id=\"rmtVideo\" autoplay playsinline></video>\n <video id=\"lclVideo\" autoplay playsinline muted></video>\n</div>\n\n@if (authLoading) {\n <div class=\"avaya-ipo-auth-loading-screen\">\n <div class=\"avaya-ipo-auth-loading-card\">\n <div class=\"avaya-ipo-spinner\" aria-hidden=\"true\"></div>\n <div class=\"avaya-ipo-auth-loading-title\">Checking authentication</div>\n <div class=\"avaya-ipo-auth-loading-message\">Please wait...</div>\n </div>\n </div>\n} @else if (authErrorMessage) {\n <div class=\"avaya-ipo-auth-error-screen\">\n <div class=\"avaya-ipo-auth-error-card\">\n <div class=\"avaya-ipo-auth-error-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M12 2a7 7 0 0 1 7 7v3a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2V9a7 7 0 0 1 7-7zm5 10V9a5 5 0 0 0-10 0v3h10zm-5 3a2 2 0 0 0-1 3.732V20h2v-1.268A2 2 0 0 0 12 15z\"\n />\n </svg>\n </div>\n <div class=\"avaya-ipo-auth-error-title\">Authentication Required</div>\n <div class=\"avaya-ipo-auth-error-message\">{{ authErrorMessage }}</div>\n </div>\n </div>\n} @else {\n@if (isReconnectingInProgress || isFailoverInProgress || isFailbackInProgress) {\n <div class=\"avaya-ipo-container_connection_status_overlay\">\n <div class=\"avaya-ipo-container_connection_status\">\n <i class=\"fa-solid fa-circle-dot\"></i>\n @if (isReconnectingInProgress) { <span>Reconnecting to the server...</span> }\n @if (isFailoverInProgress) { <span>Failover in progress...</span> }\n @if (isFailbackInProgress) { <span>Failback in progress...</span> }\n </div>\n </div>\n}\n\n@if (showLoginForm) {\n <app-avaya-ipo-login\n [loginForm]=\"loginForm\"\n [showLoginLoader]=\"showLoginLoader\"\n [hasAvayaSocketError]=\"hasAvayaSocketError\"\n [hasAvayaLoginError]=\"hasAvayaLoginError\"\n [hasAvayaLoginFailedGeneral]=\"hasAvayaLoginFailedGeneral\"\n [hasAvayaLoginConflictError]=\"hasAvayaLoginConflictError\"\n [hasAvayaDeviceError]=\"hasAvayaDeviceError\"\n (login)=\"onLogin()\"\n ></app-avaya-ipo-login>\n} @else {\n <div class=\"avaya-ipo-widget-body\">\n <div class=\"avaya-ipo-widget-content\">\n @if (activeTab === 'history') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading avaya-ipo-heading-right\">\n <span>History</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-call-history\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n (makeCallEv)=\"onHistoryMakeCall($event)\"\n ></app-call-history>\n } @else if (activeTab === 'contacts') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span>Contacts</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-contacts [tenantId]=\"tenantId\" (makeCallEv)=\"onContactsMakeCall($event)\"></app-contacts>\n } @else if (activeTab === 'settings') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span class=\"avaya-ipo-heading-with-back\">\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-back-btn\" (click)=\"closeSettings()\" aria-label=\"Go back\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n </button>\n <span>Settings</span>\n </span>\n </div>\n }\n <app-settings\n [extensionId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [darkMode]=\"darkModeEnabled\"\n (darkModeChange)=\"onThemeToggle($event)\"\n (change)=\"onDeviceChange($event)\"\n (logout)=\"onLogout()\"\n ></app-settings>\n } @else {\n @if (!hideTabs) {\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-settings-btn-floating\" (click)=\"selectTab('settings')\" aria-label=\"Settings\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n }\n <app-phone\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [activeCallNumber]=\"activeCallNumber\"\n [incomingCallName]=\"incomingCallName\"\n [incomingNameResolved]=\"incomingNameResolved\"\n [activeCallName]=\"activeCallName\"\n [serverIp]=\"avayaIPOServerIP\"\n [serverPort]=\"avayaIPOServerPort\"\n [stunIp]=\"avayaIPOServerStunServerIP\"\n [stunPort]=\"avayaIPOServerStunServerPort\"\n [turnIp]=\"avayaIPOServerTurnServerIP\"\n [turnPort]=\"avayaIPOServerTurnServerPort\"\n [configurationMode]=\"configurationMode\"\n (makeCallEv)=\"onPhoneMakeCall($event)\"\n (endCallEv)=\"onPhoneEndCall()\"\n (callScreenChange)=\"onCallScreenChange($event)\"\n ></app-phone>\n }\n </div>\n </div>\n\n @if (showLoginLoader) {\n <div class=\"avaya-ipo-global-loader\">\n <div class=\"avaya-ipo-spinner\"></div>\n <div class=\"avaya-ipo-loader-text\">Connecting to phone service...</div>\n </div>\n }\n\n @if (!hideTabs && showTabBar) {\n <nav class=\"avaya-ipo-tabs\">\n @if (showHistory) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'history'\" (click)=\"selectTab('history')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"19px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M464 256A208 208 0 1 1 48 256a208 208 0 1 1 416 0zM0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120l0 136c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2 280 120c0-13.3-10.7-24-24-24s-24 10.7-24 24z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">History</span>\n </button>\n }\n @if (showContacts) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'contacts'\" (click)=\"selectTab('contacts')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"18px\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M12 12a4 4 0 1 0-4-4 4 4 0 0 0 4 4zm0 2c-4.4 0-8 2.2-8 5v2h16v-2c0-2.8-3.6-5-8-5z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Contacts</span>\n </button>\n }\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'keypad'\" (click)=\"selectTab('keypad')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"20px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\" d=\"M256,400a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Keypad</span>\n </button>\n </nav>\n }\n\n @if (activeTab !== 'keypad') {\n <div class=\"avaya-ipo-widget-version-footer\">v{{ widgetVersion }}</div>\n }\n}\n}\n", styles: [":host{display:flex;flex-direction:column;width:100%;max-width:100%;margin:0;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;min-height:100%;height:100%;background:var(--sd-surface);color:var(--sd-text);box-sizing:border-box;--sd-tabs-height: 60px;--sd-radius-sm: 8px;--sd-radius: 10px;--sd-radius-lg: 14px;--sd-radius-pill: 999px;--sd-shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);--sd-shadow-md: 0 6px 16px rgba(16, 24, 40, .1);--sd-shadow-lg: 0 16px 40px rgba(16, 24, 40, .14);--sd-accent: var(--app-color, #ff6633);--sd-accent-strong: var(--app-color-dark, #ff5805);--sd-accent-soft: #fff1ea;--sd-accent-contrast: #ffffff;--sd-call-accept: #1aa251;--sd-call-end: #e5484d;--sd-surface: var(--background-color, #ffffff);--sd-surface-muted: var(--background-color-dark, #f7f7f7);--sd-surface-sunken: var(--background-color-dark-light, #e8e8e8);--sd-text: var(--header-text-primary, #333333);--sd-text-muted: var(--header-text-secondary, #5f6368);--sd-text-subtle: var(--header-text-muted, #9ca3af);--sd-border: var(--dropdown-border, #e3e3e3);--sd-border-strong: var(--border-color, #c9c9c9);--sd-card: var(--background-color, #ffffff);--sd-avatar: #eceff3;--sd-input: var(--background-color, #ffffff);--sd-input-border: var(--border-color, #c9c9c9);--sd-focus-ring: 0 0 0 3px rgba(255, 102, 51, .22)}:host.avaya-ipo-dark-mode{--sd-accent: #ff7a4d;--sd-accent-strong: #ff6633;--sd-accent-soft: rgba(255, 122, 77, .14);--sd-accent-contrast: #1a1109;--sd-call-accept: #34c759;--sd-call-end: #ff5b5b;--sd-surface: #0f1115;--sd-surface-muted: #151a22;--sd-surface-sunken: #1c222c;--sd-text: #f2f4f8;--sd-text-muted: #aab0bb;--sd-text-subtle: #7e8794;--sd-border: #2a2f3a;--sd-border-strong: #353b47;--sd-card: #161b24;--sd-avatar: #222833;--sd-input: #1c222c;--sd-input-border: #2a2f3a;--sd-focus-ring: 0 0 0 3px rgba(255, 122, 77, .25)}:host.avaya-ipo-mode-popup{min-width:320px;height:100%}:host.avaya-ipo-mode-standalone{width:100%;max-width:460px;height:100dvh;min-height:100dvh;margin-inline:auto;border-inline:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);overflow:hidden}@media (max-width: 768px){:host.avaya-ipo-mode-standalone{max-width:100%;border-inline:0;box-shadow:none}}.avaya-ipo-container_connection_status_overlay{width:100%;position:relative;background-color:#7f7f7f1a;padding:10px;box-sizing:border-box}.avaya-ipo-container_connection_status{width:100%;background:var(--sd-card);padding:8px 10px;border-radius:var(--sd-radius-sm);font-size:13px;font-weight:600;color:var(--sd-text-muted);display:flex;gap:8px;align-items:center;box-shadow:var(--sd-shadow-md)}.avaya-ipo-container_connection_status .fa-circle-dot{color:var(--sd-accent)}.avaya-ipo-simple-placeholder{padding:20px;text-align:center;color:var(--sd-text);font-weight:600}.avaya-ipo-auth-error-screen,.avaya-ipo-auth-loading-screen{min-height:100%;flex:1 1 auto;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box;background:var(--sd-surface)}.avaya-ipo-auth-loading-card{width:min(320px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center;align-items:center}.avaya-ipo-auth-loading-title{font-size:16px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-loading-message{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-card{width:min(360px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center}.avaya-ipo-auth-error-icon{width:56px;height:56px;margin:0 auto 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sd-radius-lg);background:var(--sd-accent);color:var(--sd-accent-contrast)}.avaya-ipo-auth-error-icon svg{width:28px;height:28px}.avaya-ipo-auth-error-title{font-size:18px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-error-message{font-size:13px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-hint{font-size:12px;color:var(--sd-text-subtle)}.avaya-ipo-media-elements{display:none}.avaya-ipo-widget-body{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;position:relative;height:100%;padding-bottom:0;overflow-y:auto;-webkit-overflow-scrolling:touch}.avaya-ipo-logout-btn{border:none;background:var(--sd-call-end);color:#fff;padding:8px 12px;border-radius:var(--sd-radius-sm);cursor:pointer;font-weight:600}.avaya-ipo-logout-btn:hover{filter:brightness(.94)}.avaya-ipo-widget-content{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:1rem;padding-bottom:0;height:100%}.avaya-ipo-page-heading{display:flex;align-items:center;justify-content:space-between;font-size:22px;font-weight:800;color:var(--sd-text);padding:15px;z-index:5;background:var(--sd-surface)}.avaya-ipo-settings-btn{width:34px;height:34px;border-radius:var(--sd-radius-sm);border:none;background:transparent;color:var(--sd-text-muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}.avaya-ipo-settings-btn:hover{background:var(--sd-surface-muted)}.avaya-ipo-settings-btn.avaya-ipo-is-active{color:var(--sd-accent);background:var(--sd-accent-soft)}.avaya-ipo-settings-btn:disabled{cursor:default;opacity:.75}.avaya-ipo-settings-btn-floating{position:absolute;top:8px;right:8px;z-index:6}.avaya-ipo-heading-with-back{display:inline-flex;align-items:center;gap:4px}.avaya-ipo-settings-btn.avaya-ipo-back-btn{color:var(--sd-text)}.avaya-ipo-tabs{position:sticky;bottom:0;left:0;right:0;display:flex;gap:6px;padding:8px 12px;background:var(--sd-surface-muted);border-top:1px solid var(--sd-border);box-sizing:border-box;z-index:10;height:var(--sd-tabs-height)}.avaya-ipo-tab-btn{flex:1 1 0;height:44px;border:none;background:transparent;font-weight:600;color:var(--sd-text-muted);border-radius:var(--sd-radius-sm);cursor:pointer;transition:background .12s ease,color .12s ease;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:12px;box-shadow:none}.avaya-ipo-tab-btn:hover{color:var(--sd-text)}.avaya-ipo-tab-btn.avaya-ipo-active{background:var(--sd-accent-soft);color:var(--sd-accent);box-shadow:none}.avaya-ipo-tab-icon{display:flex;align-items:center;justify-content:center;font-size:16px}.avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}.avaya-ipo-global-loader{position:absolute;inset:0;background:color-mix(in srgb,var(--sd-surface) 85%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;z-index:1000;color:var(--sd-text);font-weight:700}.avaya-ipo-spinner{width:48px;height:48px;border:4px solid var(--sd-surface-sunken);border-top-color:var(--sd-accent);border-radius:50%;animation:spin .9s linear infinite}.avaya-ipo-loader-text{font-size:14px}@keyframes spin{to{transform:rotate(360deg)}}:host ::ng-deep .avaya-ipo-widget-body,:host ::ng-deep .avaya-ipo-widget-content{background:var(--sd-surface);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-page-heading{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-settings-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tabs{background:var(--sd-surface-muted);border-top-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-tab-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active{color:var(--sd-accent);background:var(--sd-accent-soft)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}:host ::ng-deep .avaya-ipo-history_item,:host ::ng-deep .avaya-ipo-contact-card{border-bottom-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-history_avatar,:host ::ng-deep .avaya-ipo-skeleton_avatar,:host ::ng-deep .avaya-ipo-contact-avatar{background:var(--sd-avatar);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_name,:host ::ng-deep .avaya-ipo-contact-name{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_time,:host ::ng-deep .avaya-ipo-history_meta,:host ::ng-deep .avaya-ipo-history_group_label,:host ::ng-deep .avaya-ipo-contact-phone,:host ::ng-deep .avaya-ipo-contacts-state{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_group_label{background:#151a22eb}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_item:hover{background:#1a202b}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input{background:var(--sd-input);border-color:var(--sd-input-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input::placeholder{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call{background:#1e2b22;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-back{background:#141922;border-color:var(--sd-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call-btn{background:#1f2530;border-color:#1f2530;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-global-loader{background:#0f1115e6;color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-spinner{border-color:#2a2f3a;border-top-color:var(--sd-accent)}.avaya-ipo-widget-version-footer{flex:0 0 auto;padding:2px 8px 4px;text-align:center;font-size:10px;line-height:1.2;letter-spacing:.02em;color:var(--sd-text-muted);background:var(--sd-surface);border-top:1px solid var(--sd-border);-webkit-user-select:text;user-select:text}\n"], dependencies: [{ kind: "component", type: CallHistoryComponent, selector: "app-call-history", inputs: ["mode", "tenantId", "agentId"], outputs: ["makeCallEv", "transferEv"] }, { kind: "component", type: ContactsComponent, selector: "app-contacts", inputs: ["tenantId"], outputs: ["makeCallEv"] }, { kind: "component", type: SettingsComponent, selector: "app-settings", inputs: ["selectedAudioInputId", "selectedAudioOutputId", "extensionId", "darkMode"], outputs: ["change", "darkModeChange", "logout"] }, { kind: "component", type: AvayaIpoLoginComponent, selector: "app-avaya-ipo-login", inputs: ["loginForm", "showLoginLoader", "hasAvayaSocketError", "hasAvayaLoginError", "hasAvayaLoginFailedGeneral", "hasAvayaLoginConflictError", "hasAvayaDeviceError"], outputs: ["login"] }, { kind: "component", type: PhoneComponent, selector: "app-phone", inputs: ["contacts", "tenantId", "agentId", "isActiveCall", "activeCallNumber", "incomingCallName", "incomingNameResolved", "activeCallName", "serverIp", "serverPort", "stunIp", "stunPort", "turnIp", "turnPort", "configurationMode"], outputs: ["callScreenChange", "makeCallEv", "endCallEv"] }] });
5355
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AvayaIPOWidgetComponent, isStandalone: false, selector: "snugdesk-avaya-ipo-widget", inputs: { isVisible: "isVisible", displayMode: "displayMode", configurationMode: "configurationMode", recordingUploadMode: "recordingUploadMode", avayaIPOServerIP: "avayaIPOServerIP", avayaIPOServerPort: "avayaIPOServerPort", avayaIPOServerStunServerIP: "avayaIPOServerStunServerIP", avayaIPOServerStunServerPort: "avayaIPOServerStunServerPort", avayaIPOServerTurnServerIP: "avayaIPOServerTurnServerIP", avayaIPOServerTurnServerPort: "avayaIPOServerTurnServerPort", token: "token", tenantId: "tenantId", userId: "userId", extension: "extension", password: "password", showHistory: "showHistory", showContacts: "showContacts" }, outputs: { notificationEvent: "notificationEvent", incomingCall: "incomingCall" }, host: { properties: { "class.avaya-ipo-dark-mode": "this.hostDarkMode", "class.avaya-ipo-mode-standalone": "this.hostModeStandalone", "class.avaya-ipo-mode-popup": "this.hostModePopup" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"avaya-ipo-media-elements\">\n <audio id=\"rmtAudio\" autoplay></audio>\n <audio id=\"lclAudio\" autoplay></audio>\n <video id=\"rmtVideo\" autoplay playsinline></video>\n <video id=\"lclVideo\" autoplay playsinline muted></video>\n</div>\n\n@if (authLoading) {\n <div class=\"avaya-ipo-auth-loading-screen\">\n <div class=\"avaya-ipo-auth-loading-card\">\n <div class=\"avaya-ipo-spinner\" aria-hidden=\"true\"></div>\n <div class=\"avaya-ipo-auth-loading-title\">Checking authentication</div>\n <div class=\"avaya-ipo-auth-loading-message\">Please wait...</div>\n </div>\n </div>\n} @else if (authErrorMessage) {\n <div class=\"avaya-ipo-auth-error-screen\">\n <div class=\"avaya-ipo-auth-error-card\">\n <div class=\"avaya-ipo-auth-error-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M12 2a7 7 0 0 1 7 7v3a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2V9a7 7 0 0 1 7-7zm5 10V9a5 5 0 0 0-10 0v3h10zm-5 3a2 2 0 0 0-1 3.732V20h2v-1.268A2 2 0 0 0 12 15z\"\n />\n </svg>\n </div>\n <div class=\"avaya-ipo-auth-error-title\">Authentication Required</div>\n <div class=\"avaya-ipo-auth-error-message\">{{ authErrorMessage }}</div>\n </div>\n </div>\n} @else {\n@if (isReconnectingInProgress || isFailoverInProgress || isFailbackInProgress) {\n <div class=\"avaya-ipo-container_connection_status_overlay\">\n <div class=\"avaya-ipo-container_connection_status\">\n <i class=\"fa-solid fa-circle-dot\"></i>\n @if (isReconnectingInProgress) { <span>Reconnecting to the server...</span> }\n @if (isFailoverInProgress) { <span>Failover in progress...</span> }\n @if (isFailbackInProgress) { <span>Failback in progress...</span> }\n </div>\n </div>\n}\n\n@if (showLoginForm) {\n <app-avaya-ipo-login\n [loginForm]=\"loginForm\"\n [showLoginLoader]=\"showLoginLoader\"\n [hasAvayaSocketError]=\"hasAvayaSocketError\"\n [hasAvayaLoginError]=\"hasAvayaLoginError\"\n [hasAvayaLoginFailedGeneral]=\"hasAvayaLoginFailedGeneral\"\n [hasAvayaLoginConflictError]=\"hasAvayaLoginConflictError\"\n [hasAvayaDeviceError]=\"hasAvayaDeviceError\"\n (login)=\"onLogin()\"\n ></app-avaya-ipo-login>\n} @else {\n <div class=\"avaya-ipo-widget-body\">\n <div class=\"avaya-ipo-widget-content\">\n @if (activeTab === 'history') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading avaya-ipo-heading-right\">\n <span>History</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-call-history\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n (makeCallEv)=\"onHistoryMakeCall($event)\"\n ></app-call-history>\n } @else if (activeTab === 'contacts') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span>Contacts</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-contacts [tenantId]=\"tenantId\" (makeCallEv)=\"onContactsMakeCall($event)\"></app-contacts>\n } @else if (activeTab === 'settings') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span class=\"avaya-ipo-heading-with-back\">\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-back-btn\" (click)=\"closeSettings()\" aria-label=\"Go back\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n </button>\n <span>Settings</span>\n </span>\n </div>\n }\n <app-settings\n [extensionId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [darkMode]=\"darkModeEnabled\"\n (darkModeChange)=\"onThemeToggle($event)\"\n (change)=\"onDeviceChange($event)\"\n (logout)=\"onLogout()\"\n ></app-settings>\n } @else {\n @if (!hideTabs) {\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-settings-btn-floating\" (click)=\"selectTab('settings')\" aria-label=\"Settings\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n }\n <app-phone\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [activeCallNumber]=\"activeCallNumber\"\n [incomingCallName]=\"incomingCallName\"\n [incomingNameResolved]=\"incomingNameResolved\"\n [activeCallName]=\"activeCallName\"\n [serverIp]=\"avayaIPOServerIP\"\n [serverPort]=\"avayaIPOServerPort\"\n [stunIp]=\"avayaIPOServerStunServerIP\"\n [stunPort]=\"avayaIPOServerStunServerPort\"\n [turnIp]=\"avayaIPOServerTurnServerIP\"\n [turnPort]=\"avayaIPOServerTurnServerPort\"\n [configurationMode]=\"configurationMode\"\n [recordingUploadMode]=\"recordingUploadMode\"\n [entityId]=\"activeCallEntityId\"\n (makeCallEv)=\"onPhoneMakeCall($event)\"\n (endCallEv)=\"onPhoneEndCall()\"\n (callScreenChange)=\"onCallScreenChange($event)\"\n ></app-phone>\n }\n </div>\n </div>\n\n @if (showLoginLoader) {\n <div class=\"avaya-ipo-global-loader\">\n <div class=\"avaya-ipo-spinner\"></div>\n <div class=\"avaya-ipo-loader-text\">Connecting to phone service...</div>\n </div>\n }\n\n @if (!hideTabs && showTabBar) {\n <nav class=\"avaya-ipo-tabs\">\n @if (showHistory) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'history'\" (click)=\"selectTab('history')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"19px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M464 256A208 208 0 1 1 48 256a208 208 0 1 1 416 0zM0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120l0 136c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2 280 120c0-13.3-10.7-24-24-24s-24 10.7-24 24z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">History</span>\n </button>\n }\n @if (showContacts) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'contacts'\" (click)=\"selectTab('contacts')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"18px\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M12 12a4 4 0 1 0-4-4 4 4 0 0 0 4 4zm0 2c-4.4 0-8 2.2-8 5v2h16v-2c0-2.8-3.6-5-8-5z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Contacts</span>\n </button>\n }\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'keypad'\" (click)=\"selectTab('keypad')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"20px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\" d=\"M256,400a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Keypad</span>\n </button>\n </nav>\n }\n\n @if (activeTab !== 'keypad') {\n <div class=\"avaya-ipo-widget-version-footer\">v{{ widgetVersion }}</div>\n }\n}\n}\n", styles: [":host{display:flex;flex-direction:column;width:100%;max-width:100%;margin:0;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;min-height:100%;height:100%;background:var(--sd-surface);color:var(--sd-text);box-sizing:border-box;--sd-tabs-height: 60px;--sd-radius-sm: 8px;--sd-radius: 10px;--sd-radius-lg: 14px;--sd-radius-pill: 999px;--sd-shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);--sd-shadow-md: 0 6px 16px rgba(16, 24, 40, .1);--sd-shadow-lg: 0 16px 40px rgba(16, 24, 40, .14);--sd-accent: var(--app-color, #ff6633);--sd-accent-strong: var(--app-color-dark, #ff5805);--sd-accent-soft: #fff1ea;--sd-accent-contrast: #ffffff;--sd-call-accept: #1aa251;--sd-call-end: #e5484d;--sd-surface: var(--background-color, #ffffff);--sd-surface-muted: var(--background-color-dark, #f7f7f7);--sd-surface-sunken: var(--background-color-dark-light, #e8e8e8);--sd-text: var(--header-text-primary, #333333);--sd-text-muted: var(--header-text-secondary, #5f6368);--sd-text-subtle: var(--header-text-muted, #9ca3af);--sd-border: var(--dropdown-border, #e3e3e3);--sd-border-strong: var(--border-color, #c9c9c9);--sd-card: var(--background-color, #ffffff);--sd-avatar: #eceff3;--sd-input: var(--background-color, #ffffff);--sd-input-border: var(--border-color, #c9c9c9);--sd-focus-ring: 0 0 0 3px rgba(255, 102, 51, .22)}:host.avaya-ipo-dark-mode{--sd-accent: #ff7a4d;--sd-accent-strong: #ff6633;--sd-accent-soft: rgba(255, 122, 77, .14);--sd-accent-contrast: #1a1109;--sd-call-accept: #34c759;--sd-call-end: #ff5b5b;--sd-surface: #0f1115;--sd-surface-muted: #151a22;--sd-surface-sunken: #1c222c;--sd-text: #f2f4f8;--sd-text-muted: #aab0bb;--sd-text-subtle: #7e8794;--sd-border: #2a2f3a;--sd-border-strong: #353b47;--sd-card: #161b24;--sd-avatar: #222833;--sd-input: #1c222c;--sd-input-border: #2a2f3a;--sd-focus-ring: 0 0 0 3px rgba(255, 122, 77, .25)}:host.avaya-ipo-mode-popup{min-width:320px;height:100%}:host.avaya-ipo-mode-standalone{width:100%;max-width:460px;height:100dvh;min-height:100dvh;margin-inline:auto;border-inline:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);overflow:hidden}@media (max-width: 768px){:host.avaya-ipo-mode-standalone{max-width:100%;border-inline:0;box-shadow:none}}.avaya-ipo-container_connection_status_overlay{width:100%;position:relative;background-color:#7f7f7f1a;padding:10px;box-sizing:border-box}.avaya-ipo-container_connection_status{width:100%;background:var(--sd-card);padding:8px 10px;border-radius:var(--sd-radius-sm);font-size:13px;font-weight:600;color:var(--sd-text-muted);display:flex;gap:8px;align-items:center;box-shadow:var(--sd-shadow-md)}.avaya-ipo-container_connection_status .fa-circle-dot{color:var(--sd-accent)}.avaya-ipo-simple-placeholder{padding:20px;text-align:center;color:var(--sd-text);font-weight:600}.avaya-ipo-auth-error-screen,.avaya-ipo-auth-loading-screen{min-height:100%;flex:1 1 auto;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box;background:var(--sd-surface)}.avaya-ipo-auth-loading-card{width:min(320px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center;align-items:center}.avaya-ipo-auth-loading-title{font-size:16px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-loading-message{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-card{width:min(360px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center}.avaya-ipo-auth-error-icon{width:56px;height:56px;margin:0 auto 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sd-radius-lg);background:var(--sd-accent);color:var(--sd-accent-contrast)}.avaya-ipo-auth-error-icon svg{width:28px;height:28px}.avaya-ipo-auth-error-title{font-size:18px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-error-message{font-size:13px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-hint{font-size:12px;color:var(--sd-text-subtle)}.avaya-ipo-media-elements{display:none}.avaya-ipo-widget-body{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;position:relative;height:100%;padding-bottom:0;overflow-y:auto;-webkit-overflow-scrolling:touch}.avaya-ipo-logout-btn{border:none;background:var(--sd-call-end);color:#fff;padding:8px 12px;border-radius:var(--sd-radius-sm);cursor:pointer;font-weight:600}.avaya-ipo-logout-btn:hover{filter:brightness(.94)}.avaya-ipo-widget-content{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:1rem;padding-bottom:0;height:100%}.avaya-ipo-page-heading{display:flex;align-items:center;justify-content:space-between;font-size:22px;font-weight:800;color:var(--sd-text);padding:15px;z-index:5;background:var(--sd-surface)}.avaya-ipo-settings-btn{width:34px;height:34px;border-radius:var(--sd-radius-sm);border:none;background:transparent;color:var(--sd-text-muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}.avaya-ipo-settings-btn:hover{background:var(--sd-surface-muted)}.avaya-ipo-settings-btn.avaya-ipo-is-active{color:var(--sd-accent);background:var(--sd-accent-soft)}.avaya-ipo-settings-btn:disabled{cursor:default;opacity:.75}.avaya-ipo-settings-btn-floating{position:absolute;top:8px;right:8px;z-index:6}.avaya-ipo-heading-with-back{display:inline-flex;align-items:center;gap:4px}.avaya-ipo-settings-btn.avaya-ipo-back-btn{color:var(--sd-text)}.avaya-ipo-tabs{position:sticky;bottom:0;left:0;right:0;display:flex;gap:6px;padding:8px 12px;background:var(--sd-surface-muted);border-top:1px solid var(--sd-border);box-sizing:border-box;z-index:10;height:var(--sd-tabs-height)}.avaya-ipo-tab-btn{flex:1 1 0;height:44px;border:none;background:transparent;font-weight:600;color:var(--sd-text-muted);border-radius:var(--sd-radius-sm);cursor:pointer;transition:background .12s ease,color .12s ease;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:12px;box-shadow:none}.avaya-ipo-tab-btn:hover{color:var(--sd-text)}.avaya-ipo-tab-btn.avaya-ipo-active{background:var(--sd-accent-soft);color:var(--sd-accent);box-shadow:none}.avaya-ipo-tab-icon{display:flex;align-items:center;justify-content:center;font-size:16px}.avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}.avaya-ipo-global-loader{position:absolute;inset:0;background:color-mix(in srgb,var(--sd-surface) 85%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;z-index:1000;color:var(--sd-text);font-weight:700}.avaya-ipo-spinner{width:48px;height:48px;border:4px solid var(--sd-surface-sunken);border-top-color:var(--sd-accent);border-radius:50%;animation:spin .9s linear infinite}.avaya-ipo-loader-text{font-size:14px}@keyframes spin{to{transform:rotate(360deg)}}:host ::ng-deep .avaya-ipo-widget-body,:host ::ng-deep .avaya-ipo-widget-content{background:var(--sd-surface);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-page-heading{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-settings-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tabs{background:var(--sd-surface-muted);border-top-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-tab-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active{color:var(--sd-accent);background:var(--sd-accent-soft)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}:host ::ng-deep .avaya-ipo-history_item,:host ::ng-deep .avaya-ipo-contact-card{border-bottom-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-history_avatar,:host ::ng-deep .avaya-ipo-skeleton_avatar,:host ::ng-deep .avaya-ipo-contact-avatar{background:var(--sd-avatar);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_name,:host ::ng-deep .avaya-ipo-contact-name{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_time,:host ::ng-deep .avaya-ipo-history_meta,:host ::ng-deep .avaya-ipo-history_group_label,:host ::ng-deep .avaya-ipo-contact-phone,:host ::ng-deep .avaya-ipo-contacts-state{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_group_label{background:#151a22eb}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_item:hover{background:#1a202b}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input{background:var(--sd-input);border-color:var(--sd-input-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input::placeholder{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call{background:#1e2b22;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-back{background:#141922;border-color:var(--sd-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call-btn{background:#1f2530;border-color:#1f2530;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-global-loader{background:#0f1115e6;color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-spinner{border-color:#2a2f3a;border-top-color:var(--sd-accent)}.avaya-ipo-widget-version-footer{flex:0 0 auto;padding:2px 8px 4px;text-align:center;font-size:10px;line-height:1.2;letter-spacing:.02em;color:var(--sd-text-muted);background:var(--sd-surface);border-top:1px solid var(--sd-border);-webkit-user-select:text;user-select:text}\n"], dependencies: [{ kind: "component", type: CallHistoryComponent, selector: "app-call-history", inputs: ["mode", "tenantId", "agentId"], outputs: ["makeCallEv", "transferEv"] }, { kind: "component", type: ContactsComponent, selector: "app-contacts", inputs: ["tenantId"], outputs: ["makeCallEv"] }, { kind: "component", type: SettingsComponent, selector: "app-settings", inputs: ["selectedAudioInputId", "selectedAudioOutputId", "extensionId", "darkMode"], outputs: ["change", "darkModeChange", "logout"] }, { kind: "component", type: AvayaIpoLoginComponent, selector: "app-avaya-ipo-login", inputs: ["loginForm", "showLoginLoader", "hasAvayaSocketError", "hasAvayaLoginError", "hasAvayaLoginFailedGeneral", "hasAvayaLoginConflictError", "hasAvayaDeviceError"], outputs: ["login"] }, { kind: "component", type: PhoneComponent, selector: "app-phone", inputs: ["contacts", "tenantId", "agentId", "isActiveCall", "activeCallNumber", "incomingCallName", "incomingNameResolved", "activeCallName", "serverIp", "serverPort", "stunIp", "stunPort", "turnIp", "turnPort", "configurationMode", "recordingUploadMode", "entityId"], outputs: ["callScreenChange", "makeCallEv", "endCallEv"] }] });
4997
5356
  }
4998
5357
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AvayaIPOWidgetComponent, decorators: [{
4999
5358
  type: Component,
5000
- args: [{ selector: 'snugdesk-avaya-ipo-widget', standalone: false, template: "<div class=\"avaya-ipo-media-elements\">\n <audio id=\"rmtAudio\" autoplay></audio>\n <audio id=\"lclAudio\" autoplay></audio>\n <video id=\"rmtVideo\" autoplay playsinline></video>\n <video id=\"lclVideo\" autoplay playsinline muted></video>\n</div>\n\n@if (authLoading) {\n <div class=\"avaya-ipo-auth-loading-screen\">\n <div class=\"avaya-ipo-auth-loading-card\">\n <div class=\"avaya-ipo-spinner\" aria-hidden=\"true\"></div>\n <div class=\"avaya-ipo-auth-loading-title\">Checking authentication</div>\n <div class=\"avaya-ipo-auth-loading-message\">Please wait...</div>\n </div>\n </div>\n} @else if (authErrorMessage) {\n <div class=\"avaya-ipo-auth-error-screen\">\n <div class=\"avaya-ipo-auth-error-card\">\n <div class=\"avaya-ipo-auth-error-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M12 2a7 7 0 0 1 7 7v3a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2V9a7 7 0 0 1 7-7zm5 10V9a5 5 0 0 0-10 0v3h10zm-5 3a2 2 0 0 0-1 3.732V20h2v-1.268A2 2 0 0 0 12 15z\"\n />\n </svg>\n </div>\n <div class=\"avaya-ipo-auth-error-title\">Authentication Required</div>\n <div class=\"avaya-ipo-auth-error-message\">{{ authErrorMessage }}</div>\n </div>\n </div>\n} @else {\n@if (isReconnectingInProgress || isFailoverInProgress || isFailbackInProgress) {\n <div class=\"avaya-ipo-container_connection_status_overlay\">\n <div class=\"avaya-ipo-container_connection_status\">\n <i class=\"fa-solid fa-circle-dot\"></i>\n @if (isReconnectingInProgress) { <span>Reconnecting to the server...</span> }\n @if (isFailoverInProgress) { <span>Failover in progress...</span> }\n @if (isFailbackInProgress) { <span>Failback in progress...</span> }\n </div>\n </div>\n}\n\n@if (showLoginForm) {\n <app-avaya-ipo-login\n [loginForm]=\"loginForm\"\n [showLoginLoader]=\"showLoginLoader\"\n [hasAvayaSocketError]=\"hasAvayaSocketError\"\n [hasAvayaLoginError]=\"hasAvayaLoginError\"\n [hasAvayaLoginFailedGeneral]=\"hasAvayaLoginFailedGeneral\"\n [hasAvayaLoginConflictError]=\"hasAvayaLoginConflictError\"\n [hasAvayaDeviceError]=\"hasAvayaDeviceError\"\n (login)=\"onLogin()\"\n ></app-avaya-ipo-login>\n} @else {\n <div class=\"avaya-ipo-widget-body\">\n <div class=\"avaya-ipo-widget-content\">\n @if (activeTab === 'history') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading avaya-ipo-heading-right\">\n <span>History</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-call-history\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n (makeCallEv)=\"onHistoryMakeCall($event)\"\n ></app-call-history>\n } @else if (activeTab === 'contacts') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span>Contacts</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-contacts [tenantId]=\"tenantId\" (makeCallEv)=\"onContactsMakeCall($event)\"></app-contacts>\n } @else if (activeTab === 'settings') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span class=\"avaya-ipo-heading-with-back\">\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-back-btn\" (click)=\"closeSettings()\" aria-label=\"Go back\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n </button>\n <span>Settings</span>\n </span>\n </div>\n }\n <app-settings\n [extensionId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [darkMode]=\"darkModeEnabled\"\n (darkModeChange)=\"onThemeToggle($event)\"\n (change)=\"onDeviceChange($event)\"\n (logout)=\"onLogout()\"\n ></app-settings>\n } @else {\n @if (!hideTabs) {\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-settings-btn-floating\" (click)=\"selectTab('settings')\" aria-label=\"Settings\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n }\n <app-phone\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [activeCallNumber]=\"activeCallNumber\"\n [incomingCallName]=\"incomingCallName\"\n [incomingNameResolved]=\"incomingNameResolved\"\n [activeCallName]=\"activeCallName\"\n [serverIp]=\"avayaIPOServerIP\"\n [serverPort]=\"avayaIPOServerPort\"\n [stunIp]=\"avayaIPOServerStunServerIP\"\n [stunPort]=\"avayaIPOServerStunServerPort\"\n [turnIp]=\"avayaIPOServerTurnServerIP\"\n [turnPort]=\"avayaIPOServerTurnServerPort\"\n [configurationMode]=\"configurationMode\"\n (makeCallEv)=\"onPhoneMakeCall($event)\"\n (endCallEv)=\"onPhoneEndCall()\"\n (callScreenChange)=\"onCallScreenChange($event)\"\n ></app-phone>\n }\n </div>\n </div>\n\n @if (showLoginLoader) {\n <div class=\"avaya-ipo-global-loader\">\n <div class=\"avaya-ipo-spinner\"></div>\n <div class=\"avaya-ipo-loader-text\">Connecting to phone service...</div>\n </div>\n }\n\n @if (!hideTabs && showTabBar) {\n <nav class=\"avaya-ipo-tabs\">\n @if (showHistory) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'history'\" (click)=\"selectTab('history')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"19px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M464 256A208 208 0 1 1 48 256a208 208 0 1 1 416 0zM0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120l0 136c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2 280 120c0-13.3-10.7-24-24-24s-24 10.7-24 24z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">History</span>\n </button>\n }\n @if (showContacts) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'contacts'\" (click)=\"selectTab('contacts')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"18px\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M12 12a4 4 0 1 0-4-4 4 4 0 0 0 4 4zm0 2c-4.4 0-8 2.2-8 5v2h16v-2c0-2.8-3.6-5-8-5z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Contacts</span>\n </button>\n }\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'keypad'\" (click)=\"selectTab('keypad')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"20px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\" d=\"M256,400a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Keypad</span>\n </button>\n </nav>\n }\n\n @if (activeTab !== 'keypad') {\n <div class=\"avaya-ipo-widget-version-footer\">v{{ widgetVersion }}</div>\n }\n}\n}\n", styles: [":host{display:flex;flex-direction:column;width:100%;max-width:100%;margin:0;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;min-height:100%;height:100%;background:var(--sd-surface);color:var(--sd-text);box-sizing:border-box;--sd-tabs-height: 60px;--sd-radius-sm: 8px;--sd-radius: 10px;--sd-radius-lg: 14px;--sd-radius-pill: 999px;--sd-shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);--sd-shadow-md: 0 6px 16px rgba(16, 24, 40, .1);--sd-shadow-lg: 0 16px 40px rgba(16, 24, 40, .14);--sd-accent: var(--app-color, #ff6633);--sd-accent-strong: var(--app-color-dark, #ff5805);--sd-accent-soft: #fff1ea;--sd-accent-contrast: #ffffff;--sd-call-accept: #1aa251;--sd-call-end: #e5484d;--sd-surface: var(--background-color, #ffffff);--sd-surface-muted: var(--background-color-dark, #f7f7f7);--sd-surface-sunken: var(--background-color-dark-light, #e8e8e8);--sd-text: var(--header-text-primary, #333333);--sd-text-muted: var(--header-text-secondary, #5f6368);--sd-text-subtle: var(--header-text-muted, #9ca3af);--sd-border: var(--dropdown-border, #e3e3e3);--sd-border-strong: var(--border-color, #c9c9c9);--sd-card: var(--background-color, #ffffff);--sd-avatar: #eceff3;--sd-input: var(--background-color, #ffffff);--sd-input-border: var(--border-color, #c9c9c9);--sd-focus-ring: 0 0 0 3px rgba(255, 102, 51, .22)}:host.avaya-ipo-dark-mode{--sd-accent: #ff7a4d;--sd-accent-strong: #ff6633;--sd-accent-soft: rgba(255, 122, 77, .14);--sd-accent-contrast: #1a1109;--sd-call-accept: #34c759;--sd-call-end: #ff5b5b;--sd-surface: #0f1115;--sd-surface-muted: #151a22;--sd-surface-sunken: #1c222c;--sd-text: #f2f4f8;--sd-text-muted: #aab0bb;--sd-text-subtle: #7e8794;--sd-border: #2a2f3a;--sd-border-strong: #353b47;--sd-card: #161b24;--sd-avatar: #222833;--sd-input: #1c222c;--sd-input-border: #2a2f3a;--sd-focus-ring: 0 0 0 3px rgba(255, 122, 77, .25)}:host.avaya-ipo-mode-popup{min-width:320px;height:100%}:host.avaya-ipo-mode-standalone{width:100%;max-width:460px;height:100dvh;min-height:100dvh;margin-inline:auto;border-inline:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);overflow:hidden}@media (max-width: 768px){:host.avaya-ipo-mode-standalone{max-width:100%;border-inline:0;box-shadow:none}}.avaya-ipo-container_connection_status_overlay{width:100%;position:relative;background-color:#7f7f7f1a;padding:10px;box-sizing:border-box}.avaya-ipo-container_connection_status{width:100%;background:var(--sd-card);padding:8px 10px;border-radius:var(--sd-radius-sm);font-size:13px;font-weight:600;color:var(--sd-text-muted);display:flex;gap:8px;align-items:center;box-shadow:var(--sd-shadow-md)}.avaya-ipo-container_connection_status .fa-circle-dot{color:var(--sd-accent)}.avaya-ipo-simple-placeholder{padding:20px;text-align:center;color:var(--sd-text);font-weight:600}.avaya-ipo-auth-error-screen,.avaya-ipo-auth-loading-screen{min-height:100%;flex:1 1 auto;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box;background:var(--sd-surface)}.avaya-ipo-auth-loading-card{width:min(320px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center;align-items:center}.avaya-ipo-auth-loading-title{font-size:16px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-loading-message{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-card{width:min(360px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center}.avaya-ipo-auth-error-icon{width:56px;height:56px;margin:0 auto 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sd-radius-lg);background:var(--sd-accent);color:var(--sd-accent-contrast)}.avaya-ipo-auth-error-icon svg{width:28px;height:28px}.avaya-ipo-auth-error-title{font-size:18px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-error-message{font-size:13px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-hint{font-size:12px;color:var(--sd-text-subtle)}.avaya-ipo-media-elements{display:none}.avaya-ipo-widget-body{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;position:relative;height:100%;padding-bottom:0;overflow-y:auto;-webkit-overflow-scrolling:touch}.avaya-ipo-logout-btn{border:none;background:var(--sd-call-end);color:#fff;padding:8px 12px;border-radius:var(--sd-radius-sm);cursor:pointer;font-weight:600}.avaya-ipo-logout-btn:hover{filter:brightness(.94)}.avaya-ipo-widget-content{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:1rem;padding-bottom:0;height:100%}.avaya-ipo-page-heading{display:flex;align-items:center;justify-content:space-between;font-size:22px;font-weight:800;color:var(--sd-text);padding:15px;z-index:5;background:var(--sd-surface)}.avaya-ipo-settings-btn{width:34px;height:34px;border-radius:var(--sd-radius-sm);border:none;background:transparent;color:var(--sd-text-muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}.avaya-ipo-settings-btn:hover{background:var(--sd-surface-muted)}.avaya-ipo-settings-btn.avaya-ipo-is-active{color:var(--sd-accent);background:var(--sd-accent-soft)}.avaya-ipo-settings-btn:disabled{cursor:default;opacity:.75}.avaya-ipo-settings-btn-floating{position:absolute;top:8px;right:8px;z-index:6}.avaya-ipo-heading-with-back{display:inline-flex;align-items:center;gap:4px}.avaya-ipo-settings-btn.avaya-ipo-back-btn{color:var(--sd-text)}.avaya-ipo-tabs{position:sticky;bottom:0;left:0;right:0;display:flex;gap:6px;padding:8px 12px;background:var(--sd-surface-muted);border-top:1px solid var(--sd-border);box-sizing:border-box;z-index:10;height:var(--sd-tabs-height)}.avaya-ipo-tab-btn{flex:1 1 0;height:44px;border:none;background:transparent;font-weight:600;color:var(--sd-text-muted);border-radius:var(--sd-radius-sm);cursor:pointer;transition:background .12s ease,color .12s ease;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:12px;box-shadow:none}.avaya-ipo-tab-btn:hover{color:var(--sd-text)}.avaya-ipo-tab-btn.avaya-ipo-active{background:var(--sd-accent-soft);color:var(--sd-accent);box-shadow:none}.avaya-ipo-tab-icon{display:flex;align-items:center;justify-content:center;font-size:16px}.avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}.avaya-ipo-global-loader{position:absolute;inset:0;background:color-mix(in srgb,var(--sd-surface) 85%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;z-index:1000;color:var(--sd-text);font-weight:700}.avaya-ipo-spinner{width:48px;height:48px;border:4px solid var(--sd-surface-sunken);border-top-color:var(--sd-accent);border-radius:50%;animation:spin .9s linear infinite}.avaya-ipo-loader-text{font-size:14px}@keyframes spin{to{transform:rotate(360deg)}}:host ::ng-deep .avaya-ipo-widget-body,:host ::ng-deep .avaya-ipo-widget-content{background:var(--sd-surface);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-page-heading{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-settings-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tabs{background:var(--sd-surface-muted);border-top-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-tab-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active{color:var(--sd-accent);background:var(--sd-accent-soft)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}:host ::ng-deep .avaya-ipo-history_item,:host ::ng-deep .avaya-ipo-contact-card{border-bottom-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-history_avatar,:host ::ng-deep .avaya-ipo-skeleton_avatar,:host ::ng-deep .avaya-ipo-contact-avatar{background:var(--sd-avatar);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_name,:host ::ng-deep .avaya-ipo-contact-name{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_time,:host ::ng-deep .avaya-ipo-history_meta,:host ::ng-deep .avaya-ipo-history_group_label,:host ::ng-deep .avaya-ipo-contact-phone,:host ::ng-deep .avaya-ipo-contacts-state{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_group_label{background:#151a22eb}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_item:hover{background:#1a202b}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input{background:var(--sd-input);border-color:var(--sd-input-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input::placeholder{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call{background:#1e2b22;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-back{background:#141922;border-color:var(--sd-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call-btn{background:#1f2530;border-color:#1f2530;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-global-loader{background:#0f1115e6;color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-spinner{border-color:#2a2f3a;border-top-color:var(--sd-accent)}.avaya-ipo-widget-version-footer{flex:0 0 auto;padding:2px 8px 4px;text-align:center;font-size:10px;line-height:1.2;letter-spacing:.02em;color:var(--sd-text-muted);background:var(--sd-surface);border-top:1px solid var(--sd-border);-webkit-user-select:text;user-select:text}\n"] }]
5359
+ args: [{ selector: 'snugdesk-avaya-ipo-widget', standalone: false, template: "<div class=\"avaya-ipo-media-elements\">\n <audio id=\"rmtAudio\" autoplay></audio>\n <audio id=\"lclAudio\" autoplay></audio>\n <video id=\"rmtVideo\" autoplay playsinline></video>\n <video id=\"lclVideo\" autoplay playsinline muted></video>\n</div>\n\n@if (authLoading) {\n <div class=\"avaya-ipo-auth-loading-screen\">\n <div class=\"avaya-ipo-auth-loading-card\">\n <div class=\"avaya-ipo-spinner\" aria-hidden=\"true\"></div>\n <div class=\"avaya-ipo-auth-loading-title\">Checking authentication</div>\n <div class=\"avaya-ipo-auth-loading-message\">Please wait...</div>\n </div>\n </div>\n} @else if (authErrorMessage) {\n <div class=\"avaya-ipo-auth-error-screen\">\n <div class=\"avaya-ipo-auth-error-card\">\n <div class=\"avaya-ipo-auth-error-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" focusable=\"false\">\n <path\n fill=\"currentColor\"\n d=\"M12 2a7 7 0 0 1 7 7v3a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2V9a7 7 0 0 1 7-7zm5 10V9a5 5 0 0 0-10 0v3h10zm-5 3a2 2 0 0 0-1 3.732V20h2v-1.268A2 2 0 0 0 12 15z\"\n />\n </svg>\n </div>\n <div class=\"avaya-ipo-auth-error-title\">Authentication Required</div>\n <div class=\"avaya-ipo-auth-error-message\">{{ authErrorMessage }}</div>\n </div>\n </div>\n} @else {\n@if (isReconnectingInProgress || isFailoverInProgress || isFailbackInProgress) {\n <div class=\"avaya-ipo-container_connection_status_overlay\">\n <div class=\"avaya-ipo-container_connection_status\">\n <i class=\"fa-solid fa-circle-dot\"></i>\n @if (isReconnectingInProgress) { <span>Reconnecting to the server...</span> }\n @if (isFailoverInProgress) { <span>Failover in progress...</span> }\n @if (isFailbackInProgress) { <span>Failback in progress...</span> }\n </div>\n </div>\n}\n\n@if (showLoginForm) {\n <app-avaya-ipo-login\n [loginForm]=\"loginForm\"\n [showLoginLoader]=\"showLoginLoader\"\n [hasAvayaSocketError]=\"hasAvayaSocketError\"\n [hasAvayaLoginError]=\"hasAvayaLoginError\"\n [hasAvayaLoginFailedGeneral]=\"hasAvayaLoginFailedGeneral\"\n [hasAvayaLoginConflictError]=\"hasAvayaLoginConflictError\"\n [hasAvayaDeviceError]=\"hasAvayaDeviceError\"\n (login)=\"onLogin()\"\n ></app-avaya-ipo-login>\n} @else {\n <div class=\"avaya-ipo-widget-body\">\n <div class=\"avaya-ipo-widget-content\">\n @if (activeTab === 'history') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading avaya-ipo-heading-right\">\n <span>History</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-call-history\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n (makeCallEv)=\"onHistoryMakeCall($event)\"\n ></app-call-history>\n } @else if (activeTab === 'contacts') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span>Contacts</span>\n <button type=\"button\" class=\"avaya-ipo-settings-btn\" (click)=\"selectTab('settings')\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n </div>\n }\n <app-contacts [tenantId]=\"tenantId\" (makeCallEv)=\"onContactsMakeCall($event)\"></app-contacts>\n } @else if (activeTab === 'settings') {\n @if (!hideTabs) {\n <div class=\"avaya-ipo-page-heading\">\n <span class=\"avaya-ipo-heading-with-back\">\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-back-btn\" (click)=\"closeSettings()\" aria-label=\"Go back\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n </button>\n <span>Settings</span>\n </span>\n </div>\n }\n <app-settings\n [extensionId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [darkMode]=\"darkModeEnabled\"\n (darkModeChange)=\"onThemeToggle($event)\"\n (change)=\"onDeviceChange($event)\"\n (logout)=\"onLogout()\"\n ></app-settings>\n } @else {\n @if (!hideTabs) {\n <button type=\"button\" class=\"avaya-ipo-settings-btn avaya-ipo-settings-btn-floating\" (click)=\"selectTab('settings')\" aria-label=\"Settings\">\n <svg width=\"18px\" viewBox=\"-0.03 0 16.079 16.079\" aria-hidden=\"true\" focusable=\"false\">\n <g>\n <path fill=\"currentColor\"\n d=\"M8.182 1.083a6.99 6.99 0 0 0-6.248 3.493c-1.929 3.342-.776 7.629 2.57 9.562 3.346 1.934 7.634.792 9.562-2.55 1.929-3.343.776-7.634-2.57-9.567a6.98 6.98 0 0 0-3.314-.938zM8 2.08a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6z\" />\n <path fill=\"currentColor\"\n d=\"M9.322 0L6.69.393v1.354a6.49 6.477 43.146 0 1 2.632.005V0zM3.937 1.19L1.93 2.897l.988 1.177a6.49 6.477 43.146 0 1 2.017-1.69zm8.128.013l-.993 1.184a6.49 6.477 43.146 0 1 .17.09 6.49 6.477 43.146 0 1 1.845 1.603l1.006-1.197zM.455 5.42l-.44 2.596 1.515.267a6.49 6.477 43.146 0 1 .455-2.593zm15.086.003l-1.523.269a6.49 6.477 43.146 0 1 .464 2.59l1.533-.27zM1.858 10.118l-1.351.78 1.33 2.271 1.339-.772a6.49 6.477 43.146 0 1-1.317-2.28zm12.301.003a6.49 6.477 43.146 0 1-.534 1.215 6.49 6.477 43.146 0 1-.774 1.069l1.338.773 1.302-2.288zm-9.557 3.471l-.534 1.47 2.48.884.525-1.446a6.49 6.477 43.146 0 1-2.303-.8 6.49 6.477 43.146 0 1-.168-.108zm6.814.016a6.49 6.477 43.146 0 1-2.475.897l.53 1.457 2.468-.917z\" />\n <path fill=\"currentColor\"\n d=\"M7.648 3.093a4.989 4.989 0 0 0-3.982 2.483 5.013 5.013 0 0 0 1.836 6.834 5.002 5.002 0 0 0 6.83-1.827 5.01 5.01 0 0 0-1.836-6.832 4.976 4.976 0 0 0-2.848-.658zM8 4.08a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4z\" />\n </g>\n </svg>\n </button>\n }\n <app-phone\n [tenantId]=\"tenantId\"\n [agentId]=\"loginForm?.value?.ipoExtensionNo || userId\"\n [activeCallNumber]=\"activeCallNumber\"\n [incomingCallName]=\"incomingCallName\"\n [incomingNameResolved]=\"incomingNameResolved\"\n [activeCallName]=\"activeCallName\"\n [serverIp]=\"avayaIPOServerIP\"\n [serverPort]=\"avayaIPOServerPort\"\n [stunIp]=\"avayaIPOServerStunServerIP\"\n [stunPort]=\"avayaIPOServerStunServerPort\"\n [turnIp]=\"avayaIPOServerTurnServerIP\"\n [turnPort]=\"avayaIPOServerTurnServerPort\"\n [configurationMode]=\"configurationMode\"\n [recordingUploadMode]=\"recordingUploadMode\"\n [entityId]=\"activeCallEntityId\"\n (makeCallEv)=\"onPhoneMakeCall($event)\"\n (endCallEv)=\"onPhoneEndCall()\"\n (callScreenChange)=\"onCallScreenChange($event)\"\n ></app-phone>\n }\n </div>\n </div>\n\n @if (showLoginLoader) {\n <div class=\"avaya-ipo-global-loader\">\n <div class=\"avaya-ipo-spinner\"></div>\n <div class=\"avaya-ipo-loader-text\">Connecting to phone service...</div>\n </div>\n }\n\n @if (!hideTabs && showTabBar) {\n <nav class=\"avaya-ipo-tabs\">\n @if (showHistory) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'history'\" (click)=\"selectTab('history')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"19px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M464 256A208 208 0 1 1 48 256a208 208 0 1 1 416 0zM0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120l0 136c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2 280 120c0-13.3-10.7-24-24-24s-24 10.7-24 24z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">History</span>\n </button>\n }\n @if (showContacts) {\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'contacts'\" (click)=\"selectTab('contacts')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"18px\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\"\n d=\"M12 12a4 4 0 1 0-4-4 4 4 0 0 0 4 4zm0 2c-4.4 0-8 2.2-8 5v2h16v-2c0-2.8-3.6-5-8-5z\" />\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Contacts</span>\n </button>\n }\n <button type=\"button\" class=\"avaya-ipo-tab-btn\" [class.avaya-ipo-active]=\"activeTab === 'keypad'\" (click)=\"selectTab('keypad')\">\n <span class=\"avaya-ipo-tab-icon\">\n <svg width=\"20px\" viewBox=\"0 0 512 512\" aria-hidden=\"true\" focusable=\"false\">\n <path fill=\"currentColor\" d=\"M256,400a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M256,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M384,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,272a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,144a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n <path fill=\"currentColor\" d=\"M128,16a48,48,0,1,0,48,48,48,48,0,0,0-48-48Z\"></path>\n </svg>\n </span>\n <span class=\"avaya-ipo-tab-text\">Keypad</span>\n </button>\n </nav>\n }\n\n @if (activeTab !== 'keypad') {\n <div class=\"avaya-ipo-widget-version-footer\">v{{ widgetVersion }}</div>\n }\n}\n}\n", styles: [":host{display:flex;flex-direction:column;width:100%;max-width:100%;margin:0;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;min-height:100%;height:100%;background:var(--sd-surface);color:var(--sd-text);box-sizing:border-box;--sd-tabs-height: 60px;--sd-radius-sm: 8px;--sd-radius: 10px;--sd-radius-lg: 14px;--sd-radius-pill: 999px;--sd-shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);--sd-shadow-md: 0 6px 16px rgba(16, 24, 40, .1);--sd-shadow-lg: 0 16px 40px rgba(16, 24, 40, .14);--sd-accent: var(--app-color, #ff6633);--sd-accent-strong: var(--app-color-dark, #ff5805);--sd-accent-soft: #fff1ea;--sd-accent-contrast: #ffffff;--sd-call-accept: #1aa251;--sd-call-end: #e5484d;--sd-surface: var(--background-color, #ffffff);--sd-surface-muted: var(--background-color-dark, #f7f7f7);--sd-surface-sunken: var(--background-color-dark-light, #e8e8e8);--sd-text: var(--header-text-primary, #333333);--sd-text-muted: var(--header-text-secondary, #5f6368);--sd-text-subtle: var(--header-text-muted, #9ca3af);--sd-border: var(--dropdown-border, #e3e3e3);--sd-border-strong: var(--border-color, #c9c9c9);--sd-card: var(--background-color, #ffffff);--sd-avatar: #eceff3;--sd-input: var(--background-color, #ffffff);--sd-input-border: var(--border-color, #c9c9c9);--sd-focus-ring: 0 0 0 3px rgba(255, 102, 51, .22)}:host.avaya-ipo-dark-mode{--sd-accent: #ff7a4d;--sd-accent-strong: #ff6633;--sd-accent-soft: rgba(255, 122, 77, .14);--sd-accent-contrast: #1a1109;--sd-call-accept: #34c759;--sd-call-end: #ff5b5b;--sd-surface: #0f1115;--sd-surface-muted: #151a22;--sd-surface-sunken: #1c222c;--sd-text: #f2f4f8;--sd-text-muted: #aab0bb;--sd-text-subtle: #7e8794;--sd-border: #2a2f3a;--sd-border-strong: #353b47;--sd-card: #161b24;--sd-avatar: #222833;--sd-input: #1c222c;--sd-input-border: #2a2f3a;--sd-focus-ring: 0 0 0 3px rgba(255, 122, 77, .25)}:host.avaya-ipo-mode-popup{min-width:320px;height:100%}:host.avaya-ipo-mode-standalone{width:100%;max-width:460px;height:100dvh;min-height:100dvh;margin-inline:auto;border-inline:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);overflow:hidden}@media (max-width: 768px){:host.avaya-ipo-mode-standalone{max-width:100%;border-inline:0;box-shadow:none}}.avaya-ipo-container_connection_status_overlay{width:100%;position:relative;background-color:#7f7f7f1a;padding:10px;box-sizing:border-box}.avaya-ipo-container_connection_status{width:100%;background:var(--sd-card);padding:8px 10px;border-radius:var(--sd-radius-sm);font-size:13px;font-weight:600;color:var(--sd-text-muted);display:flex;gap:8px;align-items:center;box-shadow:var(--sd-shadow-md)}.avaya-ipo-container_connection_status .fa-circle-dot{color:var(--sd-accent)}.avaya-ipo-simple-placeholder{padding:20px;text-align:center;color:var(--sd-text);font-weight:600}.avaya-ipo-auth-error-screen,.avaya-ipo-auth-loading-screen{min-height:100%;flex:1 1 auto;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box;background:var(--sd-surface)}.avaya-ipo-auth-loading-card{width:min(320px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center;align-items:center}.avaya-ipo-auth-loading-title{font-size:16px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-loading-message{font-size:12px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-card{width:min(360px,100%);padding:24px;border-radius:var(--sd-radius-lg);background:var(--sd-card);border:1px solid var(--sd-border);box-shadow:var(--sd-shadow-lg);display:flex;flex-direction:column;gap:10px;text-align:center}.avaya-ipo-auth-error-icon{width:56px;height:56px;margin:0 auto 4px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sd-radius-lg);background:var(--sd-accent);color:var(--sd-accent-contrast)}.avaya-ipo-auth-error-icon svg{width:28px;height:28px}.avaya-ipo-auth-error-title{font-size:18px;font-weight:800;color:var(--sd-text)}.avaya-ipo-auth-error-message{font-size:13px;color:var(--sd-text-muted)}.avaya-ipo-auth-error-hint{font-size:12px;color:var(--sd-text-subtle)}.avaya-ipo-media-elements{display:none}.avaya-ipo-widget-body{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;position:relative;height:100%;padding-bottom:0;overflow-y:auto;-webkit-overflow-scrolling:touch}.avaya-ipo-logout-btn{border:none;background:var(--sd-call-end);color:#fff;padding:8px 12px;border-radius:var(--sd-radius-sm);cursor:pointer;font-weight:600}.avaya-ipo-logout-btn:hover{filter:brightness(.94)}.avaya-ipo-widget-content{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:1rem;padding-bottom:0;height:100%}.avaya-ipo-page-heading{display:flex;align-items:center;justify-content:space-between;font-size:22px;font-weight:800;color:var(--sd-text);padding:15px;z-index:5;background:var(--sd-surface)}.avaya-ipo-settings-btn{width:34px;height:34px;border-radius:var(--sd-radius-sm);border:none;background:transparent;color:var(--sd-text-muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}.avaya-ipo-settings-btn:hover{background:var(--sd-surface-muted)}.avaya-ipo-settings-btn.avaya-ipo-is-active{color:var(--sd-accent);background:var(--sd-accent-soft)}.avaya-ipo-settings-btn:disabled{cursor:default;opacity:.75}.avaya-ipo-settings-btn-floating{position:absolute;top:8px;right:8px;z-index:6}.avaya-ipo-heading-with-back{display:inline-flex;align-items:center;gap:4px}.avaya-ipo-settings-btn.avaya-ipo-back-btn{color:var(--sd-text)}.avaya-ipo-tabs{position:sticky;bottom:0;left:0;right:0;display:flex;gap:6px;padding:8px 12px;background:var(--sd-surface-muted);border-top:1px solid var(--sd-border);box-sizing:border-box;z-index:10;height:var(--sd-tabs-height)}.avaya-ipo-tab-btn{flex:1 1 0;height:44px;border:none;background:transparent;font-weight:600;color:var(--sd-text-muted);border-radius:var(--sd-radius-sm);cursor:pointer;transition:background .12s ease,color .12s ease;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:12px;box-shadow:none}.avaya-ipo-tab-btn:hover{color:var(--sd-text)}.avaya-ipo-tab-btn.avaya-ipo-active{background:var(--sd-accent-soft);color:var(--sd-accent);box-shadow:none}.avaya-ipo-tab-icon{display:flex;align-items:center;justify-content:center;font-size:16px}.avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}.avaya-ipo-global-loader{position:absolute;inset:0;background:color-mix(in srgb,var(--sd-surface) 85%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;z-index:1000;color:var(--sd-text);font-weight:700}.avaya-ipo-spinner{width:48px;height:48px;border:4px solid var(--sd-surface-sunken);border-top-color:var(--sd-accent);border-radius:50%;animation:spin .9s linear infinite}.avaya-ipo-loader-text{font-size:14px}@keyframes spin{to{transform:rotate(360deg)}}:host ::ng-deep .avaya-ipo-widget-body,:host ::ng-deep .avaya-ipo-widget-content{background:var(--sd-surface);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-page-heading{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-settings-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tabs{background:var(--sd-surface-muted);border-top-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-tab-btn{color:var(--sd-text-muted)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active{color:var(--sd-accent);background:var(--sd-accent-soft)}:host ::ng-deep .avaya-ipo-tab-btn.avaya-ipo-active .avaya-ipo-tab-icon{color:var(--sd-accent)}:host ::ng-deep .avaya-ipo-history_item,:host ::ng-deep .avaya-ipo-contact-card{border-bottom-color:var(--sd-border)}:host ::ng-deep .avaya-ipo-history_avatar,:host ::ng-deep .avaya-ipo-skeleton_avatar,:host ::ng-deep .avaya-ipo-contact-avatar{background:var(--sd-avatar);color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_name,:host ::ng-deep .avaya-ipo-contact-name{color:var(--sd-text)}:host ::ng-deep .avaya-ipo-history_time,:host ::ng-deep .avaya-ipo-history_meta,:host ::ng-deep .avaya-ipo-history_group_label,:host ::ng-deep .avaya-ipo-contact-phone,:host ::ng-deep .avaya-ipo-contacts-state{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_group_label{background:#151a22eb}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-history_item:hover{background:#1a202b}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input{background:var(--sd-input);border-color:var(--sd-input-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contacts-search input::placeholder{color:var(--sd-text-muted)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call{background:#1e2b22;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-back{background:#141922;border-color:var(--sd-border);color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-contact-call-btn{background:#1f2530;border-color:#1f2530;color:#79d48a}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-global-loader{background:#0f1115e6;color:var(--sd-text)}:host.avaya-ipo-dark-mode ::ng-deep .avaya-ipo-spinner{border-color:#2a2f3a;border-top-color:var(--sd-accent)}.avaya-ipo-widget-version-footer{flex:0 0 auto;padding:2px 8px 4px;text-align:center;font-size:10px;line-height:1.2;letter-spacing:.02em;color:var(--sd-text-muted);background:var(--sd-surface);border-top:1px solid var(--sd-border);-webkit-user-select:text;user-select:text}\n"] }]
5001
5360
  }], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: AvayaIPOService }, { type: i0.ChangeDetectorRef }, { type: CountryService }, { type: PhoneNumberLookupService }, { type: EntitiesSearchService }, { type: i1$1.SnugdeskAuthenticationService }], propDecorators: { hostDarkMode: [{
5002
5361
  type: HostBinding,
5003
5362
  args: ['class.avaya-ipo-dark-mode']
@@ -5013,6 +5372,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
5013
5372
  type: Input
5014
5373
  }], configurationMode: [{
5015
5374
  type: Input
5375
+ }], recordingUploadMode: [{
5376
+ type: Input
5016
5377
  }], avayaIPOServerIP: [{
5017
5378
  type: Input
5018
5379
  }], avayaIPOServerPort: [{